Contents
  1. 1. 准备
  • include
    1. 1. 代码
      1. 1.1. 客户端
      2. 1.2. 服务器端
    2. 2. 代码解析
      1. 2.1. 初始化部分
      2. 2.2. 监听准备
      3. 2.3. 发送数据
      4. 2.4. 接收数据
      5. 2.5. 善后处理
  • 以控制台下实现为例子

    准备

    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
    );
    The**WSAStartup**functioninitiatesuseoftheWinsockDLLbyaprocess. **Parameters** **wVersionRequested** ThehighestversionofWindowsSocketsspecificationthatthecallercanuse.Thehigh-orderbytespecifiestheminorversionnumber;thelow-orderbytespecifiesthemajorversionnumber. **ReturnValue** Ifsuccessful,the**WSAStartup**functionreturnszero.Otherwise,itreturnsoneoftheerrorcodeslistedbelow.TheWSAStartupfunctiondirectlyreturnstheextendederrorcodeinthereturnvalueforthisfunction.Acalltothe[**WSAGetLastError**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/wsagetlasterror_2.htm)functionisnotneededandshouldnotbeused.
    **Errorcode** **Meaning**
    [**WSASYSNOTREADY**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/windows_sockets_error_codes_2.htm#winsock.wsasysnotready_2) Theunderlyingnetworksubsystemisnotreadyfornetworkcommunication.
    [**WSAVERNOTSUPPORTED**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/windows_sockets_error_codes_2.htm#winsock.wsavernotsupported_2) TheversionofWindowsSocketssupportrequestedisnotprovidedbythisparticularWindowsSocketsimplementation.
    [**WSAEINPROGRESS**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/windows_sockets_error_codes_2.htm#winsock.wsaeinprogress_2) AblockingWindowsSockets1.1operationisinprogress.
    [**WSAEPROCLIM**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/windows_sockets_error_codes_2.htm#winsock.wsaeproclim_2) AlimitonthenumberoftaskssupportedbytheWindowsSocketsimplementationhasbeenreached.
    [**WSAEFAULT**](ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/winsock/winsock/windows_sockets_error_codes_2.htm#winsock.wsaefault_2) 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
    );
    The**socket**functioncreatesasocketthatisboundtoaspecifictransportserviceprovider. 结构体**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.
    };
    The**connect**functionestablishesaconnectiontoaspecifiedsocket.
    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
        );
    The**listen**functionplacesasocketinastateinwhichitislisteningforanincomingconnection.
    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动态链接库
    Contents
    1. 1. 准备
  • include
    1. 1. 代码
      1. 1.1. 客户端
      2. 1.2. 服务器端
    2. 2. 代码解析
      1. 2.1. 初始化部分
      2. 2.2. 监听准备
      3. 2.3. 发送数据
      4. 2.4. 接收数据
      5. 2.5. 善后处理