套接口网络编程原理

套接口有三种类型:流式套接口,数据报套接口及原始套接口.

流式套接口定义了一种可靠的面向连接的服务,实现了无差错无重复的顺序数据传输.数据报套接口定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错.原始套接口允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实现的测试等.

无连接服务器一般都是面向事务处理的,一个请求一个应答就完成了客户程序与服务程序之间的相互作用。若使用无连接的套接口编程,程序的流程可以用图3-1表示。

服务器

套接口网络编程原理 - 图1

套接口网络编程原理 - 图2

套接口网络编程原理 - 图3套接口网络编程原理 - 图4阻塞,等待客户数据

处理服务请求

套接口网络编程原理 - 图5

服务请求

套接口网络编程原理 - 图6套接口网络编程原理 - 图7服务应答

套接口网络编程原理 - 图8套接口网络编程原理 - 图9客户机

套接口网络编程原理 - 图10

套接口网络编程原理 - 图11

图 3-1 无连接套接口应用程序时序图

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

服务器

套接口网络编程原理 - 图12

套接口网络编程原理 - 图13

套接口网络编程原理 - 图14

套接口网络编程原理 - 图15

套接口网络编程原理 - 图16套接口网络编程原理 - 图17套接口网络编程原理 - 图18套接口网络编程原理 - 图19阻塞,等待客户数据

处理服务请求

套接口网络编程原理 - 图20图 3-2 面向连接套接口应用程序时序图

客户机

套接口网络编程原理 - 图21

套接口网络编程原理 - 图22

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

Windows Sockets 编程原理

由于Windows的基于消息的特点,WINSOCK和BSD套接口相比,有如下一些新的扩充:

  1. 异步选择机制

异步选择函数WSAAsyncSelect()允许应用程序提名一个或多个感兴趣的网络事件,如FD_READ,FD_WRITE,FD_CONNECT,FD_ACCEPT等等代表的网络事件.当

被提名的网络事件发生时,Windows应用程序的窗口函数将收到一个消息.这样就可以实现事件驱动了.

  1. 异步请求函数

异步请求函数允许应用程序用异步方式获得请求的信息,如WSAAsyncGetXByY()类函数. 这些函数是对BSD标准函数的扩充.函数WSACancelAsyncRequest()允许用户中止一个正在执行的异步请求.

  1. 阻塞处理方法

WINSOCK提供了"钩子函数"负责处理Windows消息,使Windows的消息循环能够继续.WINSOCK提供了两个函数(WSASetBlockingHook()和WSAUnhookBlockingHook())让应用程序设置或取消自己的"钩子函数".函数WSAIsBlocking()可以检测是否阻塞,函数WSACancelBlockingCall()可以取消一个阻塞的调用.

  1. 错误处理

WINSOCK提供了两个WSAGetLastError()和WSASetLastError()来获取和设置最近错误号.

  1. 启动和终止

由于Windows Sockets的服务是以动态连接库WINSOCK.DLL形式实现的, 所以必须要先调用WSAStartup()函数对Windows Sockets DLL进行初始化,协商WINSOCK的版本支持,并分配必要的资源.在应用程序关闭套接口后,还应调用WSACleanup()终止对Windows Sockets DLL的使用,并释放资源,以备下一次使用.

在这些函数中,实现Windows网络实时通信的关键是异步选择函数WSAAsyncSelect()的使用. 用法及详细说明参见第5.3.7.

Windows Sockets 与 UNIX 套接口编程实例

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

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);

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,并释放资源.

源程序清单

程序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[102 3]);

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");

}

另一个精巧的应用程序实例-wshout

在本节中,我们通过一个经过精心选择的例子,进一步讨论一下 Windows Sockets 编程技术。例如如何编制客户机或服务器程序,如何应用 TCP 有连接服务(流式套接口)或 UDP 无连接服务(数据报套接口),如何进行阻塞或非阻塞方式的套接口操作等等,这些都是经常碰到的问题。接下来要介绍的 wshout 程序,可以通过灵活地设置不同选项来达到上述应用情况的任意组合,从而基本覆盖了应用 Windows Sockets 编程所可能碰到的问题,具有很好的研究参考价值。

由于该程序思路清晰,结构精良,所以我们不打算很详细地剖析每一个语 句,而只是简要介绍一下整个程序的逻辑结构,并在源程序中加入适当的注释。我们相信,任何具有基本 C 语言和 Windows 编程经验的读者,都能很轻松地读懂绝大部分内容。经过仔细咀嚼和推敲后,更能得到一些编写优质程序的灵感。

该程序在 FTP 公司的 PCTCP 支撑环境下调试通过,不过只要读者拥有任何符合 Windows Sockets 1.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-3 w shout程序逻辑结构图

  1. 源程序清单及注释

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

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

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", B S_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 */

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

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

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

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

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

*/

zero */

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

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

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