论坛: 编程破解 标题: Windows Sockets 规范及应用(第三章 Windows Sockets 1.1应用实例) 复制本贴地址    
作者: xiaoxingchi [xiaoxingchi]    论坛用户   登录
第三章 Windows Sockets 1.1应用实例
在本章中,作者的实际工作为背景,给出了一个使用Windows Sockets 1.1编程的具体例子。并对这个例子作了详细的分析。这个例子在Windows 3.1、Windows Sockets 1.1和BSD OS for PC 2.0(BSD UNIX微机版)环境下调试通过。

3.1 套接口网络编程原理
套接口有三种类型:流式套接口,数据报套接口及原始套接口.
流式套接口定义了一种可靠的面向连接的服务,实现了无差错无重复的顺序数据传输.数据报套接口定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错.原始套接口允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实现的测试等.
无连接服务器一般都是面向事务处理的,一个请求一个应答就完成了客户程序与服务程序之间的相互作用。若使用无连接的套接口编程,程序的流程可以用图3-1表示。


面向连接服务器处理的请求往往比较复杂,不是一来一去的请求应答所能解决的,而且往往是并发服务器。使用面向连接的套接口编程,可以通过图3-1来表示:其时序。



套接口工作过程如下:服务器首先启动,通过调用socket()建立一个套接口,然后调用bind()将该套接口和本地网络地址联系在一起,再调用listen()使套接口做好侦听的准备,并规定它的请求队列的长度,之后就调用accept()来接收连接.客户在建立套接口后就可调用connect()和服务器建立连接.连接一旦建立,客户机和服务器之间就可以通过调用read()和write()来发送和接收数据.最后,待数据传送结束后,双方调用close()关闭套接口.

3.2 Windows Sockets编程原理
由于Windows的基于消息的特点,WINSOCK和BSD套接口相比,有如下一些新的扩充:
1.异步选择机制
异步选择函数WSAAsyncSelect()允许应用程序提名一个或多个感兴趣的网络事件,如FD_READ,FD_WRITE,FD_CONNECT,FD_ACCEPT等等代表的网络事件.当被提名的网络事件发生时,Windows应用程序的窗口函数将收到一个消息.这样就可以实现事件驱动了.
2.异步请求函数
异步请求函数允许应用程序用异步方式获得请求的信息,如WSAAsyncGetXByY()类函数. 这些函数是对BSD标准函数的扩充.函数WSACancelAsyncRequest()允许用户中止一个正在执行的异步请求.
3.阻塞处理方法
WINSOCK提供了"钩子函数"负责处理Windows消息,使Windows的消息循环能够继续.WINSOCK提供了两个函数(WSASetBlockingHook()和WSAUnhookBlockingHook())让应用程序设置或取消自己的"钩子函数".函数WSAIsBlocking()可以检测是否阻塞,函数WSACancelBlockingCall()可以取消一个阻塞的调用.
4.错误处理
WINSOCK提供了两个WSAGetLastError()和WSASetLastError()来获取和设置最近错误号.
5.启动和终止
由于Windows Sockets的服务是以动态连接库WINSOCK.DLL形式实现的,所以必须要先调用WSAStartup()函数对Windows Sockets DLL进行初始化,协商WINSOCK的版本支持,并分配必要的资源.在应用程序关闭套接口后,还应调用WSACleanup()终止对Windows Sockets DLL的使用,并释放资源,以备下一次使用.
在这些函数中,实现Windows网络实时通信的关键是异步选择函数WSAAsyncSelect()的使用. 用法及详细说明参见第5.3.7.

3.3 Windows Sockets与UNIX套接口编程实例
下面是一个简单的基于连接的点对点实时通信程序.它由两部分组成,服务器在主机UNIX下直接运行, 客户机在Windows下运行.

