L
lingphi
Unregistered / Unconfirmed
GUEST, unregistred user!
[h4]下面是一个从winsocket编程规范中节选的例程,但是C语言用的,改造一下就能适合delphi.更详细的资料可以去这里下载:
http://www.lingphi.com
[/h4]
3.4 另一个精巧的应用程序实例-wshout
在本节中,我们通过一个经过精心选择的例子,进一步讨论一下Windows Sockets编程技术。例如如何编制客户机或服务器程序,如何应用TCP有连接服务(流式套接口)或UDP无连接服务(数据报套接口),如何进行阻塞或非阻塞方式的套接口操作等等,这些都是经常碰到的问题。接下来要介绍的wshout程序,可以通过灵活地设置不同选项来达到上述应用情况的任意组合,从而基本覆盖了应用Windows Sockets编程所可能碰到的问题,具有很好的研究参考价值。
由于该程序思路清晰,结构精良,所以我们不打算很详细地剖析每一个语句,而只是简要介绍一下整个程序的逻辑结构,并在源程序中加入适当的注释。我们相信,任何具有基本C语言和Windows编程经验的读者,都能很轻松地读懂绝大部分内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。
该程序在FTP公司的PCTCP支撑环境下调试通过,不过只要读者拥有任何符合Windows Sockets 1.1规范的实现,也能顺利执行该程序。
3.4.1 源程序目录
1. wshout.c wshout主程序
2. wshout.h wshout头文件
3. wshout.rc wshout资源文件
4. ushout.c UDP客户机程序
5. ulisten.c UDP服务器程序
6. tshout.c TCP客户机程序
7. tlisten.c TCP服务器程序
8. errno.c 获取WSAE*错误描述字符串程序
9. resolve.c 客户机/服务器启动程序
在编译本程序时,笔者用的是BC3.1,只需做一个PRJ工程文件,将上述.c文件及winsock.lib包括进来就行了。请注意winsock.h应在include目录或当前目录中,winsock.lib可利用winsock.dll通过implib工具来建立。如果读者使用其他的编译器,可自行作相应的调整,在此不再赘述。
3.4.2 程序逻辑结构
3.4.3 源程序清单及注释
3.4.3.1 wshout.c清单
/*
* 文件名: WSHOUT.C
*/
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "wshout.h"
#define MAJOR_VERSION 1
#define MINOR_VERSION 2
#define WSA_MAKEWORD(x,y) ( * 256 + (x)) /* HI:Minor, LO:Major */
HANDLE hInst; /* 进程实例句柄 */
HWND hOurWnd; /* 主窗口句柄 */
HWND hMainDlg; /* 主对话框句柄 */
int ret; /* 工作变量 */
char prbuf[PRBUF_LEN]; /* 用于显示文本的工作缓冲区 */
SOCKET sd; /* 用于监听连接的套接口描述字 */
long temporary_option = 0L; /* 缺省为阻塞模式 */
long blocking_option = 0L; /* 阻塞模式的全局标识 */
int run_cancelled = 0; /* 指示何时按下了取消按钮 */
int len = 1024; /* 一次写的字节数 */
BOOL running = FALSE; /* 程序的运行状态 */
const int iTCP = 1; /* 指定为TCP Shout */
const int iUDP = 2; /* 指定为UDP Shout */
int iProto = 1; /* 缺省为TCP Shout */
int iPortNo = SOCK_SHOUT;
int temporary_protocol = 1; /* 在Settings()中使用 */
int iShout = 1;
int iListen = 2;
int iClientOrServer = 1; /* 缺省为Shout(客户机) */
int tClientOrServer = 1; /* 在Settings()中使用 */
char HostModeBuf[20];/* 保存模式字符串 */
WORD VersionReqd;
LPWSADATA lpmyWSAData;
int PASCAL
WinMain (HANDLE hInstance,HANDLE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
HWND hWnd;
MSG msg;
BOOL InitApp(HANDLE);
if (!hPrevInstance)
if (!InitApp(hInstance))
return (NULL);
hInst = hInstance;
hWnd = CreateWindow("MainMenu",
"Windows Shout",
WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (NULL);
hOurWnd = hWnd;
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg); /* 翻译虚拟键码 */
DispatchMessage(&msg);
}
return (msg.wParam);
}
BOOL InitApp(HANDLE hInstance)
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);
pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
pWndClass->hIcon = LoadIcon(hInstance, (LPSTR) "SHOUT");
pWndClass->lpszMenuName = (LPSTR) "MainMenu";
pWndClass->lpszClassName = (LPSTR) "MainMenu";
pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
pWndClass->hInstance = hInstance;
pWndClass->style = NULL;
pWndClass->lpfnWndProc = ShoutWndProc;
bSuccess = RegisterClass(pWndClass);
LocalUnlock(hMemory);
LocalFree(hMemory);
return (bSuccess);
}
long FAR PASCAL ShoutWndProc(HWND hWnd, WORD message,WORD wParam, LONG lParam)
{
FARPROC lpDialogBoxProc;
switch (message){
case WM_CREATE:
/* Put up the dialog box */
lpDialogBoxProc = MakeProcInstance(DialogProc, hInst);
DialogBox (hInst, (LPSTR) "MainDialog", hWnd, lpDialogBoxProc) ;
FreeProcInstance(lpDialogBoxProc);
PostMessage(hWnd, WM_DESTROY, 0, 0L);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return NULL;
}
BOOL FAR PASCAL DialogProc(HWND hOurDlg, WORD message, WORD wParam, LONG lParam)
{
FARPROC lpProcAbout;
FARPROC lpProcSettings;
long lret;
WORD wMajorVersion, wMinorVersion;
char hostnm[64]; /* 包含主机名的工作缓冲区 */
switch (message) {
case WM_INITDIALOG:
/* 选择缺省主机 */
SetDlgItemText(hOurDlg, IDD_HNAME, "");
SendDlgItemMessage(hOurDlg, /* 对话框句柄 */
IDD_HNAME, /* 向何处发送msg */
EM_SETSEL, /* 选择字符 */
NULL, /* 附加信息 */
MAKELONG(0, 0x7fff)); /* 全部内容 */
SetFocus(GetDlgItem(hOurDlg, IDD_HNAME));
/* 初始化 */
hMainDlg = hOurDlg; /* 保存自己的窗口句柄 */
SetDlgItemText(hOurDlg, IDD_COHOST,"Shout to:");
wMajorVersion = MAJOR_VERSION;
wMinorVersion = MINOR_VERSION;
VersionReqd=WSA_MAKEWORD(wMajorVersion, wMinorVersion);
lpmyWSAData = (LPWSADATA)_calloc(1, sizeof(WSADATA));
ret = WSAStartup(VersionReqd, lpmyWSAData);
if (ret != 0){
wshout_err (hOurDlg, WSAGetLastError(), "WSAStartup()");
}
return (TRUE);
case WM_CLOSE:
PostMessage(hOurDlg, WM_COMMAND, IDM_EXIT, 0L);
break;
case WM_SYSCOMMAND:
SendMessage(hOurWnd, message, wParam, lParam);
break;
case WM_COMMAND:
switch (wParam) {
case IDD_CONNECT: /* 按下连接按钮 */
case IDM_START: /* 选择了Start菜单项 */
run_cancelled = FALSE;
/* 不能重入 */
if (running){
MessageBox(hOurWnd,"Shout is already running !",
"Shout", MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
return FALSE;
}
ClearBoxes(hOurDlg);
running = TRUE;
if (iClientOrServer == iShout) {
/* 确保有主机名 */
if (GetDlgItemText (hOurDlg, IDD_HNAME, hostnm, 80) < 2) {
MessageBeep(0);
SetDlgItemText(hOurDlg,
IDD_COMMENT,"No hostname specified");
running = FALSE;
break;
}
sd = ResolveAndConnectHost((char FAR *)hostnm,hOurDlg,iProto,
iPortNo);
if (sd == SOCKET_ERROR) {/* 无法创建套接口 */
running = FALSE;
break;
}
}
else {
sd = GetSocketAndBind(hOurDlg, iProto, iPortNo);
if (sd == SOCKET_ERROR) {
running = FALSE;
break;
}
}
/* Set the I/O mode of the socket */
if (blocking_option) {
lret = 1L; /* 非阻塞模式 */
ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret);
}
else {
lret = 0L; /* 阻塞模式 */
ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret);
}
if (iClientOrServer == iShout) { /* SHOUT */
/* 产生数据并写入套接口 */
if (iProto == iTCP)
lret = TWriteData(sd, hOurDlg, len);
else /* UDP */
lret = UWriteData(sd, hOurDlg, len);
}
else { /* LISTEN */
if (iProto == iTCP)
lret = TReadData(sd,hOurDlg, len);
else /* UDP */
lret = UReadData(sd,hOurDlg, len);
}
closesocket(sd);
running = FALSE;
break;
case IDD_CANCEL:
if (running) {
/* 停止 */
ret = WSACancelBlockingCall();
run_cancelled = TRUE;
if (ret == SOCKET_ERROR) {
/* WSANOTINITIALISED or WSAENETDOWN or WSAEINVAL */
if (h_errno == WSAENETDOWN) {
/* Watch out for hAcceptSock! */
/* close what is left of the connection */
closesocket(sd);
}
}
}
break;
case IDM_EXIT:
ret = WSACleanup();
if (ret == SOCKET_ERROR && h_errno == WSAEINPROGRESS){
MessageBox(hOurWnd,
"Data transfer in progress./nStop transfer first.",
"WndProc()", MB_OK | MB_APPLMODAL|MB_ICONINFORMATION);
break; /* 一个套接口正处于阻塞状态 */
}
_free((char NEAR *) lpmyWSAData);
EndDialog(hOurDlg, TRUE) ; /* 退出 */
break;
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hOurDlg, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_SETTINGS:
lpProcSettings = MakeProcInstance(Settings, hInst);
DialogBox(hInst, "SettingsDialog", hOurDlg, lpProcSettings);
FreeProcInstance(lpProcSettings);
break;
default:
break;
} /* switch (wParam) */
break;
} /* switch (message) */
return FALSE;
}
/* 此函数处理About对话框 */
BOOL FAR PASCAL About(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
char tempBuf[15];
switch (message) {
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDA_COPYRIGHT,(LPSTR)lpmyWSAData->szDescription);
wsprintf(tempBuf, "%d.%2d/n",MAJOR_VERSION, MINOR_VERSION);
SetDlgItemText(hDlg, IDA_APP_VERSION, (LPSTR) tempBuf);
wsprintf(tempBuf, "%d.%2d/n",
lpmyWSAData->wVersion%256,lpmyWSAData->wVersion/256);
SetDlgItemText (hDlg, IDA_DLL_VERSION, (LPSTR) tempBuf);
return (FALSE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/* 此函数处理Settings 对话框 */
BOOL FAR PASCAL Settings(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
int buffer_len = len;
int port_no = iPortNo;
switch (message) {
case WM_INITDIALOG:
/* Select a default send() buffer length */
SetDlgItemInt(hDlg, IDS_BUFFLEN, len, 0);
/* Select a default port number */
SetDlgItemInt(hDlg, IDS_PORTNO, iPortNo, 0);
if (iClientOrServer == iShout) /* 程序类型 */
CheckThisProgBoxOn(hDlg, IDS_CLIENT);
else
CheckThisProgBoxOn(hDlg, IDS_SERVER);
if (iProto == iTCP) /* 协议类型 */
CheckThisProtoBoxOn(hDlg, IDS_TCP);
else
CheckThisProtoBoxOn(hDlg, IDS_UDP);
if (!blocking_option) /* 阻塞模式 */
CheckThisBoxOn(hDlg, IDS_BLOCK);
else
CheckThisBoxOn(hDlg, IDS_NOBLOCK);
SendDlgItemMessage(hDlg, /* dialog handle */
IDS_PORTNO, /* where to send msg */
EM_SETSEL, /* select characters */
NULL, /* additional info */
MAKELONG(0, 0x7fff)); /* entire contents */
SendDlgItemMessage(hDlg, /* dialog handle */
IDS_BUFFLEN, /* where to send msg */
EM_SETSEL, /* select characters */
NULL, /* additional info */
MAKELONG(0, 0x7fff)); /* entire contents */
SetFocus(GetDlgItem(hDlg, IDS_BUFFLEN));
return (TRUE);
case WM_COMMAND:
switch (wParam){
case IDS_CLIENT:
/* USer has set to Shout */
CheckThisProgBoxOn(hDlg, IDS_CLIENT);
tClientOrServer = iShout;
SetDlgItemText(hMainDlg, IDD_COHOST,"Foreign host:");
SetDlgItemText(hMainDlg, IDD_HNAME,"");
break;
case IDS_SERVER:
/* USer has set to Listen */
CheckThisProgBoxOn(hDlg, IDS_SERVER);
tClientOrServer = iListen;
SetDlgItemText(hMainDlg, IDD_COHOST,"Listening to:");
SetDlgItemText(hMainDlg, IDD_HNAME,"[Hit 'Start']");
break;
case IDS_TCP:
/* USer has set to TCP */
CheckThisProtoBoxOn(hDlg, IDS_TCP);
temporary_protocol = iTCP;
break;
case IDS_UDP:
/* USer has set to UDP */
CheckThisProtoBoxOn(hDlg, IDS_UDP);
temporary_protocol = iUDP;
break;
case IDS_BLOCK:
/* User has set to blocking mode */
CheckThisBoxOn(hDlg, IDS_BLOCK);
temporary_option = 0L;
break;
case IDS_NOBLOCK:
/* User has set to nonblocking mode */
CheckThisBoxOn(hDlg, IDS_NOBLOCK);
temporary_option = 1L;
break;
case IDOK:
/* 用户已完成对设置的修改 */
buffer_len = GetDlgItemInt(hDlg, IDS_BUFFLEN, NULL, 0);
if (buffer_len == 0 || buffer_len > 8192) {
MessageBox(hOurWnd, "Buffer length must be between 1 and 8K",
"Settings()",
MB_OK | MB_APPLMODAL | MB_ICONSTOP);
return (FALSE);
}
port_no = GetDlgItemInt(hDlg, IDS_PORTNO, NULL, 0);
if (port_no == 0) {
MessageBox(hDlg, "Port number must be between 0 and 65,535",
"Settings()",
MB_OK | MB_APPLMODAL | MB_ICONSTOP);
return (FALSE);
}
len = buffer_len;
iPortNo = port_no;
blocking_option = temporary_option;
iProto = temporary_protocol;
iClientOrServer = tClientOrServer;
case IDCANCEL:
/* 用户不想改变设置 */
EndDialog(hDlg, TRUE);
return (TRUE);
default:
break;
}
default:
break;
}
return (FALSE);
}
void
CheckThisBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_BLOCK:
CheckDlgButton(hDlg, IDS_BLOCK, 1);
CheckDlgButton(hDlg, IDS_NOBLOCK, 0);
break;
case IDS_NOBLOCK:
CheckDlgButton(hDlg, IDS_BLOCK, 0);
CheckDlgButton(hDlg, IDS_NOBLOCK, 1);
break;
default:
break;
}
return;
}
void
CheckThisProtoBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_TCP:
CheckDlgButton(hDlg, IDS_TCP, 1);
CheckDlgButton(hDlg, IDS_UDP, 0);
break;
case IDS_UDP:
CheckDlgButton(hDlg, IDS_TCP, 0);
CheckDlgButton(hDlg, IDS_UDP, 1);
break;
default:
break;
}
return;
}
void
CheckThisProgBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_CLIENT: /* Shout */
CheckDlgButton(hDlg, IDS_CLIENT, 1);
CheckDlgButton(hDlg, IDS_SERVER, 0);
break;
case IDS_SERVER: /* Listen */
CheckDlgButton(hDlg, IDS_CLIENT, 0);
CheckDlgButton(hDlg, IDS_SERVER, 1);
break;
default:
break;
}
return;
}
/* 以下就是我们如何处理“模拟阻塞”-本函数检查消息队列,如果发现需要处理的消息,就返回一个正的值。*/
int
ShoutBlockingHook (void)
{
MSG msg; /* lets us pull messages via PeekMessage */
int ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return ret;
}
char *
_calloc (nelem, elsize)
unsigned nelem, elsize;
{
HANDLE hMem;
PSTR ptr;
unsigned size = nelem * elsize;
if ((hMem = LocalAlloc(LPTR, size)) == NULL)
return (char *) 0;
if ((ptr = LocalLock(hMem)) == NULL) {
LocalFree(hMem);
return (char *) 0;
}
return (char *) ptr;
}
void
_free (void *cP)
{
(void) LocalFree(LocalHandle((WORD) cP));
}
void
ClearBoxes(HWND hOurDlg)
{
wsprintf(prbuf," /n");
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
return;
}
/*
* wshout_err()函数
* 描述:
*
* 通过错误代码获取相应的错误描述文本,与用户提供的错误前缀合
* 并,并显示在对话框中。
*/
void wshout_err (HWND hOurDlg, /* 对话框的窗口句柄 */
int wsa_err, /* WinSock错误代码 */
char far *err_prefix) /* 错误前缀字符串 */
{
char errbuf[PRBUF_LEN]; /* 错误描述字符串缓冲区 */
/* 获取错误描述字符串 */
WSAsperror(hInst, wsa_err, (LPSTR)errbuf, PRBUF_LEN);
/* 合并错误描述字符串与用户错误前缀字符串 */
wsprintf((LPSTR)prbuf, "%s:%s", (LPSTR) err_prefix, (LPSTR)errbuf);
/* 在对话框中显示错误文本 */
SetDlgItemText(hOurDlg, IDD_COMMENT, (LPSTR) prbuf);
} /* end wshout_err() */
/* eof */
3.4.3.2 wshout.h清单
/*
* 文件名: WSHOUT.H
*/
#ifndef _WSHOUT_INC_
#define _WSHOUT_INC_
/* Windows 3.0 头文件 */
#include <windows.h>
#define _INC_WINDOWS
#include <winsock.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* WSHOUT.C 中定义的全局变量 */
extern HANDLE hInst; /* Instance handle */
extern HWND hOurWnd; /* Main Window Handle */
extern int ret; /* work variable */
#define PRBUF_LEN 50
extern char prbuf[PRBUF_LEN]; /* work buffer */
/* 菜单IDs */
#define IDM_START 101
#define IDM_ABOUT 102
#define IDM_STOP 103
#define IDM_EXIT 104
#define IDM_SETTINGS 105
/* 对话框控制IDs */
#define IDD_HNAME 200
#define IDD_CONNECT IDOK
#define IDD_CANCEL IDCANCEL
#define IDD_WRITES 208
#define IDD_BYTES 210
#define IDD_BITS 212
#define IDD_HELP 214
#define IDD_SENT 230
#define IDD_WRITE 232
#define IDD_TIME 234
#define IDD_COMMENT 236
#define IDD_COHOST 240
/* “Settings”对话框控制IDs */
#define IDS_BUFFLEN 300
#define IDS_PORTNO 301
#define IDS_BLOCK 302
#define IDS_NOBLOCK 304
#define IDS_TCP 306
#define IDS_UDP 308
#define IDS_CLIENT 310
#define IDS_SERVER 312
#define IDS_DEFAULT 314
/* “About”对话框控制IDs */
#define IDA_COPYRIGHT 400
#define IDA_APP_VERSION 402
#define IDA_DLL_VERSION 404
/* 程序控制IDs */
#define WM_SELECT WM_USER+16
/* 全局变量*/
#define SOCK_DISCARD 9 /* use the UDP ttytst source port for test */
#define SOCK_SHOUT 32766 /* TCP port used for SHOUT & LISTEN */
#define BUF_SIZE 8192
#define WRITE_TIMER 1
/* 函数原型 */
int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
long FAR PASCAL ShoutWndProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL About(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL DialogProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL Settings(HWND, WORD, WORD, LONG);
BOOL InitApp(HANDLE);
void CheckThisBoxOn(HWND, int);
void CheckThisProtoBoxOn(HWND, int);
void CheckThisProgBoxOn(HWND, int);
void ClearBoxes(HWND);
SOCKET ResolveAndConnectHost(LPSTR, HWND, int, int);
SOCKET GetSocketAndBind(HWND, int, int);
long UWriteData(SOCKET, HWND, int);
long UReadData(SOCKET, HWND, int);
long TWriteData(SOCKET, HWND, int);
long TReadData(SOCKET, HWND, int);
int ShoutBlockingHook (void);
int PASCAL FAR WSAsperror (HANDLE, int, char far *, int);
void wshout_err (HWND, int, char far *);
#define bcopy(a,b,c) _fmemcpy(b,a,c)
char * _calloc (unsigned, unsigned);
void _free (void *);
#ifdef _cplusplus
}
#endif /* __cplusplus */
#endif /* ifndef _WSHOUT_INC_ */
/* eof */
3.4.3.3 wshout.rc清单
/*
* 文件名: WSHOUT.RC
*/
#include <windows.h>
#include <winsock.h>
#include "wshout.h"
MainMenu MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Start", IDM_START
MENUITEM "Sto&p", IDM_STOP
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Options"
BEGIN
MENUITEM "&Settings ...", IDM_SETTINGS
MENUITEM SEPARATOR
MENUITEM "&About Shout...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 144, 102
CAPTION "About Shout for Windows"
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
BEGIN
CTEXT "Windows Shout", -1, 29, 5, 85, 8
CTEXT "Version", -1, 46, 13, 33, 8, SS_CENTER | WS_GROUP
CTEXT "WINSOCK.DLL /n FTP Software, Inc. /nCopyright 1993", IDA_COPYRIGHT, 38, 40, 68, 25, SS_CENTER | WS_GROUP
CTEXT "Version", -1, 46, 67, 33, 8, SS_CENTER | WS_GROUP
CTEXT "num", IDA_DLL_VERSION, 79, 67, 18, 8, SS_CENTER | WS_GROUP
CONTROL "OK", 1, "BUTTON", BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP, 56, 82, 32, 14
ICON "SHOUT", -1, 11, 8, 16, 16
CONTROL "num", IDA_APP_VERSION, "STATIC", SS_LEFT | WS_GROUP, 79, 13, 18, 8
CONTROL "using", -1, "STATIC", SS_CENTER | WS_GROUP, 55, 26, 30, 8
END
SettingsDialog DIALOG 9, 16, 172, 117
CAPTION "Settings"
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
BEGIN
CONTROL " send/recv /nBuffer &length", -1, "STATIC", SS_LEFT | WS_GROUP, 84, 8, 48, 20
CONTROL "&Port number", -1, "STATIC", SS_LEFT | WS_GROUP, 84, 31, 48, 10
CONTROL "&Blocking", IDS_BLOCK, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 100, 61, 56, 12
CONTROL "&TCP", IDS_TCP, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 20, 60, 41, 12
CONTROL "&Client", IDS_CLIENT, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 19, 15, 35, 12
CONTROL "&Server", IDS_SERVER, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 19, 26, 35, 12
CONTROL "&UDP", IDS_UDP, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 20, 72, 41, 12
CONTROL "&Nonblocking", IDS_NOBLOCK, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 100, 73, 56, 12
CONTROL "O.K.", IDOK, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 40, 95, 37, 14
CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 90, 95, 37, 14
CONTROL "", IDS_BUFFLEN, "EDIT", ES_CENTER | WS_BORDER | WS_TABSTOP, 130, 11, 36, 12
CONTROL "", IDS_PORTNO, "EDIT", ES_CENTER | WS_BORDER | WS_TABSTOP, 130, 29, 36, 12
CONTROL "Protocol", 237, "button", BS_GROUPBOX, 6, 49, 70, 38
CONTROL "I/O Mode", 239, "button", BS_GROUPBOX, 90, 49, 70, 38
CONTROL "Program Mode", 241, "button", BS_GROUPBOX, 6, 7, 70, 34
END
MainDialog DIALOG 17, 32, 163, 135
CAPTION "Windows Shout"
MENU MainMenu
STYLE DS_ABSALIGN | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
BEGIN
CONTROL "", IDD_HNAME, "EDIT", ES_CENTER | WS_BORDER | WS_GROUP | WS_TABSTOP, 62, 9, 93, 12
CONTROL "", IDD_WRITE, "STATIC", SS_CENTER | SS_NOPREFIX | WS_BORDER, 7, 95, 45, 11
CONTROL "", IDD_SENT, "STATIC", SS_CENTER | WS_BORDER, 59, 95, 45, 11
CONTROL "", IDD_TIME, "STATIC", SS_CENTER | WS_BORDER, 111, 95, 45, 11
CONTROL "", IDD_WRITES, "STATIC", SS_CENTER | WS_BORDER, 7, 120, 45, 11
CONTROL "", IDD_BYTES, "STATIC", SS_CENTER | WS_BORDER, 59, 120, 45, 11
CONTROL "", IDD_BITS, "STATIC", SS_CENTER | WS_BORDER, 111, 120, 45, 11
CONTROL "writes[reads]", 105, "STATIC", SS_CENTER | WS_GROUP, 3, 85, 52, 9
CONTROL "writes[reads]/s", 105, "STATIC", SS_CENTER | WS_GROUP, 3, 111, 55, 9
CONTROL "bytes", 105, "STATIC", SS_CENTER | WS_GROUP, 61, 85, 42, 9
CONTROL "bytes/sec", 105, "STATIC", SS_CENTER | WS_GROUP, 61, 111, 42, 9
CONTROL "time (sec)", 105, "STATIC", SS_CENTER | WS_GROUP, 111, 85, 45, 9
CONTROL "bits/sec", 105, "STATIC", SS_CENTER | WS_GROUP, 113, 111, 42, 9
CONTROL "Host", IDD_COHOST, "STATIC", SS_LEFT, 7, 10, 52, 10
CONTROL "", IDD_COMMENT, "STATIC", SS_CENTER | WS_BORDER | WS_GROUP, 9, 68, 146, 11
CONTROL "&Start", IDOK, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 6, 32, 32, 20
CONTROL "Sto&p", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 65, 32, 32, 20
CONTROL "E&xit", IDM_EXIT, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 125, 32, 32, 20
CONTROL "", -1, "static", SS_BLACKFRAME, 0, 60, 163, 1
END
SHOUT ICON wshout.ico
/*
* 错误描述字符串表
* 用于WSAsperror()函数
*/
STRINGTABLE
BEGIN
WSABASEERR, "[0] No Error"
WSAEINTR, "[10004] Interrupted system call"
WSAEBADF, "[10009] Bad file number"
WSAEACCES, "[10013] Permission denied"
WSAEFAULT, "[10014] Bad address"
WSAEINVAL, "[10022] Invalid argument"
WSAEMFILE, "[10024] Too many open files"
WSAEWOULDBLOCK, "[10035] Operation would block"
WSAEINPROGRESS, "[10036] Operation now in progress"
WSAEALREADY, "[10037] Operation already in progress"
WSAENOTSOCK, "[10038] Socket operation on non-socket"
WSAEDESTADDRREQ, "[10039] Destination address required"
WSAEMSGSIZE, "[10040] Message too long"
WSAEPROTOTYPE, "[10041] Protocol wrong type for socket"
WSAENOPROTOOPT, "[10042] Bad protocol option"
WSAEPROTONOSUPPORT, "[10043] Protocol not supported"
WSAESOCKTNOSUPPORT, "[10044] Socket type not supported"
WSAEOPNOTSUPP, "[10045] Operation not supported on socket"
WSAEPFNOSUPPORT, "[10046] Protocol family not supported"
WSAEAFNOSUPPORT, "[10047] Address family not supported by protocol family"
WSAEADDRINUSE, "[10048] Address already in use"
WSAEADDRNOTAVAIL, "[10049] Can't assign requested address"
WSAENETDOWN, "[10050] Network is down"
WSAENETUNREACH, "[10051] Network is unreachable"
WSAENETRESET, "[10052] Net dropped connection or reset"
WSAECONNABORTED, "[10053] Software caused connection abort"
WSAECONNRESET, "[10054] Connection reset by peer"
WSAENOBUFS, "[10055] No buffer space available"
WSAEISCONN, "[10056] Socket is already connected"
WSAENOTCONN, "[10057] Socket is not connected"
WSAESHUTDOWN, "[10058] Can't send after socket shutdown"
WSAETOOMANYREFS, "[10059] Too many references, can't splice"
WSAETIMEDOUT, "[10060] Connection timed out"
WSAECONNREFUSED, "[10061] Connection refused"
WSAELOOP, "[10062] Too many levels of symbolic links"
WSAENAMETOOLONG, "[10063] File name too long"
WSAEHOSTDOWN, "[10064] Host is down"
WSAEHOSTUNREACH, "[10065] No Route to Host"
WSAENOTEMPTY, "[10066] Directory not empty"
WSAEPROCLIM, "[10067] Too many processes"
WSAEUSERS, "[10068] Too many users"
WSAEDQUOT, "[10069] Disc Quota Exceeded"
WSAESTALE, "[10070] Stale NFS file handle"
WSAEREMOTE, "[10071] Too many levels of remote in path"
WSASYSNOTREADY, "[10091] Network SubSystem is unavailable"
WSAVERNOTSUPPORTED, "[10092] WINSOCK DLL Version out of range"
WSANOTINITIALISED, "[10093] Successful WSASTARTUP not yet performed"
WSAHOST_NOT_FOUND, "[11001] Host not found"
WSATRY_AGAIN, "[11002] Non-Authoritative Host not found"
WSANO_RECOVERY, "[11003] Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"
WSANO_DATA, "[11004] Valid name, no data record of requested
type"
END
/* eof */
3.4.3.4 ushout.c清单
/*
* 文件名: USHOUT.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long UWriteData(SOCKET hSock, HWND hOurDlg, int send_len)
{
int counter;
static int DataBuffer[BUF_SIZE]; /* Buffer to hold generated data */
static char ReplyBuffer[512]; /* Buffer to hold any reply rcvd */
long bytes_sent = 0L; /* Counter of bytes on connection */
long total_len = 1024L*1024L; /* Total # of bytes to generate */
time_t start, end; /* variables to hold read timing */
long total_time = 0L; /* variable to hold delta t */
long write_count = 0L; /* number of times */
long tmp = 0L; /* holds count for bytes written */
long ltemp = 0L;
int i_temp;
extern int run_cancelled;
struct sockaddr_in dest; /* Destination machine address structure */
/* What makes shout unique is that it generates data*
* in memory (as opposed to accessing the disk). *
* This tests the 'raw' speed of the TCP connection *
* as the rate-limiting access time is eliminated. *
* First, generate the data and place it into an *
* array, data_buffer: */
for (counter = 0; counter < BUF_SIZE; counter++)
DataBuffer[counter] = counter;
/* Write data on the descriptor like a banshee,
* careful to time the writes and count data
* transmitted:
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Sending UDP Data ...");
time( &start );
while (bytes_sent < total_len){/* while still bytes to send */
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
tmp = send(hSock, (char FAR *) &DataBuffer, send_len, 0);
if (tmp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) /* if no data, read again */
continue;
else {
wshout_err (hOurDlg, WSAGetLastError(), "send()");
}
/* Calc. time elapsed & stats about any data sent */
time(&end);
if (total_time = (long) difftime(end, start)) {
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = write_count/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_sent/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_sent/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
/* exit from the while loop */
break;
} /* end if (total_time) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* # of bytes placed on connection */
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end if (tmp == -1) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* # of bytes placed on connection */
wsprintf((LPSTR)prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end while */
/* Look for a reply ... NOTE: most hosts won't give
* a 'reply', done to illustrate communication between
* sockets. Our ulisten example will give a reply though.
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Waiting for reply from server../n");
while (1) {
tmp = sizeof(dest);
i_temp = recvfrom(hSock,(char FAR *) &ReplyBuffer,sizeof(ReplyBuffer),
0, (struct sockaddr *) &dest, (int FAR *) &tmp);
if (i_temp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) /* if no data, read again */
continue;
else {
/* any error besides these. just punt */
wshout_err (hOurDlg, WSAGetLastError(), "recvfrom()");
}
break;
} /* end if (i_temp == SOCKET_ERROR) */
/* else got a reply ...*/
wsprintf((LPSTR)prbuf, "Server: %s/n", (LPSTR) ReplyBuffer);
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
break;
} /* end while(1) */
/* All done */
return bytes_sent;
}
/* eof */
3.4.3.5 ulisten.c清单
/*
* 文件名: ULISTEN.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long UReadData(SOCKET hSock, HWND hOurDlg, int read_len)
{
static char ReadBuf[BUF_SIZE];
static char SendBuf[512];
struct sockaddr_in local; /* Local machine address structure */
int i; /* General purpose return code */
long total_time = 0L; /* variable to hold delta t */
int tmp, len = 0;
int num_reads = 0;
long bytes_read = 0L;
long last_time, now, timeout = 15L;
long ltemp;
extern int run_cancelled;
BOOL bTemp = TRUE;
SetDlgItemText(hOurDlg, IDD_COMMENT, "Awaiting the UDP Data ...");
SetDlgItemText(hOurDlg, IDD_HNAME, " ");
time(&now); time(&last_time);
while (last_time + timeout > now) {
time(&now);
tmp = sizeof(local);
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages while available */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
len = recvfrom(hSock, ReadBuf, read_len, 0,
(struct sockaddr *) &local, &tmp);
if (len == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) {/* if no data, read again */
continue;
} /* end: if (errno == WSAEWOULDBLOCK) */
else {
if (bytes_read) {
wshout_err (hOurDlg, WSAGetLastError(), "recvfrom()");
}
} /* end else */
break;
} /* end: if (len == SOCKET_ERROR) */
if (bTemp) { /* To update our main display once */
/* Do not use wsprintf() or you will add an extra char */
_fmemcpy(prbuf, inet_ntoa(local.sin_addr), 4*sizeof(u_long));
SetDlgItemText(hOurDlg, IDD_HNAME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_COMMENT, "Reading UDP Data ...");
bTemp = FALSE;
}
num_reads++;
if (len != SOCKET_ERROR)
bytes_read += len;
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%d/n",num_reads);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_read);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
time(&last_time);
} /* end: while */
total_time = timeout;
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = num_reads/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_read/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_read/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
if (bytes_read) {
SetDlgItemText(hOurDlg, IDD_COMMENT, "...UDP Listen Done/n");
} /* end: if (bytes_read) */
else {
wsprintf((LPSTR)prbuf, "Timed out. No data received./n");
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
goto come_here;
} /* end: else */
/* send reply to 'client' */
wsprintf((LPSTR)prbuf,
"Replied to %s/n", inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
for (i=0; i<10; ++i) {
sprintf(SendBuf, "Rec'd %ld bytes./n", bytes_read);
if(len = sendto(hSock, SendBuf, sizeof(SendBuf), 0,
(struct sockaddr FAR *)&local,sizeof(local)))
{
if (len == SOCKET_ERROR) { /* if could not send bec. */
if (h_errno == WSAEWOULDBLOCK)
continue;
wshout_err (hOurDlg, WSAGetLastError(), "sendto()");
break;
} /* end: if (len == -1) */
} /* end: if (len = sendto()) */
} /* end for */
come_here:
return (bytes_read);
}
/* eof */
3.4.3.6 tshout.c清单
/*
* 文件名: TSHOUT.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long TWriteData(SOCKET hSock, HWND hOurDlg, int send_len)
{
int counter;
static int DataBuffer[BUF_SIZE]; /* Buffer to hold generated data */
long total_len = 1024L*1024L; /* Total # of bytes to generate */
long bytes_sent = 0L; /* Counter of bytes on connection */
int tmp = 0; /* holds count for bytes written */
long write_count = 0L; /* number of times */
time_t start, end; /* variables to hold read timing */
long total_time = 0L; /* variable to hold delta t */
long ltemp = 0L;
extern int run_cancelled;
/* What makes shout unique is that it generates data*
* in memory (as opposed to accessing the disk). *
* This tests the 'raw' speed of the TCP connection *
* as the rate-limiting access time is eliminated. *
* First, generate the data and place it into an *
* array, data_buffer: */
for (counter = 0; counter < BUF_SIZE; counter++)
DataBuffer[counter] = counter;
/* Write data on the descriptor like a banshee,
* careful to time the writes and count data
* transmitted:
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "...Sending TCP Data");
time(&start);
while ( bytes_sent < total_len) { /* while still bytes to send... */
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
tmp = send(hSock, (char FAR*) &DataBuffer, send_len, 0);
if (tmp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK)
continue;
else {
wshout_err (hOurDlg, WSAGetLastError(), "send()");
}
/* Calc. time elapsed & stats about any data sent */
time(&end);
/* exit from the while loop */
break;
} /* end if (tmp == -1) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* total # of bytes placed on connection*/
wsprintf(prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf(prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end while */
time(&end);
if (total_time = (long) difftime(end, start)) {
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = write_count/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_sent/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_sent/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
} /* end if (total_time) */
/* All done */
SetDlgItemText(hOurDlg, IDD_COMMENT, "...TCP Shout Done");
return bytes_sent;
}
/* eof */
3.4.3.7 tlisten.c清单
/*
* 文件名:TLISTEN.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long TReadData(SOCKET hSock, HWND hOurDlg, int read_len)
{
static char ReadBuf[BUF_SIZE];
SOCKET hAcceptSock;
struct sockaddr_in local; /* Local machine address structure */
long total_time = 0L; /* variable to hold delta t */
int tmp, len = 0;
int num_reads = 0;
long bytes_read = 0L;
long last_time = 0L;
long now = 0L;
long ltemp;
extern long blocking_option;
extern int run_cancelled;
struct linger AcceptLinger;
BOOL running = FALSE;
BOOL bTemp = TRUE;
SetDlgItemText(hOurDlg, IDD_COMMENT, "Awaiting the TCP Data ...");
SetDlgItemText(hOurDlg, IDD_HNAME, " ");
tmp = sizeof(local);
if (!blocking_option) {
hAcceptSock = accept(hSock,(struct sockaddr FAR *)&local,
(int FAR *)&tmp);
}
else {
for (; {
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
hAcceptSock = accept(hSock,(struct sockaddr FAR *)&local,
(int FAR *)&tmp);
if (hAcceptSock == INVALID_SOCKET) {
if (h_errno == WSAEWOULDBLOCK)
/* Try again */
;
else {
/* Fatal error -- pop out. */
break;
}
} /* end if ((hAcceptSock = .. */
else {
/* Success -- pop out. */
break;
}
} /* end for */
} /* end else */
if (hAcceptSock == INVALID_SOCKET) {
wshout_err (hOurDlg, WSAGetLastError(), "accept()");
return 0;
}
/* Now, read the data as fast as we can until no more to read */
time(&last_time);
do {
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages while available */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
len = recv(hAcceptSock, ReadBuf, read_len, 0);
if (len == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK)
continue;
else
break;
}
else if (len == 0)
break;
num_reads++;
bytes_read += len;
wsprintf((LPSTR)prbuf,"%d/n",num_reads);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_read);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
if (bTemp) { /* To update our main display once */
/* Do not use wsprintf() or you will add an extra char */
_fmemcpy(prbuf, inet_ntoa(local.sin_addr), 4*sizeof(u_long));
SetDlgItemText(hOurDlg, IDD_HNAME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_COMMENT, "Reading TCP Data ...");
bTemp = FALSE;
}
} while ((len != 0) || (len != SOCKET_ERROR));
time (&now);
if (len == SOCKET_ERROR) {
if ((h_errno == WSAESHUTDOWN) || (h_errno == WSAENOTCONN)) {
/* nothing available for read. */
wsprintf((LPSTR)prbuf,
"Connection from %s closed./n",inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
}
else { /* Other error */
wshout_err (hOurDlg, WSAGetLastError(), "recv()");
}
}
else if (len == 0) {
/* Other side shut down the connection */
wsprintf((LPSTR)prbuf,
"Connection from %s closed./n",inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
}
AcceptLinger.l_onoff = 1;
AcceptLinger.l_linger = 0;
ret = setsockopt(hAcceptSock, SOL_SOCKET, SO_LINGER,
(char FAR *) &AcceptLinger, sizeof(AcceptLinger));
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "setsockopt()");
}
ret = closesocket(hAcceptSock);
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "closesocket()");
}
total_time = (long) difftime(now, last_time);
if (total_time == 0)
total_time = 1L; /* Avoid dividing by zero */
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = num_reads/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_read/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_read/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
if (bytes_read) {
SetDlgItemText(hOurDlg, IDD_COMMENT, "...TCP Listen Done/n");
} /* end: if (bytes_read) */
return (bytes_read);
}
/* eof */
3.4.3.8 errno.c清单
#include <windows.h>
#include <winsock.h>
/*
* 文件名: ERRNO.C
*/
/*
* Function: WSAsperror()
*
* Description:
*
* Copies string corresponding to the error code provided
* into buf, maximum length len. Returns length actually
* copied to buffer, or zero if error code is unknown.
* String resources should be present for each error code
* using the value of the code as the string ID (except for
* error = 0, which is mapped to WSABASEERR to keep it with
* the others). The DLL is free to use any string IDs that
* are less than WSABASEERR for its own use.
*
*/
int PASCAL FAR WSAsperror (HANDLE hInst, /* Instance Handle */
int errorcode, /* WSA Error Number */
char far * buf, /* Buffer for error string */
int len) /* Length of buffer */
{
int err_len; /* length of error text */
if (errorcode == 0) /* If error passed is 0, use the */
errorcode = WSABASEERR; /* base resource file number */
if (errorcode < WSABASEERR) /* If invalid Error code */
return 0; /* return string length of zero */
/* error string from the table in the Resource file into buffer */
err_len = LoadString(hInst,errorcode,buf,len);
return (err_len); /* return length of error string retrieved */
} /* end WSAsperror() */
/* eof */
3.4.3.9 resolve.c清单
/*
* 文件名: RESOLVE.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
SOCKET
ResolveAndConnectHost(LPSTR lpHostName,HWND hOurDlg,int iproto, int iSockPort)
{
struct hostent FAR *host_ptr; /* Ptr to the host name */
struct sockaddr_in dest; /* Addr of target host */
SOCKET hSock; /* The socket to create */
int iSockType;
extern int iTCP;
extern int iUDP;
/* Internet family addressing */
dest.sin_family = PF_INET;
if (iproto == iTCP) {
iSockType = SOCK_STREAM;
}
else if (iproto == iUDP) {
iSockType = SOCK_DGRAM;
}
else {
return (SOCKET) -1; /* Unknown protocol */
}
/* default port to connect to. Must be in network byte order */
dest.sin_port = htons((u_int) iSockPort);
SetDlgItemText(hOurDlg, IDD_COMMENT,"Resolving hostname...");
/* Resolve the host name */
host_ptr = gethostbyname(lpHostName);
if (host_ptr == NULL) {
wshout_err (hOurDlg, WSAGetLastError(), "gethostbyname()");
return (SOCKET) -1;
}
/* Patch host address into struct describing conn: */
bcopy(host_ptr->h_addr,&dest.sin_addr,host_ptr->h_length);
/* Allocate a network (socket) descriptor: */
hSock = socket(PF_INET, iSockType, 0);
if (hSock == INVALID_SOCKET) {
wshout_err (hOurDlg, WSAGetLastError(), "socket()");
return (SOCKET) -1;
}
/* Start connection process to host described in 'dest' *
* struct.
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Connecting ...");
ret=connect(hSock,(struct sockaddr FAR *)&dest,sizeof(dest));
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "connect()");
closesocket(hSock);
return (SOCKET) -1;
}
SetDlgItemText(hOurDlg, IDD_COMMENT, "...Connected");
return hSock;
}
SOCKET GetSocketAndBind(HWND hOurDlg, int iProto, int iSockPort)
{
SOCKET hSock; /* Connection socket descriptor */
struct sockaddr_in local; /* Local machine address structure*/
int iSockType;
extern int iTCP;
extern int iUDP;
/* Internet family addressing */
if (iProto == iTCP) {
iSockType = SOCK_STREAM;
}
else {
iSockType = SOCK_DGRAM;
}
memset(&local, '/0', sizeof (local));
local.sin_family = PF_INET;
local.sin_port = htons((u_short)iSockPort);
/* allocate a socket descriptor */
hSock = socket(PF_INET, iSockType, 0);
if (hSock == INVALID_SOCKET) { /* socket() failed */
wshout_err (hOurDlg, WSAGetLastError(), "socket()");
return (SOCKET) -1;
}
/* bind socket to a local addr */
ret = bind(hSock, (struct sockaddr FAR *) &local, sizeof(local));
if (ret == SOCKET_ERROR){ /* bind() failed */
wshout_err (hOurDlg, WSAGetLastError(), "bind()");
return (SOCKET) -1;
}
if (iProto == iUDP)
return (hSock);
/* If iProto == iTCP, then must listen() and accept() also */
ret = listen(hSock, 0); /* listen on the socket */
if (ret == SOCKET_ERROR){ /* listen() failed */
wshout_err (hOurDlg, WSAGetLastError(), "listen()");
return (SOCKET) -1;
}
return(hSock);
}
/* eof */
http://www.lingphi.com
[/h4]
3.4 另一个精巧的应用程序实例-wshout
在本节中,我们通过一个经过精心选择的例子,进一步讨论一下Windows Sockets编程技术。例如如何编制客户机或服务器程序,如何应用TCP有连接服务(流式套接口)或UDP无连接服务(数据报套接口),如何进行阻塞或非阻塞方式的套接口操作等等,这些都是经常碰到的问题。接下来要介绍的wshout程序,可以通过灵活地设置不同选项来达到上述应用情况的任意组合,从而基本覆盖了应用Windows Sockets编程所可能碰到的问题,具有很好的研究参考价值。
由于该程序思路清晰,结构精良,所以我们不打算很详细地剖析每一个语句,而只是简要介绍一下整个程序的逻辑结构,并在源程序中加入适当的注释。我们相信,任何具有基本C语言和Windows编程经验的读者,都能很轻松地读懂绝大部分内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。
该程序在FTP公司的PCTCP支撑环境下调试通过,不过只要读者拥有任何符合Windows Sockets 1.1规范的实现,也能顺利执行该程序。
3.4.1 源程序目录
1. wshout.c wshout主程序
2. wshout.h wshout头文件
3. wshout.rc wshout资源文件
4. ushout.c UDP客户机程序
5. ulisten.c UDP服务器程序
6. tshout.c TCP客户机程序
7. tlisten.c TCP服务器程序
8. errno.c 获取WSAE*错误描述字符串程序
9. resolve.c 客户机/服务器启动程序
在编译本程序时,笔者用的是BC3.1,只需做一个PRJ工程文件,将上述.c文件及winsock.lib包括进来就行了。请注意winsock.h应在include目录或当前目录中,winsock.lib可利用winsock.dll通过implib工具来建立。如果读者使用其他的编译器,可自行作相应的调整,在此不再赘述。
3.4.2 程序逻辑结构
3.4.3 源程序清单及注释
3.4.3.1 wshout.c清单
/*
* 文件名: WSHOUT.C
*/
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "wshout.h"
#define MAJOR_VERSION 1
#define MINOR_VERSION 2
#define WSA_MAKEWORD(x,y) ( * 256 + (x)) /* HI:Minor, LO:Major */
HANDLE hInst; /* 进程实例句柄 */
HWND hOurWnd; /* 主窗口句柄 */
HWND hMainDlg; /* 主对话框句柄 */
int ret; /* 工作变量 */
char prbuf[PRBUF_LEN]; /* 用于显示文本的工作缓冲区 */
SOCKET sd; /* 用于监听连接的套接口描述字 */
long temporary_option = 0L; /* 缺省为阻塞模式 */
long blocking_option = 0L; /* 阻塞模式的全局标识 */
int run_cancelled = 0; /* 指示何时按下了取消按钮 */
int len = 1024; /* 一次写的字节数 */
BOOL running = FALSE; /* 程序的运行状态 */
const int iTCP = 1; /* 指定为TCP Shout */
const int iUDP = 2; /* 指定为UDP Shout */
int iProto = 1; /* 缺省为TCP Shout */
int iPortNo = SOCK_SHOUT;
int temporary_protocol = 1; /* 在Settings()中使用 */
int iShout = 1;
int iListen = 2;
int iClientOrServer = 1; /* 缺省为Shout(客户机) */
int tClientOrServer = 1; /* 在Settings()中使用 */
char HostModeBuf[20];/* 保存模式字符串 */
WORD VersionReqd;
LPWSADATA lpmyWSAData;
int PASCAL
WinMain (HANDLE hInstance,HANDLE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
HWND hWnd;
MSG msg;
BOOL InitApp(HANDLE);
if (!hPrevInstance)
if (!InitApp(hInstance))
return (NULL);
hInst = hInstance;
hWnd = CreateWindow("MainMenu",
"Windows Shout",
WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return (NULL);
hOurWnd = hWnd;
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg); /* 翻译虚拟键码 */
DispatchMessage(&msg);
}
return (msg.wParam);
}
BOOL InitApp(HANDLE hInstance)
{
HANDLE hMemory;
PWNDCLASS pWndClass;
BOOL bSuccess;
hMemory = LocalAlloc(LPTR, sizeof(WNDCLASS));
pWndClass = (PWNDCLASS) LocalLock(hMemory);
pWndClass->hCursor = LoadCursor(NULL, IDC_ARROW);
pWndClass->hIcon = LoadIcon(hInstance, (LPSTR) "SHOUT");
pWndClass->lpszMenuName = (LPSTR) "MainMenu";
pWndClass->lpszClassName = (LPSTR) "MainMenu";
pWndClass->hbrBackground = GetStockObject(WHITE_BRUSH);
pWndClass->hInstance = hInstance;
pWndClass->style = NULL;
pWndClass->lpfnWndProc = ShoutWndProc;
bSuccess = RegisterClass(pWndClass);
LocalUnlock(hMemory);
LocalFree(hMemory);
return (bSuccess);
}
long FAR PASCAL ShoutWndProc(HWND hWnd, WORD message,WORD wParam, LONG lParam)
{
FARPROC lpDialogBoxProc;
switch (message){
case WM_CREATE:
/* Put up the dialog box */
lpDialogBoxProc = MakeProcInstance(DialogProc, hInst);
DialogBox (hInst, (LPSTR) "MainDialog", hWnd, lpDialogBoxProc) ;
FreeProcInstance(lpDialogBoxProc);
PostMessage(hWnd, WM_DESTROY, 0, 0L);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, message, wParam, lParam));
}
return NULL;
}
BOOL FAR PASCAL DialogProc(HWND hOurDlg, WORD message, WORD wParam, LONG lParam)
{
FARPROC lpProcAbout;
FARPROC lpProcSettings;
long lret;
WORD wMajorVersion, wMinorVersion;
char hostnm[64]; /* 包含主机名的工作缓冲区 */
switch (message) {
case WM_INITDIALOG:
/* 选择缺省主机 */
SetDlgItemText(hOurDlg, IDD_HNAME, "");
SendDlgItemMessage(hOurDlg, /* 对话框句柄 */
IDD_HNAME, /* 向何处发送msg */
EM_SETSEL, /* 选择字符 */
NULL, /* 附加信息 */
MAKELONG(0, 0x7fff)); /* 全部内容 */
SetFocus(GetDlgItem(hOurDlg, IDD_HNAME));
/* 初始化 */
hMainDlg = hOurDlg; /* 保存自己的窗口句柄 */
SetDlgItemText(hOurDlg, IDD_COHOST,"Shout to:");
wMajorVersion = MAJOR_VERSION;
wMinorVersion = MINOR_VERSION;
VersionReqd=WSA_MAKEWORD(wMajorVersion, wMinorVersion);
lpmyWSAData = (LPWSADATA)_calloc(1, sizeof(WSADATA));
ret = WSAStartup(VersionReqd, lpmyWSAData);
if (ret != 0){
wshout_err (hOurDlg, WSAGetLastError(), "WSAStartup()");
}
return (TRUE);
case WM_CLOSE:
PostMessage(hOurDlg, WM_COMMAND, IDM_EXIT, 0L);
break;
case WM_SYSCOMMAND:
SendMessage(hOurWnd, message, wParam, lParam);
break;
case WM_COMMAND:
switch (wParam) {
case IDD_CONNECT: /* 按下连接按钮 */
case IDM_START: /* 选择了Start菜单项 */
run_cancelled = FALSE;
/* 不能重入 */
if (running){
MessageBox(hOurWnd,"Shout is already running !",
"Shout", MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
return FALSE;
}
ClearBoxes(hOurDlg);
running = TRUE;
if (iClientOrServer == iShout) {
/* 确保有主机名 */
if (GetDlgItemText (hOurDlg, IDD_HNAME, hostnm, 80) < 2) {
MessageBeep(0);
SetDlgItemText(hOurDlg,
IDD_COMMENT,"No hostname specified");
running = FALSE;
break;
}
sd = ResolveAndConnectHost((char FAR *)hostnm,hOurDlg,iProto,
iPortNo);
if (sd == SOCKET_ERROR) {/* 无法创建套接口 */
running = FALSE;
break;
}
}
else {
sd = GetSocketAndBind(hOurDlg, iProto, iPortNo);
if (sd == SOCKET_ERROR) {
running = FALSE;
break;
}
}
/* Set the I/O mode of the socket */
if (blocking_option) {
lret = 1L; /* 非阻塞模式 */
ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret);
}
else {
lret = 0L; /* 阻塞模式 */
ioctlsocket(sd, FIONBIO, (u_long FAR *) &lret);
}
if (iClientOrServer == iShout) { /* SHOUT */
/* 产生数据并写入套接口 */
if (iProto == iTCP)
lret = TWriteData(sd, hOurDlg, len);
else /* UDP */
lret = UWriteData(sd, hOurDlg, len);
}
else { /* LISTEN */
if (iProto == iTCP)
lret = TReadData(sd,hOurDlg, len);
else /* UDP */
lret = UReadData(sd,hOurDlg, len);
}
closesocket(sd);
running = FALSE;
break;
case IDD_CANCEL:
if (running) {
/* 停止 */
ret = WSACancelBlockingCall();
run_cancelled = TRUE;
if (ret == SOCKET_ERROR) {
/* WSANOTINITIALISED or WSAENETDOWN or WSAEINVAL */
if (h_errno == WSAENETDOWN) {
/* Watch out for hAcceptSock! */
/* close what is left of the connection */
closesocket(sd);
}
}
}
break;
case IDM_EXIT:
ret = WSACleanup();
if (ret == SOCKET_ERROR && h_errno == WSAEINPROGRESS){
MessageBox(hOurWnd,
"Data transfer in progress./nStop transfer first.",
"WndProc()", MB_OK | MB_APPLMODAL|MB_ICONINFORMATION);
break; /* 一个套接口正处于阻塞状态 */
}
_free((char NEAR *) lpmyWSAData);
EndDialog(hOurDlg, TRUE) ; /* 退出 */
break;
case IDM_ABOUT:
lpProcAbout = MakeProcInstance(About, hInst);
DialogBox(hInst, "AboutBox", hOurDlg, lpProcAbout);
FreeProcInstance(lpProcAbout);
break;
case IDM_SETTINGS:
lpProcSettings = MakeProcInstance(Settings, hInst);
DialogBox(hInst, "SettingsDialog", hOurDlg, lpProcSettings);
FreeProcInstance(lpProcSettings);
break;
default:
break;
} /* switch (wParam) */
break;
} /* switch (message) */
return FALSE;
}
/* 此函数处理About对话框 */
BOOL FAR PASCAL About(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
char tempBuf[15];
switch (message) {
case WM_INITDIALOG:
SetDlgItemText(hDlg, IDA_COPYRIGHT,(LPSTR)lpmyWSAData->szDescription);
wsprintf(tempBuf, "%d.%2d/n",MAJOR_VERSION, MINOR_VERSION);
SetDlgItemText(hDlg, IDA_APP_VERSION, (LPSTR) tempBuf);
wsprintf(tempBuf, "%d.%2d/n",
lpmyWSAData->wVersion%256,lpmyWSAData->wVersion/256);
SetDlgItemText (hDlg, IDA_DLL_VERSION, (LPSTR) tempBuf);
return (FALSE);
case WM_COMMAND:
if (wParam == IDOK
|| wParam == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE);
}
/* 此函数处理Settings 对话框 */
BOOL FAR PASCAL Settings(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
int buffer_len = len;
int port_no = iPortNo;
switch (message) {
case WM_INITDIALOG:
/* Select a default send() buffer length */
SetDlgItemInt(hDlg, IDS_BUFFLEN, len, 0);
/* Select a default port number */
SetDlgItemInt(hDlg, IDS_PORTNO, iPortNo, 0);
if (iClientOrServer == iShout) /* 程序类型 */
CheckThisProgBoxOn(hDlg, IDS_CLIENT);
else
CheckThisProgBoxOn(hDlg, IDS_SERVER);
if (iProto == iTCP) /* 协议类型 */
CheckThisProtoBoxOn(hDlg, IDS_TCP);
else
CheckThisProtoBoxOn(hDlg, IDS_UDP);
if (!blocking_option) /* 阻塞模式 */
CheckThisBoxOn(hDlg, IDS_BLOCK);
else
CheckThisBoxOn(hDlg, IDS_NOBLOCK);
SendDlgItemMessage(hDlg, /* dialog handle */
IDS_PORTNO, /* where to send msg */
EM_SETSEL, /* select characters */
NULL, /* additional info */
MAKELONG(0, 0x7fff)); /* entire contents */
SendDlgItemMessage(hDlg, /* dialog handle */
IDS_BUFFLEN, /* where to send msg */
EM_SETSEL, /* select characters */
NULL, /* additional info */
MAKELONG(0, 0x7fff)); /* entire contents */
SetFocus(GetDlgItem(hDlg, IDS_BUFFLEN));
return (TRUE);
case WM_COMMAND:
switch (wParam){
case IDS_CLIENT:
/* USer has set to Shout */
CheckThisProgBoxOn(hDlg, IDS_CLIENT);
tClientOrServer = iShout;
SetDlgItemText(hMainDlg, IDD_COHOST,"Foreign host:");
SetDlgItemText(hMainDlg, IDD_HNAME,"");
break;
case IDS_SERVER:
/* USer has set to Listen */
CheckThisProgBoxOn(hDlg, IDS_SERVER);
tClientOrServer = iListen;
SetDlgItemText(hMainDlg, IDD_COHOST,"Listening to:");
SetDlgItemText(hMainDlg, IDD_HNAME,"[Hit 'Start']");
break;
case IDS_TCP:
/* USer has set to TCP */
CheckThisProtoBoxOn(hDlg, IDS_TCP);
temporary_protocol = iTCP;
break;
case IDS_UDP:
/* USer has set to UDP */
CheckThisProtoBoxOn(hDlg, IDS_UDP);
temporary_protocol = iUDP;
break;
case IDS_BLOCK:
/* User has set to blocking mode */
CheckThisBoxOn(hDlg, IDS_BLOCK);
temporary_option = 0L;
break;
case IDS_NOBLOCK:
/* User has set to nonblocking mode */
CheckThisBoxOn(hDlg, IDS_NOBLOCK);
temporary_option = 1L;
break;
case IDOK:
/* 用户已完成对设置的修改 */
buffer_len = GetDlgItemInt(hDlg, IDS_BUFFLEN, NULL, 0);
if (buffer_len == 0 || buffer_len > 8192) {
MessageBox(hOurWnd, "Buffer length must be between 1 and 8K",
"Settings()",
MB_OK | MB_APPLMODAL | MB_ICONSTOP);
return (FALSE);
}
port_no = GetDlgItemInt(hDlg, IDS_PORTNO, NULL, 0);
if (port_no == 0) {
MessageBox(hDlg, "Port number must be between 0 and 65,535",
"Settings()",
MB_OK | MB_APPLMODAL | MB_ICONSTOP);
return (FALSE);
}
len = buffer_len;
iPortNo = port_no;
blocking_option = temporary_option;
iProto = temporary_protocol;
iClientOrServer = tClientOrServer;
case IDCANCEL:
/* 用户不想改变设置 */
EndDialog(hDlg, TRUE);
return (TRUE);
default:
break;
}
default:
break;
}
return (FALSE);
}
void
CheckThisBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_BLOCK:
CheckDlgButton(hDlg, IDS_BLOCK, 1);
CheckDlgButton(hDlg, IDS_NOBLOCK, 0);
break;
case IDS_NOBLOCK:
CheckDlgButton(hDlg, IDS_BLOCK, 0);
CheckDlgButton(hDlg, IDS_NOBLOCK, 1);
break;
default:
break;
}
return;
}
void
CheckThisProtoBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_TCP:
CheckDlgButton(hDlg, IDS_TCP, 1);
CheckDlgButton(hDlg, IDS_UDP, 0);
break;
case IDS_UDP:
CheckDlgButton(hDlg, IDS_TCP, 0);
CheckDlgButton(hDlg, IDS_UDP, 1);
break;
default:
break;
}
return;
}
void
CheckThisProgBoxOn(HWND hDlg, int ButtonID)
{
switch (ButtonID) {
case IDS_CLIENT: /* Shout */
CheckDlgButton(hDlg, IDS_CLIENT, 1);
CheckDlgButton(hDlg, IDS_SERVER, 0);
break;
case IDS_SERVER: /* Listen */
CheckDlgButton(hDlg, IDS_CLIENT, 0);
CheckDlgButton(hDlg, IDS_SERVER, 1);
break;
default:
break;
}
return;
}
/* 以下就是我们如何处理“模拟阻塞”-本函数检查消息队列,如果发现需要处理的消息,就返回一个正的值。*/
int
ShoutBlockingHook (void)
{
MSG msg; /* lets us pull messages via PeekMessage */
int ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return ret;
}
char *
_calloc (nelem, elsize)
unsigned nelem, elsize;
{
HANDLE hMem;
PSTR ptr;
unsigned size = nelem * elsize;
if ((hMem = LocalAlloc(LPTR, size)) == NULL)
return (char *) 0;
if ((ptr = LocalLock(hMem)) == NULL) {
LocalFree(hMem);
return (char *) 0;
}
return (char *) ptr;
}
void
_free (void *cP)
{
(void) LocalFree(LocalHandle((WORD) cP));
}
void
ClearBoxes(HWND hOurDlg)
{
wsprintf(prbuf," /n");
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
return;
}
/*
* wshout_err()函数
* 描述:
*
* 通过错误代码获取相应的错误描述文本,与用户提供的错误前缀合
* 并,并显示在对话框中。
*/
void wshout_err (HWND hOurDlg, /* 对话框的窗口句柄 */
int wsa_err, /* WinSock错误代码 */
char far *err_prefix) /* 错误前缀字符串 */
{
char errbuf[PRBUF_LEN]; /* 错误描述字符串缓冲区 */
/* 获取错误描述字符串 */
WSAsperror(hInst, wsa_err, (LPSTR)errbuf, PRBUF_LEN);
/* 合并错误描述字符串与用户错误前缀字符串 */
wsprintf((LPSTR)prbuf, "%s:%s", (LPSTR) err_prefix, (LPSTR)errbuf);
/* 在对话框中显示错误文本 */
SetDlgItemText(hOurDlg, IDD_COMMENT, (LPSTR) prbuf);
} /* end wshout_err() */
/* eof */
3.4.3.2 wshout.h清单
/*
* 文件名: WSHOUT.H
*/
#ifndef _WSHOUT_INC_
#define _WSHOUT_INC_
/* Windows 3.0 头文件 */
#include <windows.h>
#define _INC_WINDOWS
#include <winsock.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* WSHOUT.C 中定义的全局变量 */
extern HANDLE hInst; /* Instance handle */
extern HWND hOurWnd; /* Main Window Handle */
extern int ret; /* work variable */
#define PRBUF_LEN 50
extern char prbuf[PRBUF_LEN]; /* work buffer */
/* 菜单IDs */
#define IDM_START 101
#define IDM_ABOUT 102
#define IDM_STOP 103
#define IDM_EXIT 104
#define IDM_SETTINGS 105
/* 对话框控制IDs */
#define IDD_HNAME 200
#define IDD_CONNECT IDOK
#define IDD_CANCEL IDCANCEL
#define IDD_WRITES 208
#define IDD_BYTES 210
#define IDD_BITS 212
#define IDD_HELP 214
#define IDD_SENT 230
#define IDD_WRITE 232
#define IDD_TIME 234
#define IDD_COMMENT 236
#define IDD_COHOST 240
/* “Settings”对话框控制IDs */
#define IDS_BUFFLEN 300
#define IDS_PORTNO 301
#define IDS_BLOCK 302
#define IDS_NOBLOCK 304
#define IDS_TCP 306
#define IDS_UDP 308
#define IDS_CLIENT 310
#define IDS_SERVER 312
#define IDS_DEFAULT 314
/* “About”对话框控制IDs */
#define IDA_COPYRIGHT 400
#define IDA_APP_VERSION 402
#define IDA_DLL_VERSION 404
/* 程序控制IDs */
#define WM_SELECT WM_USER+16
/* 全局变量*/
#define SOCK_DISCARD 9 /* use the UDP ttytst source port for test */
#define SOCK_SHOUT 32766 /* TCP port used for SHOUT & LISTEN */
#define BUF_SIZE 8192
#define WRITE_TIMER 1
/* 函数原型 */
int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
long FAR PASCAL ShoutWndProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL About(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL DialogProc(HWND, WORD, WORD, LONG);
BOOL FAR PASCAL Settings(HWND, WORD, WORD, LONG);
BOOL InitApp(HANDLE);
void CheckThisBoxOn(HWND, int);
void CheckThisProtoBoxOn(HWND, int);
void CheckThisProgBoxOn(HWND, int);
void ClearBoxes(HWND);
SOCKET ResolveAndConnectHost(LPSTR, HWND, int, int);
SOCKET GetSocketAndBind(HWND, int, int);
long UWriteData(SOCKET, HWND, int);
long UReadData(SOCKET, HWND, int);
long TWriteData(SOCKET, HWND, int);
long TReadData(SOCKET, HWND, int);
int ShoutBlockingHook (void);
int PASCAL FAR WSAsperror (HANDLE, int, char far *, int);
void wshout_err (HWND, int, char far *);
#define bcopy(a,b,c) _fmemcpy(b,a,c)
char * _calloc (unsigned, unsigned);
void _free (void *);
#ifdef _cplusplus
}
#endif /* __cplusplus */
#endif /* ifndef _WSHOUT_INC_ */
/* eof */
3.4.3.3 wshout.rc清单
/*
* 文件名: WSHOUT.RC
*/
#include <windows.h>
#include <winsock.h>
#include "wshout.h"
MainMenu MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Start", IDM_START
MENUITEM "Sto&p", IDM_STOP
MENUITEM SEPARATOR
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Options"
BEGIN
MENUITEM "&Settings ...", IDM_SETTINGS
MENUITEM SEPARATOR
MENUITEM "&About Shout...", IDM_ABOUT
END
END
ABOUTBOX DIALOG 22, 17, 144, 102
CAPTION "About Shout for Windows"
STYLE DS_MODALFRAME | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
BEGIN
CTEXT "Windows Shout", -1, 29, 5, 85, 8
CTEXT "Version", -1, 46, 13, 33, 8, SS_CENTER | WS_GROUP
CTEXT "WINSOCK.DLL /n FTP Software, Inc. /nCopyright 1993", IDA_COPYRIGHT, 38, 40, 68, 25, SS_CENTER | WS_GROUP
CTEXT "Version", -1, 46, 67, 33, 8, SS_CENTER | WS_GROUP
CTEXT "num", IDA_DLL_VERSION, 79, 67, 18, 8, SS_CENTER | WS_GROUP
CONTROL "OK", 1, "BUTTON", BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP, 56, 82, 32, 14
ICON "SHOUT", -1, 11, 8, 16, 16
CONTROL "num", IDA_APP_VERSION, "STATIC", SS_LEFT | WS_GROUP, 79, 13, 18, 8
CONTROL "using", -1, "STATIC", SS_CENTER | WS_GROUP, 55, 26, 30, 8
END
SettingsDialog DIALOG 9, 16, 172, 117
CAPTION "Settings"
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
BEGIN
CONTROL " send/recv /nBuffer &length", -1, "STATIC", SS_LEFT | WS_GROUP, 84, 8, 48, 20
CONTROL "&Port number", -1, "STATIC", SS_LEFT | WS_GROUP, 84, 31, 48, 10
CONTROL "&Blocking", IDS_BLOCK, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 100, 61, 56, 12
CONTROL "&TCP", IDS_TCP, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 20, 60, 41, 12
CONTROL "&Client", IDS_CLIENT, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 19, 15, 35, 12
CONTROL "&Server", IDS_SERVER, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 19, 26, 35, 12
CONTROL "&UDP", IDS_UDP, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 20, 72, 41, 12
CONTROL "&Nonblocking", IDS_NOBLOCK, "BUTTON", BS_AUTOCHECKBOX | WS_TABSTOP, 100, 73, 56, 12
CONTROL "O.K.", IDOK, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 40, 95, 37, 14
CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 90, 95, 37, 14
CONTROL "", IDS_BUFFLEN, "EDIT", ES_CENTER | WS_BORDER | WS_TABSTOP, 130, 11, 36, 12
CONTROL "", IDS_PORTNO, "EDIT", ES_CENTER | WS_BORDER | WS_TABSTOP, 130, 29, 36, 12
CONTROL "Protocol", 237, "button", BS_GROUPBOX, 6, 49, 70, 38
CONTROL "I/O Mode", 239, "button", BS_GROUPBOX, 90, 49, 70, 38
CONTROL "Program Mode", 241, "button", BS_GROUPBOX, 6, 7, 70, 34
END
MainDialog DIALOG 17, 32, 163, 135
CAPTION "Windows Shout"
MENU MainMenu
STYLE DS_ABSALIGN | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
BEGIN
CONTROL "", IDD_HNAME, "EDIT", ES_CENTER | WS_BORDER | WS_GROUP | WS_TABSTOP, 62, 9, 93, 12
CONTROL "", IDD_WRITE, "STATIC", SS_CENTER | SS_NOPREFIX | WS_BORDER, 7, 95, 45, 11
CONTROL "", IDD_SENT, "STATIC", SS_CENTER | WS_BORDER, 59, 95, 45, 11
CONTROL "", IDD_TIME, "STATIC", SS_CENTER | WS_BORDER, 111, 95, 45, 11
CONTROL "", IDD_WRITES, "STATIC", SS_CENTER | WS_BORDER, 7, 120, 45, 11
CONTROL "", IDD_BYTES, "STATIC", SS_CENTER | WS_BORDER, 59, 120, 45, 11
CONTROL "", IDD_BITS, "STATIC", SS_CENTER | WS_BORDER, 111, 120, 45, 11
CONTROL "writes[reads]", 105, "STATIC", SS_CENTER | WS_GROUP, 3, 85, 52, 9
CONTROL "writes[reads]/s", 105, "STATIC", SS_CENTER | WS_GROUP, 3, 111, 55, 9
CONTROL "bytes", 105, "STATIC", SS_CENTER | WS_GROUP, 61, 85, 42, 9
CONTROL "bytes/sec", 105, "STATIC", SS_CENTER | WS_GROUP, 61, 111, 42, 9
CONTROL "time (sec)", 105, "STATIC", SS_CENTER | WS_GROUP, 111, 85, 45, 9
CONTROL "bits/sec", 105, "STATIC", SS_CENTER | WS_GROUP, 113, 111, 42, 9
CONTROL "Host", IDD_COHOST, "STATIC", SS_LEFT, 7, 10, 52, 10
CONTROL "", IDD_COMMENT, "STATIC", SS_CENTER | WS_BORDER | WS_GROUP, 9, 68, 146, 11
CONTROL "&Start", IDOK, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 6, 32, 32, 20
CONTROL "Sto&p", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 65, 32, 32, 20
CONTROL "E&xit", IDM_EXIT, "BUTTON", BS_PUSHBUTTON | WS_TABSTOP, 125, 32, 32, 20
CONTROL "", -1, "static", SS_BLACKFRAME, 0, 60, 163, 1
END
SHOUT ICON wshout.ico
/*
* 错误描述字符串表
* 用于WSAsperror()函数
*/
STRINGTABLE
BEGIN
WSABASEERR, "[0] No Error"
WSAEINTR, "[10004] Interrupted system call"
WSAEBADF, "[10009] Bad file number"
WSAEACCES, "[10013] Permission denied"
WSAEFAULT, "[10014] Bad address"
WSAEINVAL, "[10022] Invalid argument"
WSAEMFILE, "[10024] Too many open files"
WSAEWOULDBLOCK, "[10035] Operation would block"
WSAEINPROGRESS, "[10036] Operation now in progress"
WSAEALREADY, "[10037] Operation already in progress"
WSAENOTSOCK, "[10038] Socket operation on non-socket"
WSAEDESTADDRREQ, "[10039] Destination address required"
WSAEMSGSIZE, "[10040] Message too long"
WSAEPROTOTYPE, "[10041] Protocol wrong type for socket"
WSAENOPROTOOPT, "[10042] Bad protocol option"
WSAEPROTONOSUPPORT, "[10043] Protocol not supported"
WSAESOCKTNOSUPPORT, "[10044] Socket type not supported"
WSAEOPNOTSUPP, "[10045] Operation not supported on socket"
WSAEPFNOSUPPORT, "[10046] Protocol family not supported"
WSAEAFNOSUPPORT, "[10047] Address family not supported by protocol family"
WSAEADDRINUSE, "[10048] Address already in use"
WSAEADDRNOTAVAIL, "[10049] Can't assign requested address"
WSAENETDOWN, "[10050] Network is down"
WSAENETUNREACH, "[10051] Network is unreachable"
WSAENETRESET, "[10052] Net dropped connection or reset"
WSAECONNABORTED, "[10053] Software caused connection abort"
WSAECONNRESET, "[10054] Connection reset by peer"
WSAENOBUFS, "[10055] No buffer space available"
WSAEISCONN, "[10056] Socket is already connected"
WSAENOTCONN, "[10057] Socket is not connected"
WSAESHUTDOWN, "[10058] Can't send after socket shutdown"
WSAETOOMANYREFS, "[10059] Too many references, can't splice"
WSAETIMEDOUT, "[10060] Connection timed out"
WSAECONNREFUSED, "[10061] Connection refused"
WSAELOOP, "[10062] Too many levels of symbolic links"
WSAENAMETOOLONG, "[10063] File name too long"
WSAEHOSTDOWN, "[10064] Host is down"
WSAEHOSTUNREACH, "[10065] No Route to Host"
WSAENOTEMPTY, "[10066] Directory not empty"
WSAEPROCLIM, "[10067] Too many processes"
WSAEUSERS, "[10068] Too many users"
WSAEDQUOT, "[10069] Disc Quota Exceeded"
WSAESTALE, "[10070] Stale NFS file handle"
WSAEREMOTE, "[10071] Too many levels of remote in path"
WSASYSNOTREADY, "[10091] Network SubSystem is unavailable"
WSAVERNOTSUPPORTED, "[10092] WINSOCK DLL Version out of range"
WSANOTINITIALISED, "[10093] Successful WSASTARTUP not yet performed"
WSAHOST_NOT_FOUND, "[11001] Host not found"
WSATRY_AGAIN, "[11002] Non-Authoritative Host not found"
WSANO_RECOVERY, "[11003] Non-Recoverable errors: FORMERR, REFUSED, NOTIMP"
WSANO_DATA, "[11004] Valid name, no data record of requested
type"
END
/* eof */
3.4.3.4 ushout.c清单
/*
* 文件名: USHOUT.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long UWriteData(SOCKET hSock, HWND hOurDlg, int send_len)
{
int counter;
static int DataBuffer[BUF_SIZE]; /* Buffer to hold generated data */
static char ReplyBuffer[512]; /* Buffer to hold any reply rcvd */
long bytes_sent = 0L; /* Counter of bytes on connection */
long total_len = 1024L*1024L; /* Total # of bytes to generate */
time_t start, end; /* variables to hold read timing */
long total_time = 0L; /* variable to hold delta t */
long write_count = 0L; /* number of times */
long tmp = 0L; /* holds count for bytes written */
long ltemp = 0L;
int i_temp;
extern int run_cancelled;
struct sockaddr_in dest; /* Destination machine address structure */
/* What makes shout unique is that it generates data*
* in memory (as opposed to accessing the disk). *
* This tests the 'raw' speed of the TCP connection *
* as the rate-limiting access time is eliminated. *
* First, generate the data and place it into an *
* array, data_buffer: */
for (counter = 0; counter < BUF_SIZE; counter++)
DataBuffer[counter] = counter;
/* Write data on the descriptor like a banshee,
* careful to time the writes and count data
* transmitted:
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Sending UDP Data ...");
time( &start );
while (bytes_sent < total_len){/* while still bytes to send */
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
tmp = send(hSock, (char FAR *) &DataBuffer, send_len, 0);
if (tmp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) /* if no data, read again */
continue;
else {
wshout_err (hOurDlg, WSAGetLastError(), "send()");
}
/* Calc. time elapsed & stats about any data sent */
time(&end);
if (total_time = (long) difftime(end, start)) {
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = write_count/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_sent/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_sent/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
/* exit from the while loop */
break;
} /* end if (total_time) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* # of bytes placed on connection */
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end if (tmp == -1) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* # of bytes placed on connection */
wsprintf((LPSTR)prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end while */
/* Look for a reply ... NOTE: most hosts won't give
* a 'reply', done to illustrate communication between
* sockets. Our ulisten example will give a reply though.
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Waiting for reply from server../n");
while (1) {
tmp = sizeof(dest);
i_temp = recvfrom(hSock,(char FAR *) &ReplyBuffer,sizeof(ReplyBuffer),
0, (struct sockaddr *) &dest, (int FAR *) &tmp);
if (i_temp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) /* if no data, read again */
continue;
else {
/* any error besides these. just punt */
wshout_err (hOurDlg, WSAGetLastError(), "recvfrom()");
}
break;
} /* end if (i_temp == SOCKET_ERROR) */
/* else got a reply ...*/
wsprintf((LPSTR)prbuf, "Server: %s/n", (LPSTR) ReplyBuffer);
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
break;
} /* end while(1) */
/* All done */
return bytes_sent;
}
/* eof */
3.4.3.5 ulisten.c清单
/*
* 文件名: ULISTEN.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long UReadData(SOCKET hSock, HWND hOurDlg, int read_len)
{
static char ReadBuf[BUF_SIZE];
static char SendBuf[512];
struct sockaddr_in local; /* Local machine address structure */
int i; /* General purpose return code */
long total_time = 0L; /* variable to hold delta t */
int tmp, len = 0;
int num_reads = 0;
long bytes_read = 0L;
long last_time, now, timeout = 15L;
long ltemp;
extern int run_cancelled;
BOOL bTemp = TRUE;
SetDlgItemText(hOurDlg, IDD_COMMENT, "Awaiting the UDP Data ...");
SetDlgItemText(hOurDlg, IDD_HNAME, " ");
time(&now); time(&last_time);
while (last_time + timeout > now) {
time(&now);
tmp = sizeof(local);
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages while available */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
len = recvfrom(hSock, ReadBuf, read_len, 0,
(struct sockaddr *) &local, &tmp);
if (len == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK) {/* if no data, read again */
continue;
} /* end: if (errno == WSAEWOULDBLOCK) */
else {
if (bytes_read) {
wshout_err (hOurDlg, WSAGetLastError(), "recvfrom()");
}
} /* end else */
break;
} /* end: if (len == SOCKET_ERROR) */
if (bTemp) { /* To update our main display once */
/* Do not use wsprintf() or you will add an extra char */
_fmemcpy(prbuf, inet_ntoa(local.sin_addr), 4*sizeof(u_long));
SetDlgItemText(hOurDlg, IDD_HNAME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_COMMENT, "Reading UDP Data ...");
bTemp = FALSE;
}
num_reads++;
if (len != SOCKET_ERROR)
bytes_read += len;
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%d/n",num_reads);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_read);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
time(&last_time);
} /* end: while */
total_time = timeout;
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = num_reads/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_read/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_read/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
if (bytes_read) {
SetDlgItemText(hOurDlg, IDD_COMMENT, "...UDP Listen Done/n");
} /* end: if (bytes_read) */
else {
wsprintf((LPSTR)prbuf, "Timed out. No data received./n");
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
goto come_here;
} /* end: else */
/* send reply to 'client' */
wsprintf((LPSTR)prbuf,
"Replied to %s/n", inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
for (i=0; i<10; ++i) {
sprintf(SendBuf, "Rec'd %ld bytes./n", bytes_read);
if(len = sendto(hSock, SendBuf, sizeof(SendBuf), 0,
(struct sockaddr FAR *)&local,sizeof(local)))
{
if (len == SOCKET_ERROR) { /* if could not send bec. */
if (h_errno == WSAEWOULDBLOCK)
continue;
wshout_err (hOurDlg, WSAGetLastError(), "sendto()");
break;
} /* end: if (len == -1) */
} /* end: if (len = sendto()) */
} /* end for */
come_here:
return (bytes_read);
}
/* eof */
3.4.3.6 tshout.c清单
/*
* 文件名: TSHOUT.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long TWriteData(SOCKET hSock, HWND hOurDlg, int send_len)
{
int counter;
static int DataBuffer[BUF_SIZE]; /* Buffer to hold generated data */
long total_len = 1024L*1024L; /* Total # of bytes to generate */
long bytes_sent = 0L; /* Counter of bytes on connection */
int tmp = 0; /* holds count for bytes written */
long write_count = 0L; /* number of times */
time_t start, end; /* variables to hold read timing */
long total_time = 0L; /* variable to hold delta t */
long ltemp = 0L;
extern int run_cancelled;
/* What makes shout unique is that it generates data*
* in memory (as opposed to accessing the disk). *
* This tests the 'raw' speed of the TCP connection *
* as the rate-limiting access time is eliminated. *
* First, generate the data and place it into an *
* array, data_buffer: */
for (counter = 0; counter < BUF_SIZE; counter++)
DataBuffer[counter] = counter;
/* Write data on the descriptor like a banshee,
* careful to time the writes and count data
* transmitted:
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "...Sending TCP Data");
time(&start);
while ( bytes_sent < total_len) { /* while still bytes to send... */
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
tmp = send(hSock, (char FAR*) &DataBuffer, send_len, 0);
if (tmp == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK)
continue;
else {
wshout_err (hOurDlg, WSAGetLastError(), "send()");
}
/* Calc. time elapsed & stats about any data sent */
time(&end);
/* exit from the while loop */
break;
} /* end if (tmp == -1) */
write_count++; /* incr. counter of times written */
bytes_sent += tmp; /* total # of bytes placed on connection*/
wsprintf(prbuf,"%ld/n",write_count);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf(prbuf,"%ld/n",bytes_sent);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
} /* end while */
time(&end);
if (total_time = (long) difftime(end, start)) {
/* Print the statistics gathered */
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = write_count/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_sent/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_sent/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
} /* end if (total_time) */
/* All done */
SetDlgItemText(hOurDlg, IDD_COMMENT, "...TCP Shout Done");
return bytes_sent;
}
/* eof */
3.4.3.7 tlisten.c清单
/*
* 文件名:TLISTEN.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
/* Returns the number of bytes written */
long TReadData(SOCKET hSock, HWND hOurDlg, int read_len)
{
static char ReadBuf[BUF_SIZE];
SOCKET hAcceptSock;
struct sockaddr_in local; /* Local machine address structure */
long total_time = 0L; /* variable to hold delta t */
int tmp, len = 0;
int num_reads = 0;
long bytes_read = 0L;
long last_time = 0L;
long now = 0L;
long ltemp;
extern long blocking_option;
extern int run_cancelled;
struct linger AcceptLinger;
BOOL running = FALSE;
BOOL bTemp = TRUE;
SetDlgItemText(hOurDlg, IDD_COMMENT, "Awaiting the TCP Data ...");
SetDlgItemText(hOurDlg, IDD_HNAME, " ");
tmp = sizeof(local);
if (!blocking_option) {
hAcceptSock = accept(hSock,(struct sockaddr FAR *)&local,
(int FAR *)&tmp);
}
else {
for (; {
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages if any */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
hAcceptSock = accept(hSock,(struct sockaddr FAR *)&local,
(int FAR *)&tmp);
if (hAcceptSock == INVALID_SOCKET) {
if (h_errno == WSAEWOULDBLOCK)
/* Try again */
;
else {
/* Fatal error -- pop out. */
break;
}
} /* end if ((hAcceptSock = .. */
else {
/* Success -- pop out. */
break;
}
} /* end for */
} /* end else */
if (hAcceptSock == INVALID_SOCKET) {
wshout_err (hOurDlg, WSAGetLastError(), "accept()");
return 0;
}
/* Now, read the data as fast as we can until no more to read */
time(&last_time);
do {
do {
;
} while (ShoutBlockingHook()); /* Dispatch messages while available */
if (run_cancelled) {
WSASetLastError(WSAEINTR);
break; /* Non-blocking mode was cancelled */
}
len = recv(hAcceptSock, ReadBuf, read_len, 0);
if (len == SOCKET_ERROR) {
if (h_errno == WSAEWOULDBLOCK)
continue;
else
break;
}
else if (len == 0)
break;
num_reads++;
bytes_read += len;
wsprintf((LPSTR)prbuf,"%d/n",num_reads);
SetDlgItemText(hOurDlg, IDD_WRITE, (LPSTR) prbuf);
wsprintf((LPSTR)prbuf,"%ld/n",bytes_read);
SetDlgItemText(hOurDlg, IDD_SENT, (LPSTR) prbuf);
if (bTemp) { /* To update our main display once */
/* Do not use wsprintf() or you will add an extra char */
_fmemcpy(prbuf, inet_ntoa(local.sin_addr), 4*sizeof(u_long));
SetDlgItemText(hOurDlg, IDD_HNAME, (LPSTR) prbuf);
SetDlgItemText(hOurDlg, IDD_COMMENT, "Reading TCP Data ...");
bTemp = FALSE;
}
} while ((len != 0) || (len != SOCKET_ERROR));
time (&now);
if (len == SOCKET_ERROR) {
if ((h_errno == WSAESHUTDOWN) || (h_errno == WSAENOTCONN)) {
/* nothing available for read. */
wsprintf((LPSTR)prbuf,
"Connection from %s closed./n",inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
}
else { /* Other error */
wshout_err (hOurDlg, WSAGetLastError(), "recv()");
}
}
else if (len == 0) {
/* Other side shut down the connection */
wsprintf((LPSTR)prbuf,
"Connection from %s closed./n",inet_ntoa(local.sin_addr));
SetDlgItemText(hOurDlg, IDD_COMMENT, prbuf);
}
AcceptLinger.l_onoff = 1;
AcceptLinger.l_linger = 0;
ret = setsockopt(hAcceptSock, SOL_SOCKET, SO_LINGER,
(char FAR *) &AcceptLinger, sizeof(AcceptLinger));
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "setsockopt()");
}
ret = closesocket(hAcceptSock);
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "closesocket()");
}
total_time = (long) difftime(now, last_time);
if (total_time == 0)
total_time = 1L; /* Avoid dividing by zero */
wsprintf((LPSTR)prbuf,"%ld/n",total_time);
SetDlgItemText(hOurDlg, IDD_TIME, (LPSTR) prbuf);
ltemp = num_reads/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_WRITES,(LPSTR) prbuf);
ltemp = bytes_read/total_time;
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BYTES, (LPSTR) prbuf);
ltemp = 8 * (bytes_read/total_time);
wsprintf((LPSTR)prbuf,"%ld/n", ltemp);
SetDlgItemText(hOurDlg, IDD_BITS, (LPSTR) prbuf);
if (bytes_read) {
SetDlgItemText(hOurDlg, IDD_COMMENT, "...TCP Listen Done/n");
} /* end: if (bytes_read) */
return (bytes_read);
}
/* eof */
3.4.3.8 errno.c清单
#include <windows.h>
#include <winsock.h>
/*
* 文件名: ERRNO.C
*/
/*
* Function: WSAsperror()
*
* Description:
*
* Copies string corresponding to the error code provided
* into buf, maximum length len. Returns length actually
* copied to buffer, or zero if error code is unknown.
* String resources should be present for each error code
* using the value of the code as the string ID (except for
* error = 0, which is mapped to WSABASEERR to keep it with
* the others). The DLL is free to use any string IDs that
* are less than WSABASEERR for its own use.
*
*/
int PASCAL FAR WSAsperror (HANDLE hInst, /* Instance Handle */
int errorcode, /* WSA Error Number */
char far * buf, /* Buffer for error string */
int len) /* Length of buffer */
{
int err_len; /* length of error text */
if (errorcode == 0) /* If error passed is 0, use the */
errorcode = WSABASEERR; /* base resource file number */
if (errorcode < WSABASEERR) /* If invalid Error code */
return 0; /* return string length of zero */
/* error string from the table in the Resource file into buffer */
err_len = LoadString(hInst,errorcode,buf,len);
return (err_len); /* return length of error string retrieved */
} /* end WSAsperror() */
/* eof */
3.4.3.9 resolve.c清单
/*
* 文件名: RESOLVE.C
*/
#include "wshout.h"
/* MSC Include files: */
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
SOCKET
ResolveAndConnectHost(LPSTR lpHostName,HWND hOurDlg,int iproto, int iSockPort)
{
struct hostent FAR *host_ptr; /* Ptr to the host name */
struct sockaddr_in dest; /* Addr of target host */
SOCKET hSock; /* The socket to create */
int iSockType;
extern int iTCP;
extern int iUDP;
/* Internet family addressing */
dest.sin_family = PF_INET;
if (iproto == iTCP) {
iSockType = SOCK_STREAM;
}
else if (iproto == iUDP) {
iSockType = SOCK_DGRAM;
}
else {
return (SOCKET) -1; /* Unknown protocol */
}
/* default port to connect to. Must be in network byte order */
dest.sin_port = htons((u_int) iSockPort);
SetDlgItemText(hOurDlg, IDD_COMMENT,"Resolving hostname...");
/* Resolve the host name */
host_ptr = gethostbyname(lpHostName);
if (host_ptr == NULL) {
wshout_err (hOurDlg, WSAGetLastError(), "gethostbyname()");
return (SOCKET) -1;
}
/* Patch host address into struct describing conn: */
bcopy(host_ptr->h_addr,&dest.sin_addr,host_ptr->h_length);
/* Allocate a network (socket) descriptor: */
hSock = socket(PF_INET, iSockType, 0);
if (hSock == INVALID_SOCKET) {
wshout_err (hOurDlg, WSAGetLastError(), "socket()");
return (SOCKET) -1;
}
/* Start connection process to host described in 'dest' *
* struct.
*/
SetDlgItemText(hOurDlg, IDD_COMMENT, "Connecting ...");
ret=connect(hSock,(struct sockaddr FAR *)&dest,sizeof(dest));
if (ret == SOCKET_ERROR) {
wshout_err (hOurDlg, WSAGetLastError(), "connect()");
closesocket(hSock);
return (SOCKET) -1;
}
SetDlgItemText(hOurDlg, IDD_COMMENT, "...Connected");
return hSock;
}
SOCKET GetSocketAndBind(HWND hOurDlg, int iProto, int iSockPort)
{
SOCKET hSock; /* Connection socket descriptor */
struct sockaddr_in local; /* Local machine address structure*/
int iSockType;
extern int iTCP;
extern int iUDP;
/* Internet family addressing */
if (iProto == iTCP) {
iSockType = SOCK_STREAM;
}
else {
iSockType = SOCK_DGRAM;
}
memset(&local, '/0', sizeof (local));
local.sin_family = PF_INET;
local.sin_port = htons((u_short)iSockPort);
/* allocate a socket descriptor */
hSock = socket(PF_INET, iSockType, 0);
if (hSock == INVALID_SOCKET) { /* socket() failed */
wshout_err (hOurDlg, WSAGetLastError(), "socket()");
return (SOCKET) -1;
}
/* bind socket to a local addr */
ret = bind(hSock, (struct sockaddr FAR *) &local, sizeof(local));
if (ret == SOCKET_ERROR){ /* bind() failed */
wshout_err (hOurDlg, WSAGetLastError(), "bind()");
return (SOCKET) -1;
}
if (iProto == iUDP)
return (hSock);
/* If iProto == iTCP, then must listen() and accept() also */
ret = listen(hSock, 0); /* listen on the socket */
if (ret == SOCKET_ERROR){ /* listen() failed */
wshout_err (hOurDlg, WSAGetLastError(), "listen()");
return (SOCKET) -1;
}
return(hSock);
}
/* eof */