套接口网络编程原理
套接口有三种类型:流式套接口,数据报套接口及原始套接口.
流式套接口定义了一种可靠的面向连接的服务,实现了无差错无重复的顺序数据传输.数据报套接口定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证可靠,无差错.原始套接口允许对低层协议如IP或ICMP直接访问,主要用于新的网络协议实现的测试等.
无连接服务器一般都是面向事务处理的,一个请求一个应答就完成了客户程序与服务程序之间的相互作用。若使用无连接的套接口编程,程序的流程可以用图3-1表示。
服务器
阻塞,等待客户数据
处理服务请求
服务请求
服务应答
客户机
图 3-1 无连接套接口应用程序时序图
面向连接服务器处理的请求往往比较复杂,不是一来一去的请求应答所能解决的,而且往往是并发服务器。使用面向连接的套接口编程,可以通过图3-1来表示:其时序。
服务器
阻塞,等待客户数据
处理服务请求
图 3-2 面向连接套接口应用程序时序图
客户机
套接口工作过程如下:服务器首先启动,通过调用socket()建立一个套接口, 然后调用bind()将该套接口和本地网络地址联系在一起,再调用listen()使套接口做好侦听的准备,并规定它的请求队列的长度,之后就调用accept()来接收连接.客户在建立套接口后就可调用connect()和服务器建立连接.连接一旦建立, 客户机和服务器之间就可以通过调用read()和write()来发送和接收数据.最后, 待数据传送结束后,双方调用close()关闭套接口.
Windows Sockets 编程原理
由于Windows的基于消息的特点,WINSOCK和BSD套接口相比,有如下一些新的扩充:
- 异步选择机制
异步选择函数WSAAsyncSelect()允许应用程序提名一个或多个感兴趣的网络事件,如FD_READ,FD_WRITE,FD_CONNECT,FD_ACCEPT等等代表的网络事件.当
被提名的网络事件发生时,Windows应用程序的窗口函数将收到一个消息.这样就可以实现事件驱动了.
- 异步请求函数
异步请求函数允许应用程序用异步方式获得请求的信息,如WSAAsyncGetXByY()类函数. 这些函数是对BSD标准函数的扩充.函数WSACancelAsyncRequest()允许用户中止一个正在执行的异步请求.
- 阻塞处理方法
WINSOCK提供了"钩子函数"负责处理Windows消息,使Windows的消息循环能够继续.WINSOCK提供了两个函数(WSASetBlockingHook()和WSAUnhookBlockingHook())让应用程序设置或取消自己的"钩子函数".函数WSAIsBlocking()可以检测是否阻塞,函数WSACancelBlockingCall()可以取消一个阻塞的调用.
- 错误处理
WINSOCK提供了两个WSAGetLastError()和WSASetLastError()来获取和设置最近错误号.
- 启动和终止
由于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 规范的实现,也能顺利执行该程序。
源程序目录
-
wshout.c wshout 主程序
-
wshout.h wshout 头文件
-
wshout.rc wshout 资源文件
-
ushout.c UDP 客户机程序
-
ulisten.c UDP 服务器程序
-
tshout.c TCP 客户机程序
-
tlisten.c TCP 服务器程序
-
errno.c 获取 WSAE*错误描述字符串程序
-
resolve.c 客户机/服务器启动程序
在编译本程序时,笔者用的是 BC3.1,只需做一个 PRJ 工程文件,将上述.c 文件及 winsock.lib 包括进来就行了。请注意 winsock.h 应在 include 目录或当前目录中,winsock.lib 可利用 winsock.dll 通过 implib 工具来建立。如果读者使用其他的编译器,可自行作相应的调整,在此不再赘述。
程序逻辑结构
图 3-3 w shout程序逻辑结构图
-
源程序清单及注释
-
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 */