3.3.1 SERVER介绍
由于SERVER是在UNIX下运行的,它对套接口的使用都是BSD的标准函数,程序也比较简单, 只有一段程序,下面简要解释一下.
首先,建立自己的套接口.在互连网的进程通信中,全局标识一个进程需要一个被称为"半相关"的三元组(协议,本地主机地址,本地端口号)来描述,而一个完整的进程通信实例则需要一个被称为"相关"的五元组(协议, 本地主机地址,本地端口号,远端主机地址,远端端口号)来描述.
s=socket(AF_INET, SOCK_STREAM, 0)
该函数建立指定地址格式,数据类型和协议下的套接口,地址格式为AF_INET(唯一支持的格式),数据类型SOCK_STREAM表示建立流式套接口,参数三为0,即协议缺省.
bind(s, (struct sockaddr *)&server, sizeof(server))
该函数将建立服务器本地的半相关,其中,server是sockaddr_in结构,其成员描述了本地端口号和本地主机地址,经过bind()将服务器进程在网上标识出来.
然后,建立连接.先是调用listen()函数表示开始侦听.再通过accept()调用等待接收连接.
listen(s,1)表示连接请求队列长度为1,即只允许有一个请求,若有多个请求,则出现错误,给出错误代码WSAECONNREFUSED.
ns = accept(s, (struct sockaddr *)&client, &namelen)) 
accept()阻塞(缺省)等待请求队列中的请求,一旦有连接请求来,该函数就建立一个和s有相同属性的新的套接口.client也是一个sockaddr_in结构,连接建立时填入请求连接的套接口的半相关信息.
接下来,就可以接收和发送数据了.
recv(ns,buf,1024,0)
send(ns,buf,pktlen,0)
上面两个函数分别负责接收和发送数据,recv从ns(建立连接的套接口)接收数据放入buf中,send则将buf中数据发送给ns.至于第四个参数,表示该函数调用方式,可选择MSG_DONTROUTE和MSG_OOB, 0表示缺省.
最后,关闭套接口.
close(ns);
close(s);

3.3.2 CLIENT介绍
客户端是在Windows上运行的,使用了一些Windows Sockets的扩展函数,稍微复杂一些.包括了.RC和.C两个文件,其中的主窗口函数ClientProc()是程序的主要部分,下面简单解释一下.
首先,是在WinMain()中建立好窗口后,即向主窗口函数发一条自定义的WM_USER消息, 做相关的准备工作.在主窗口函数中,一接收到WM_USER消息,首先调用WSAStartup()函数初始化Windows Sockets DLL,并检查版本号.如下:
Status = WSAStartup(VersionReqd, lpmyWSAData);
其中,VersionReqd描述了WINSOCK的版本(这里为1.1版),lpmyWSAData指向一个WSADATA结构,该结构描述了Windows Sockets的实现细节.
WSAStartup()之后,进程通过主机名(运行时命令行参数传入)获取主机地址,如下:
hostaddr = gethostbyname(server_address);
hostaddr指向hostent结构,内容参见5.2.1.
然后,进程就不断地消息循环,等待用户通过菜单选择"启动".这时,通过调用Client()来启动套接口.在Client()中,首先也是调用socket()来建立套接口.如下:
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
AlertUser(hWnd, "Socket Failed");
return (FALSE);
}
紧接着,调用WSAAsyncSelect()函数提名FD_CONNECT网络事件,如下: 
if (!SetSelect(hWnd, FD_CONNECT))
return (FALSE);
SetSelect()主要就是调用WSAASyncSelect(),让Windows Sockets DLL在侦测到连接建立时,就发送一条UM_SOCK的自定义消息,使消息循环继续下去.如下:
BOOL SetSelect(HWND hWnd, long lEvent)
{
if (WSAAsyncSelect(s, hWnd, UM_SOCK, lEvent) == SOCKET_ERROR)
{
AlertUser(hWnd, "WSAAsyncSelect Failure.");
return (FALSE);
}
return (TRUE);
}
为建立连接,必须马上调用connect()如下,由于先调用了WSAASyncSelect(),connect()便是非阻塞调用.进程发出连接请求后就不管了,当连接建立好后,WINSOCK DLL自动发一条消息给主窗口函数,以使程序运行下去.
connect(s, (struct sockaddr FAR *)&dst_addr, sizeof(dst_addr));
窗口函数在收到UM_SOCK消息后,判断是由哪个网络事件引起的,第一次,必然是由连接事件引起的,这样,就会执行相应的程序段,同样调用SetSelect()来提名FD_WRITE事件.希望在套接口可发送数据时接到消息.在收到FD_WRITE消息时,先调用send()发送数据,再调用SetSelect()来提名FD_READ事件, 希望在套接口可接收数据是接到消息.在收到FD_READ消息时,先调用recv()来接收数据再提名FD_WRITE事件,如此循环下去.直到发生连接关闭的事件FD_CLOSE,这时就调用WSAAsyncSelect(s,hWnd,0,0)来停止异步选择.在窗口函数接到WM_DESTROY消息时(即关闭窗口之前),先调用closesocket()(作用同UNIX 中的close())来关闭套接口,再调用WSACleanup()终止Windows Sockets DLL,并释放资源.
3.3.3 源程序清单
程序1:CLIENT.RC
ClientMenu MENU
BEGIN
POPUP "&Server"
BEGIN
MENUITEM "&Start...", 101
MENUITEM "&Exit", 102
END
END

