VS Socket编程
以控制台下实现为例子
准备
#include<Winsock2.h>
需要在项目中添加依赖项:Ws2_32.lib
代码
此代码实现的功能是服务器端发送数据,客户端连接上服务器端并监听服务器端发送来的数据。
客户端
#include "stdafx.h" #include<Winsock2.h> void _tmain(int argc, _TCHAR* argv[]) { //加载socket动态链接库 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } //创建客户端套接字 SOCKET client=socket(AF_INET,SOCK_STREAM,0);//流式套接字。(数据报套接字,原套接字) SOCKADDR_IN svr_addr_in;//保存服务器端的地址信息 svr_addr_in.sin_family=AF_INET;//代表TCP/IP协议族 //inet_addr()把字符串变成无符号的长整型。获取服务器地址.0.0.1:本机做服务器,127.0.0.1是服务器的ip地址 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //htons本函数将一个位数从主机字节顺序转换成网络字节顺序,该端口号要与服务器的端口号相同 svr_addr_in.sin_port=htons(6000); while(connect(client,(sockaddr*)&svr_addr_in,sizeof(svr_addr_in))!=0);//链接服务器,等于表示连上服务器 char b[1024]; for(int i=0;;i++) { recv(client,b,sizeof(b),0);//客户端接受文件 printf("%s",b); } closesocket(client);//关闭客户端套接字 WSACleanup();//卸载winsock动态链接库 }
服务器端
#include "stdafx.h" #include<Winsock2.h> void _tmain(int argc, _TCHAR* argv[]) { //加载socket动态链接库 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } SOCKET svr=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN svr_addr_in;//创建一个服务器地址结构体,用于保存服务器的信息 svr_addr_in.sin_family=AF_INET;//协议家族 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//htonl(INADDR_ANY);//获取当前机子网卡ip地址 svr_addr_in.sin_port=htons(6000);//设置端口地址 bind(svr,(sockaddr*)&svr_addr_in,sizeof(SOCKADDR_IN));//将socket绑定到本地机地址上面 //把服务器socket设置为监听socket,同时能监听个client客服 listen(svr,5); SOCKADDR_IN client_addr_in;//用于保存客户端的信息 int len=sizeof(SOCKADDR_IN); SOCKET client=accept(svr,(sockaddr*)&client_addr_in,&len);//等待(接受)客户端请求到来 char b[1024]="ss"; for(int i=0;;i++) { send(client,b,sizeof(b),0);//向服务器发送数据 //system("pause"): } closesocket(client);//关闭客户端套接字 closesocket(svr);//关闭服务器套接字 WSACleanup();//卸载socket链接库 return ; }
代码解析
初始化部分
WORD wVersionRequested MAKEWORD( 1, 1 ); WSADATA wsaData; int err= WSAStartup( wVersionRequested, &wsaData );
MAKEWORD(a,b)是一个宏,定义如下:
#defineMAKEWORD(a,b)((WORD)(((BYTE)(((DWORD_PTR)(a))&0xff))|((WORD)((BYTE)(((DWORD_PTR)(b))&0xff)))<<8))
目的是将两个单字节拼成一个双字节,比如(1,1)会被拼成0x0101.
WSADATA为结构体,用于存储socket的内容,定义如下:
typedef struct WSAData { WORD wVersion; WORD wHighVersion; #ifdef _WIN64 unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; #else char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYS_STATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; #endif } WSADATA
函数
int WSAStartup( __in WORD wVersionRequested, __out LPWSADATA lpWSAData );
TheWSAStartupfunctioninitiatesuseoftheWinsockDLLbyaprocess.
Parameters
wVersionRequested
ThehighestversionofWindowsSocketsspecificationthatthecallercanuse.Thehigh-orderbytespecifiestheminorversionnumber;thelow-orderbytespecifiesthemajorversionnumber.
ReturnValue
Ifsuccessful,theWSAStartupfunctionreturnszero.Otherwise,itreturnsoneoftheerrorcodeslistedbelow.TheWSAStartupfunctiondirectlyreturnstheextendederrorcodeinthereturnvalueforthisfunction.AcalltotheWSAGetLastErrorfunctionisnotneededandshouldnotbeused.
Errorcode |
Meaning |
WSASYSNOTREADY | Theunderlyingnetworksubsystemisnotreadyfornetworkcommunication. |
WSAVERNOTSUPPORTED | TheversionofWindowsSocketssupportrequestedisnotprovidedbythisparticularWindowsSocketsimplementation. |
WSAEINPROGRESS | AblockingWindowsSockets1.1operationisinprogress. |
WSAEPROCLIM | AlimitonthenumberoftaskssupportedbytheWindowsSocketsimplementationhasbeenreached. |
WSAEFAULT | ThelpWSADataparameterisnotavalidpointer. |
Requirements
Client | RequiresWindowsVista,WindowsXP,Windows2000Professional,WindowsNTWorkstation,WindowsMe,Windows98,orWindows95. |
Server | RequiresWindowsServer2008,WindowsServer2003,Windows2000Server,orWindowsNTServer. |
Header | DeclaredinWinsock2.h. |
Library | UseWs2_32.lib. |
DLL | RequiresWs2_32.dll. |
连接准备
//创建客户端套接字 SOCKET client=socket(AF_INET,SOCK_STREAM,0);//流式套接字。(数据报套接字,原套接字) SOCKADDR_IN svr_addr_in;//保存服务器端的地址信息 svr_addr_in.sin_family=AF_INET;//代表TCP/IP协议族 //inet_addr()把字符串变成无符号的长整型。获取服务器地址.0.0.1:本机做服务器,127.0.0.1是服务器的ip地址 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); //htons本函数将一个位数从主机字节顺序转换成网络字节顺序,该端口号要与服务器的端口号相同 svr_addr_in.sin_port=htons(6000); while(connect(client,(sockaddr*)&svr_addr_in,sizeof(svr_addr_in))!=0);//链接服务器,等于表示连上服务器
SOCKET为重定义变量,原始变量类型为_W64unsignedint.
函数
SOCKET WSAAPI socket( __in int af, __in int type, __in int protocol );
Thesocketfunctioncreatesasocketthatisboundtoaspecifictransportserviceprovider.
结构体SOCKADDR_IN
struct sockaddr_in{ short sin_family; //Address family (must be AF_INET). unsigned short sin_port; //IP port. struct in_addr sin_addr; //IP address. char sin_zero[8]; //Padding to make structure the same size as SOCKADDR. };
Theconnectfunctionestablishesaconnectiontoaspecifiedsocket.
int connect( __in SOCKET s, //Descriptor identifying an unconnected socket. __in const struct sockaddr* name,//Name of the socket in the sockaddr structure to which the connection should be established. __in int namelen //Length of name, in bytes. );
监听准备
SOCKET svr=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN svr_addr_in;//创建一个服务器地址结构体,用于保存服务器的信息 svr_addr_in.sin_family=AF_INET;//协议家族 svr_addr_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//htonl(INADDR_ANY);//获取当前机子网卡ip地址 svr_addr_in.sin_port=htons(6000);//设置端口地址 bind(svr,(sockaddr*)&svr_addr_in,sizeof(SOCKADDR_IN));//将socket绑定到本地机地址上面 //把服务器socket设置为监听socket,同时能监听个client客服 listen(svr,5);
bind函数
bind( IN SOCKET s, __in_bcount(namelen) const struct sockaddr FAR * name, IN int namelen );
Thelistenfunctionplacesasocketinastateinwhichitislisteningforanincomingconnection.
int listen( __in SOCKET s, //Descriptor identifying a bound, unconnected socket. __in int backlog //允许的最多的连接队列 );
发送数据
SOCKADDR_IN client_addr_in;//用于保存客户端的信息 int len=sizeof(SOCKADDR_IN); SOCKET client=accept(svr,(sockaddr*)&client_addr_in,&len);//等待(接受)客户端请求到来 char b[1024]="ss"; for(int i=0;;i++) { send(client,b,sizeof(b),0);//向服务器发送数据 //system("pause"): }
接收数据
char b[1024]; for(int i=0;;i++) { recv(client,b,sizeof(b),0);//客户端接受文件 printf("%s",b); }
send与recv函数的参数表都是
IN SOCKET s, // The descriptor that identifies a connected socket. __out_bcount_part(len, return) __out_data_source(NETWORK) char FAR * buf, // The buffer for incoming data. IN int len,// The length, in bytes, of the buf parameter. IN int flags //A pointer to flags that influences the behavior of this function. See remarks below.
善后处理
closesocket(client);//关闭客户端套接字 closesocket(svr);//关闭服务器套接字 WSACleanup();//卸载winsock动态链接库
发表评论