一、初始化和释放套接字库
用户在工程设置中,可以修改或添加库模板,在库模板中添加动态链接库WS2_32.dll,这样在程序中能调用winsock函数。
注:用户必须首先从动态链接库中调用函数WSAstartup()对该库进行初始化,之后才能从该库中继续正确调用其他Winsock函数,否则,就会出现错误。
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSADate);
typedef struct WSAData { WORD wVersion; WORD wHighVersion; //库文件支持的最高版本 char szDescription[WSADESCRIPTION_LEN + 1]; //描述库文件的字符串 char szSystemStatus[WSASYS_STATUS_LEN + 1]; //系统状态字符串 unsigned short iMaxSockets; //同时支持的最大套接字字数 unsigned short iMaxUdpDg; //已废弃 char FAR * lpVendorInfo; //已废弃 }WSADATA, FAR * LPWSADATA;
WSAData data; //定义WSAData变量 WORD wVersionRequested = MAKEWORD(2, 0); //定义套接字库的版本号 ::WSAStartup(wVersionRequested, &data); //初始化套接字库
::WSACleanup();
二、创建套接字句柄
在Socket API中,创建套接字句柄的函数是socket(),函数原型如下:
SOCKET socket { int af; //指定套接字所使用的地址格式 int type; //套接字类型 int protocol; //如果参数type已经指定套接字类型为TCP或UDP,则该参数可以设置为0 };该函数执行成功,将返回新创建的套接字句柄,否则将返回INVALID_SOCKET表示失败。
例如,创建流式套接字的句柄。
SOCKET s; s = ::socket(AF_INET, SOCK_STREAM, 0);
对于服务器而言,套接字创建成功后,还应该将套接字与地址结构信息相关联。函数Bind()。
int bind( SOCKET s, //套接字句柄 const struct sockaddr FAR* name, //地址结构信息 int namelen //地址结构大小 );
例如将套接字句柄绑定到本地地址,代码如下:
sockaddr_in addr; //定义套接字地址结构变量 in_addr in_add; //定义IP地址结构变量 addr.sin_family = AF_INET; //指定地址家族为TCP/IP addr.sin_port = htons(80); //指定端口号 addr.sin_addr.S_un.S_addr = INADDR_ANY;//表示服务器能接收任何计算机发过来的请求 ::bind(s, (sockaddr)&addr, sizeof(addr));//绑定套接字到指定地址结构当服务器程序将套接字句柄绑定套接字地址成功时,则调用函数Listen()实现监听端口的功能。
int listen( SOCKET s, //实现监听功能的套接字句柄 int backlog //指定监听的最大连接数量 );该函数仅用于流式套接字。如果多个客户端同时向服务器发出连接请求,并以及超过了最大监听数,则客户端将返回错误代码。
四、连接
客户端程序连接服务器使用函数connect()实现
int connect( SOCKET s, //套接字句柄 const struct sockaddr FAR* name, //将要连接的服务器地址信息结构指针 int namelen //地址信息结构体长度 )例如,客户端使用该函数连接地址为“127.0.0.1”,端口为80的服务器。
sockaddr_in addr; in_addr in_add; addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //指定服务器地址 SOCKET s; //定义套接字句柄 s = ::socket(AF_INET, SOCK_STREAM, 0); //创建并返回套接字句柄 ::connect(s, (sockaddr)&addr, sizeof(addr)); //连接服务器
SOCKET accept( SOCKET s, struct sockaddr FAR* addr, //获取连接对方的地址信息 int FAR* addrlen //地址长度 );
五、数据收发
当用户使用Winsock编程时,都是调用函数send和recv进行数据的发送和接收。
int send(SOCKET s, const char FAR* buf, int len, int flags); int recv(SOCKET s, char FAR* buf, int len, int flags);
如果客户端使用以上函数进行数据收发,则参数s应该为客户端创建的套接字句柄。
六、关闭套接字
closesocket()关闭套接字句柄
--------------------------------------------------------------------------------------
// Socket.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" struct sockaddr_in{ short sin_family; //指定地址家族即地址格式 unsigned short sin_port; //端口号码 struct in_addr sin_addr; //IP地址 char sin_zero[8]; //留作备用,需要指定为0 }; struct in_addr { union { struct { unsigned char s_b1, s_b2, s_b3, s_b4; }S_un_b; //用4个u_char字符描述IP地址 struct { unsigned short s_w1, s_w2; //用2个u_short类型描述IP地址 }S_un_w; unsigned long S_addr; //用1个u_long类型描述IP地址 }S_un; }; int _tmain(int argc, _TCHAR* argv[]) { sockaddr_in addr; //定义套接字地址结构变量 in_addr in_add; //定义IP地址结构变量 addr.sin_family = AF_INET; //指定地址家族为TCP/IP addr.sin_port = htons(80); //指定端口号 addr.sin_addr.S_un.S_addr = INADDR_ANY;//表示服务器能接收任何计算机发过来的请求 ::bind(s, (sockaddr)&addr, sizeof(addr));//绑定套接字到指定地址结构 int listen( SOCKET s, //实现监听功能的套接字句柄 int backlog //指定监听的最大连接数量 ); int connect( SOCKET s, //套接字句柄 const struct sockaddr FAR* name, //将要连接的服务器地址信息结构指针 int namelen //地址信息结构体长度 ) sockaddr_in addr; in_addr in_add; addr.sin_family = AF_INET; addr.sin_port = htons(80); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //指定服务器地址 SOCKET s; //定义套接字句柄 s = ::socket(AF_INET, SOCK_STREAM, 0); //创建并返回套接字句柄 ::connect(s, (sockaddr)&addr, sizeof(addr)); //连接服务器 SOCKET accept( SOCKET s, struct sockaddr FAR* addr, //获取连接对方的地址信息 int FAR* addrlen //地址长度 ); int send(SOCKET s, const char FAR* buf, int len, int flags); int recv(SOCKET s, char FAR* buf, int len, int flags); return 0; } int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSADate); typedef struct WSAData { WORD wVersion; WORD wHighVersion; //库文件支持的最高版本 char szDescription[WSADESCRIPTION_LEN + 1]; //描述库文件的字符串 char szSystemStatus[WSASYS_STATUS_LEN + 1]; //系统状态字符串 unsigned short iMaxSockets; //同时支持的最大套接字字数 unsigned short iMaxUdpDg; //已废弃 char FAR * lpVendorInfo; //已废弃 }WSADATA, FAR * LPWSADATA; WSAData data; //定义WSAData变量 WORD wVersionRequested = MAKEWORD(2, 0); //定义套接字库的版本号 ::WSAStartup(wVersionRequested, &data); //初始化套接字库 SOCKET socket { int af; //指定套接字所使用的地址格式 int type; //套接字类型 int protocol; //如果参数type已经指定套接字类型为TCP或UDP,则该参数可以设置为0 }; SOCKET s; s = ::socket(AF_INET, SOCK_STREAM, 0); int bind( SOCKET s, //套接字句柄 const struct sockaddr FAR* name, //地址结构信息 int namelen //地址结构大小 );