程序2:CLIENT.C
#define USERPORT 10001
#define IDM_START 101
#define IDM_EXIT 102
#define UM_SOCK WM_USER + 0X100

#include <alloc.h>
#include <mem.h>
#include <windows.h>
#include <winsock.h>
#define MAJOR_VERSION 1
#define MINOR_VERSION 2
#define WSA_MAKEWORD(x,y) ((y)*256+(x))

HANDLE hInst;
char server_address[256] = {0};
char buffer[1024];
char FAR * lpBuffer = &buffer[0];
SOCKET s = 0;
struct sockaddr_in dst_addr;
struct hostent far *hostaddr;
struct hostent hostnm;
struct servent far *sp;
int count = 0;

BOOL InitApplication(HINSTANCE hInstance);
long FAR PASCAL ClientProc(HWND hWnd, unsigned message, UINT wParam, LONG lParam);
void AlertUser(HWND hWnd, char *message);

BOOL Client(HWND hWnd);
BOOL ReceivePacket(HWND hWnd);
BOOL SetSelect(HWND hWnd, long lEvent);
BOOL SendPacket(HWND hWnd, int len);

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;

lstrcpy((LPSTR)server_address, lpCmdLine);
if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);
hInst = hInstance;
hWnd = CreateWindow("ClientClass", "Windows ECHO Client", WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,\
hInstance, NULL);
if (!hWnd)
return (FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
PostMessage(hWnd, WM_USER, (WPARAM)0, (LPARAM)0);
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}

BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS WndClass;

char *szAppName = "ClientClass";
// fill in window class information

WndClass.lpszClassName = (LPSTR)szAppName;
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = ClientProc;
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(hInstance, NULL);
WndClass.lpszMenuName = "ClientMenu";
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.style = CS_HREDRAW | CS_VREDRAW;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;

// register the class

if (!RegisterClass(&WndClass))
return(FALSE);

return(TRUE);
}

long FAR PASCAL ClientProc(HWND hWnd, unsigned message, UINT wParam, LONG lParam)
{
int length, i;
WSADATA wsaData;

int Status;

switch (message)
{
case WM_USER:
{
WORD wMajorVersion, wMinorVersion;
LPWSADATA lpmyWSAData;
WORD VersionReqd;
int ret;

wMajorVersion = MAJOR_VERSION;
wMinorVersion = MINOR_VERSION;
VersionReqd = WSA_MAKEWORD(wMajorVersion,wMinorVersion);

lpmyWSAData = (LPWSADATA)malloc(sizeof(WSADATA));
Status = WSAStartup(VersionReqd, lpmyWSAData);
if (Status != 0)
{
AlertUser(hWnd, "WSAStartup() failed\n");
PostQuitMessage(0);
}
hostaddr = gethostbyname(server_address);
if (hostaddr == NULL)
{
AlertUser(hWnd, "gethostbyname ERROR!\n");
WSACleanup();
PostQuitMessage(0);
}
_fmemcpy(&hostnm, hostaddr, sizeof(struct hostent));
}
break;
case WM_COMMAND:
switch (wParam)
{
case IDM_START:
if (!Client(hWnd))
{
closesocket(s);
AlertUser(hWnd, "Start Failed");
}
break;
case IDM_EXIT:
// WSACleanup();
PostQuitMessage(0);
break;
}
break;
case UM_SOCK:
switch (lParam)
{
case FD_CONNECT:
if (!SetSelect(hWnd, FD_WRITE))
closesocket(s);
break;
case FD_READ:
if (!ReceivePacket(hWnd))
{
AlertUser(hWnd, "Receive Packet Failed.\n");
closesocket(s);
break;
}
if (!SetSelect(hWnd, FD_WRITE))
closesocket(s);
break;
case FD_WRITE:
for (i = 0; i < 1024; i ++)
buffer[i] = (char)'A' + i % 26;
length = 1024;
if (!SendPacket(hWnd, length))
{
AlertUser(hWnd, "Packet Send Failed!\n");
closesocket(s);
break;
}
if (!SetSelect(hWnd, FD_READ))
closesocket(s);
break;
case FD_CLOSE:
if (WSAAsyncSelect(s, hWnd, 0, 0) == SOCKET_ERROR)
AlertUser(hWnd, "WSAAsyncSelect Failed.\n");
break;
default:
if (WSAGETSELECTERROR(lParam) != 0)
{
AlertUser(hWnd, "Socket Report Failure.");
closesocket(s);
break;
}
break;
}
break;
case WM_DESTROY:
closesocket(s);
WSACleanup();
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return(NULL);
}

void AlertUser(HWND hWnd, char *message)
{
MessageBox(hWnd, (LPSTR)message, "Warning", MB_ICONEXCLAMATION);
return;
}

BOOL Client(HWND hWnd)
{
memset(&dst_addr,'\0', sizeof (struct sockaddr_in));
_fmemcpy((char FAR *)&dst_addr.sin_addr,(char FAR *)hostnm.h_addr,hostnm.h_length);
dst_addr.sin_family = hostnm.h_addrtype;
dst_addr.sin_port = htons(USERPORT);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
AlertUser(hWnd, "Socket Failed");
return (FALSE);
}
if (!SetSelect(hWnd, FD_CONNECT))
return (FALSE);
connect(s, (struct sockaddr FAR *)&dst_addr, sizeof(dst_addr));
return (TRUE);
}


BOOL ReceivePacket(HWND hWnd)
{
HDC hDc;
int length;
int i1,i2,i3;
char line1[255], line2[255], line3[255];

count ++;
if ((length = recv(s, lpBuffer, 1024, 0)) == SOCKET_ERROR)
return (FALSE);
if (length == 0)
return (FALSE);
if (hDc = GetDC(hWnd))
{
i1 = wsprintf((LPSTR)line1, "TCP Echo Client No.%d", count);
i2 = wsprintf((LPSTR)line2, "Receive %d bytes",length);
i3 = wsprintf((LPSTR)line3, "Those are:%c, %c, %c, %c, %c, %c",buffer[0],buffer[1],buffer[2],buffer[100],buffer[1000],buffer[1023]);
TextOut(hDc, 10, 2, (LPSTR)line1, i1);
TextOut(hDc, 10, 22, (LPSTR)line2, i2);
TextOut(hDc, 10, 42, (LPSTR)line3, i3);
ReleaseDC(hWnd, hDc);
}
return (TRUE);
}

BOOL SetSelect(HWND hWnd, long lEvent)
{
if (WSAAsyncSelect(s, hWnd, UM_SOCK, lEvent) == SOCKET_ERROR)
{
AlertUser(hWnd, "WSAAsyncSelect Failure.");
return (FALSE);
}
return (TRUE);
}

BOOL SendPacket(HWND hWnd, int len)
{
int length;

if ((length = send(s, lpBuffer, len, 0)) == SOCKET_ERROR)
return (FALSE);
else
if (length != len)
{
AlertUser(hWnd, "Send Length NOT Match!");
return (FALSE);
}
return (TRUE);
}

程序3:SERVER.C
#include <sys/types.h>
#include <sys/mntent.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define USERPORT 10001
#define HOST_IP_ADDR "192.1.1.2"

main(int argc, char **argv)
{
char buf[1024];
struct sockaddr_in client;
struct sockaddr_in server;

int s;
int ns;
int namelen;
int pktlen;

if ((s=socket(AF_INET, SOCK_STREAM, 0))<0)
{
perror("Socket()");
return;
}
bzero((char *)&server,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(USERPORT);
server.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr *)&server, sizeof(server))<0)
{
perror("Bind()");
return;
}
if (listen(s,1)!=0)
{
perror("Listen()");
return;
}
namelen = sizeof(client);
if ((ns = accept(s, (struct sockaddr *)&client, &namelen)) ==-1)
{
perror("Accept()");
return;
}
for (;;)
{
if ((pktlen = recv(ns,buf,1024,0))<0)
{
perror("Recv()");
break;
}
else
if (pktlen == 0)
{
printf("Recv():return FAILED,connection is shut down!\n");
break;
}
else
printf("Recv():return SUCCESS,packet length = %d\n",pktlen);
sleep(1);
if (send(ns,buf,pktlen,0)<0)
{
perror("Send()");
break;
}
else
printf("Send():return SUCCESS,packet length = %d\n",pktlen);
}
close(ns);
close(s);
printf("Server ended successfully\n");
}

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) ((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 */



地主 发表时间: 04/29 08:38

论坛: 编程破解

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号