zoukankan      html  css  js  c++  java
  • MFC 网络编程 总结 .

    基于 TCP 的 socket 编程

    /*
    服务器端程序流程:
    1.加载套接字库       WSAStartup
    2.创建套接字           socket
    3.将我们创建的套接字,绑定到本机地址的某一端口上     bind
    4.为套接字设置监听模式,准备客户请求                          listen
    5.等待客户请求到来。当请求到来,将接受连接请求,并返回一个新的对应于此次连接的套接字     accept
    6.用新返回的套接字和客户端进行通信                             send / recv
    7.在通信结束后,关闭套接字                                            closesocket


    客户端程序流程:
    1.加载套接字库                           WSAStartup
    2.创建套接字                              socket
    3.向服务器发出请求连接            connect
    4.和服务器进行通信                   send / recv
    5.在通信结束后,关闭套接字    closesocket
    */

    服务器端代码:

    1. #include <Winsock2.h>   
    2. #include <stdio.h>   
    3.   
    4. #pragma comment(lib, "Ws2_32.lib")   
    5.   
    6. void main()  
    7. {  
    8.     // 加载套接字库,并进行套接字的版本协商   
    9.     WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   
    10.     WSADATA     wsaData;            // 用于存储加载的 winsock 库版本信息   
    11.     int         result;             // 用于检测 WSAStartup 函数运行结果   
    12.   
    13.     wVersionRequested   = MAKEWORD(1, 1);   // 设定版本   
    14.   
    15.     result = WSAStartup(wVersionRequested, &wsaData);  
    16.   
    17.     // 函数 WSAStartup 调用成功返回 0   
    18.     // 出错处理   
    19.     if (result != 0)                  
    20.     {  
    21.         return;  
    22.     }  
    23.   
    24.     if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  
    25.     {  
    26.         WSACleanup();  
    27.         return;  
    28.     }  
    29.   
    30.     // 创建套接字   
    31.     SOCKET      sock    = socket(AF_INET, SOCK_STREAM, 0);  
    32.   
    33.     // 绑定套接字   
    34.     SOCKADDR_IN addrInfo;           // 存储本地主机地址信息   
    35.   
    36.     addrInfo.sin_addr.S_un.S_addr   = htonl(INADDR_ANY);    // 本地主机地址   
    37.     addrInfo.sin_port               = htons(6000);          // 端口号   
    38.     addrInfo.sin_family             = AF_INET;              // 地址族   
    39.   
    40.     bind(sock, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR));  
    41.   
    42.     // 设置套接字监听模式   
    43.     listen(sock, 5);  
    44.   
    45.     SOCKADDR_IN     addrInfoClient; // 存储客户端地址信息   
    46.     int             len = sizeof(SOCKADDR);  
    47.   
    48.     while (true)  
    49.     {  
    50.         // 等待客户请求到来,并返回用于通信的套接字   
    51.         SOCKET  sockConnect = accept(sock, (SOCKADDR *)&addrInfoClient, &len);  
    52.   
    53.         // 下面通过刚建立的套接字,来进行通信   
    54.   
    55.         // 发送数据   
    56.         char    sendBuf[100];  
    57.         sprintf(sendBuf, "这是服务器端,主机地址:%s", inet_ntoa(addrInfo.sin_addr));  
    58.         send(sockConnect, sendBuf, strlen(sendBuf), 0);  
    59.   
    60.         // 接收数据   
    61.         char    recvBuf[100];  
    62.         recv(sockConnect, recvBuf, strlen(recvBuf), 0);  
    63.   
    64.         // 打印接收的数据   
    65.         printf("%s\n", recvBuf);  
    66.   
    67.         closesocket(sockConnect);  
    68.     }  
    69.   
    70. }  


     

    客户端代码:

    1. #include <Winsock2.h>   
    2. #include <stdio.h>   
    3.   
    4. #pragma comment(lib,"Ws2_32.lib")   
    5.   
    6. void main()  
    7. {  
    8.     // 加载套接字库,并进行套接字的版本协商   
    9.     WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   
    10.     WSADATA     wsaData;            // 用于存储加载的 winsock 库版本信息   
    11.     int         result;             // 用于检测 WSAStartup 函数运行结果   
    12.   
    13.     wVersionRequested   = MAKEWORD(1, 1);   // 设定版本   
    14.   
    15.     result = WSAStartup(wVersionRequested, &wsaData);  
    16.   
    17.     // 函数 WSAStartup 调用成功返回 0   
    18.     // 出错处理   
    19.     if (result != 0)                  
    20.     {  
    21.         return;  
    22.     }  
    23.   
    24.     if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  
    25.     {  
    26.         WSACleanup();  
    27.         return;  
    28.     }  
    29.   
    30.     // 创建套接字   
    31.     SOCKET      sockConnect = socket(AF_INET, SOCK_STREAM, 0);  
    32.   
    33.     // 向服务器发出连接请求   
    34.     SOCKADDR_IN     addrInfoServer;     // 存储服务器端地址信息   
    35.     addrInfoServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  
    36.     addrInfoServer.sin_port             = htons(6000);  
    37.     addrInfoServer.sin_family           = AF_INET;  
    38.   
    39.     // 向服务器发出连接请求   
    40.     connect(sockConnect, (SOCKADDR *)&addrInfoServer, sizeof(SOCKADDR));  
    41.   
    42.     // 接收数据   
    43.     char    recvBuf[100];  
    44.     recv(sockConnect, recvBuf, sizeof(recvBuf), 0);  
    45.     printf("%s\n", recvBuf);  
    46.   
    47.     // 发送数据   
    48.     char    sendBuf[100] = "这是客户端\n";  
    49.     send(sockConnect, sendBuf, sizeof(sendBuf) + 1, 0);  
    50.   
    51.     //关闭套接字   
    52.     closesocket(sockConnect);  
    53.   
    54.     WSACleanup();  
    55.   
    56.     system("pause");  
    57.     return;  
    58. }  


     

     ================================================

     基于 UDP 无连接的 socket 编程

    /*

    服务端程序流程:
    1.加载套接字库       WSAStartup
    2.创建套接字           socket
    3.将创建的套接字绑定到一个本地地址和端口上     bind
    4.等待接收数据。后与客户端实现实时交流            recvfrom / sendto
    5.关闭套接字          closesocket

    客户端程序流程:
    1.加载套接字库     WSAStartup
    2.创建套接字         socket
    3.向服务器发送数据.后与服务端实现实时交流     recvfrom / sendto
    4.关闭套接字        closesocket

    */

    服务器端代码:

    1. #include <Winsock2.h>   
    2. #include <stdio.h>   
    3. #pragma comment(lib, "Ws2_32.lib")   
    4.   
    5. void main()  
    6. {  
    7.     // 加载套接字库,并进行套接字的版本协商   
    8.     WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   
    9.     WSADATA     wsaData;            // 用于存储加载的 wdnsock 库版本信息   
    10.     int         result;             // 用于检测 WSAStartup 函数运行结果   
    11.   
    12.     wVersionRequested = MAKEWORD(1, 1);     // 设定版本   
    13.   
    14.     result  = WSAStartup(wVersionRequested, &wsaData);  
    15.   
    16.     // 函数 WSAStartup 调用成功返回 0   
    17.     // 出错处理   
    18.     if (result != 0)  
    19.     {  
    20.         return;  
    21.     }  
    22.   
    23.     if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  
    24.     {  
    25.         WSACleanup();  
    26.         return;  
    27.     }  
    28.   
    29.     // 创建用于套接字   
    30.     SOCKET  sockConnect = socket(AF_INET, SOCK_DGRAM, 0);  
    31.   
    32.     // 绑定套接字   
    33.     SOCKADDR_IN     addrInfo;       // 存储本地主机地址信息   
    34.   
    35.     addrInfo.sin_addr.S_un.S_addr   = htonl(INADDR_ANY);    // 本地主机地址     
    36.     addrInfo.sin_port               = htons(6000);          // 端口号     
    37.     addrInfo.sin_family             = AF_INET;              // 地址族     
    38.     
    39.     bind(sockConnect, (SOCKADDR *)&addrInfo, sizeof(SOCKADDR));    
    40.   
    41.     // 等待接收数据   
    42.     char    recvBuf[100];   // 接收数据缓冲   
    43.     char    sendBuf[100];   // 发送数据缓冲   
    44.     char    tempBuf[200];     
    45.   
    46.     SOCKADDR_IN     addrInfoClient; // 存储客户端地址信息   
    47.     int             len = sizeof(SOCKADDR);  
    48.   
    49.     while (true)  
    50.     {  
    51.         recvfrom(sockConnect, recvBuf, strlen(recvBuf), 0, (SOCKADDR *)&addrInfoClient, &len);  
    52.         if ('q' == recvBuf[0])  
    53.         {  
    54.             sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR *)&addrInfoClient, len);  
    55.             printf("聊天结束");  
    56.             break;  
    57.         }  
    58.   
    59.         sprintf(tempBuf, "%s 说:%s", inet_ntoa(addrInfoClient.sin_addr), recvBuf);  
    60.         printf("%s\n", tempBuf);  
    61.   
    62.         // 发送数据   
    63.         printf("我说:");  
    64.         gets(sendBuf);  
    65.         sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR *)&addrInfoClient, len);  
    66.     }  
    67.   
    68.     // 关闭套接字   
    69.     closesocket(sockConnect);  
    70.     WSACleanup();  
    71.   
    72. }  

    客户端代码:

    1. #include <Winsock2.h>   
    2. #include <stdio.h>   
    3. #pragma comment(lib, "Ws2_32.lib")   
    4.   
    5. void main()  
    6. {  
    7.     // 加载套接字库,并进行套接字的版本协商   
    8.     WORD        wVersionRequested;  // 指定将要加载的 winsock 库版本   
    9.     WSADATA     wsaData;            // 用于存储加载的 wdnsock 库版本信息   
    10.     int         result;             // 用于检测 WSAStartup 函数运行结果   
    11.   
    12.     wVersionRequested = MAKEWORD(1, 1);     // 设定版本   
    13.   
    14.     result  = WSAStartup(wVersionRequested, &wsaData);  
    15.   
    16.     // 函数 WSAStartup 调用成功返回 0   
    17.     // 出错处理   
    18.     if (result != 0)  
    19.     {  
    20.         return;  
    21.     }  
    22.   
    23.     if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)  
    24.     {  
    25.         WSACleanup();  
    26.         return;  
    27.     }  
    28.   
    29.     // 创建套接字   
    30.     SOCKET  sockConnect = socket(AF_INET, SOCK_DGRAM, 0);  
    31.   
    32.     // 向服务器发送数据   
    33.     SOCKADDR_IN     addrInfoServer;     // 存储服务器地址信息   
    34.   
    35.     addrInfoServer.sin_addr.S_un.S_addr   = inet_addr("127.0.0.1");     // 指定服务器地址   
    36.     addrInfoServer.sin_port               = htons(6000);                // 端口号     
    37.     addrInfoServer.sin_family             = AF_INET;                    // 地址族    
    38.   
    39.     int     len = sizeof(SOCKADDR);  
    40.   
    41.     char    recvBuf[100];   // 接收数据缓冲   
    42.     char    sendBuf[100];   // 发送数据缓冲   
    43.     char    tempBuf[200];     
    44.   
    45.     while (true)  
    46.     {  
    47.         // 发送数据   
    48.         printf("我说:");  
    49.         gets(sendBuf);  
    50.         sendto(sockConnect, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&addrInfoServer, len);  
    51.   
    52.         // 等待并接收数据   
    53.         recvfrom(sockConnect,recvBuf, strlen(recvBuf), 0, (SOCKADDR*)&addrInfoServer, &len);  
    54.         if ('q' == recvBuf[0])  
    55.         {  
    56.             sendto(sockConnect, "q", strlen("q") + 1, 0, (SOCKADDR*)&addrInfoServer, len);  
    57.             printf("聊天结束");  
    58.             break;  
    59.         }  
    60.   
    61.         sprintf(tempBuf, "%s 说:%s", inet_ntoa(addrInfoServer.sin_addr), recvBuf);  
    62.         printf("%s\n", tempBuf);  
    63.     }  
    64.   
    65.     // 关闭套接字   
    66.     closesocket(sockConnect);  
    67.     WSACleanup();  
    68.   
    69. }  


     


    1. vc网络编程常用类型解析:  
    2.   
    3. 1. SOCKET 类型  
    4. SOCKET 是 socket 套接字类型,在 WINSOCK2.H 中有如下定义:  
    5. typedef unsigned u_int;  
    6. typedef u_int    SOCKET;  
    7. 可知套接字实际上就是一个无符号整形,它将被 Socket 环境管理和使用。  
    8. 套接字将被创建、设置、用来发送和接收数据,最后会被关闭。  
    9.   
    10. 2.WORD 类型、MAKEWORD、LOBYTE、HIBYTE 宏  
    11. WORD 类型是一个 16 位的无符号整型, 在 WTYPES.H 中被定义为:  
    12. typedef unsigned short  WORD;  
    13. 其目的是提供两个字节的存储, 在 Socket 中这两个字节可以表示主版本号和副版本号。  
    14. 使用 MAKEWORD 宏可以给一个 WORD 类型赋值。例如要表示主版本号 2, 副版本号 0,可以使用如下代码:  
    15. WORD wVersionRequested;  
    16. wVersionRequested   = MAKEWORD(2, 0);  
    17. 注意低位内存存储主版本号 2, 高位内存存储副版本号 0,其值为 0x0002。  
    18. 使用宏 LOBYTE 可以读取 WORD 的低位字节, HIBYTE 可以读取高位字节。  
    19.   
    20. 3.WSADATA 类型和 LPWSADATA 类型  
    21. WSADATA 类型是一个结构,描述了 Socket 库的一些相关信息,其结构定义如下:  
    22.   
    23. typedef struct WSAData  
    24. {  
    25.     WORD        wVersion;                                 
    26.     WORD        wHighVersion;                             
    27.     char        szDescription[WSADESCRIPTION_LEN + 1];    
    28.     char        szSystemStatus[WSASYS_STATUS_LEN + 1];  
    29.     unsigned short  iMaxSockets;  
    30.     unsigned short  iMaxUdpDg;  
    31.     char    FAR*    lpVendorInfo;  
    32. }WSADATA;  
    33. typedef WSADATA FAR*    LPWSADATA;  
    34.   
    35. 值得注意的是 wVersion 字段,存储了 Socket 的版本类型。LPWSADATA 是 WSADATA 的指针类型。  
    36. 他们通过 Socket 的初始化函数 WSAStartup 读取出来。  
    37.   
    38. vc网络编程常用函数解析:  
    39.   
    40. 1. WSAStartup 函数  
    41. 用于初始化 Socket 环境,函数原型:  
    42. int WSAStartup(WORD wVersionRequested,  LPWSADATA lpWSAData);  
    43. 其返回值为整型,调用方式为 PASCAL (即标准类型,PASCAL 等于__stdcall),参数有两个,  
    44. 第一个参数为 WORD 类型,指明了 Socket 的版本号,第二个参数为 LPWSADATA,指向一个用于存储 Socket 库信息的WSAStartup结构。  
    45. 返回值:  
    46. 返回值为0,则初始化成功,若不为0则为失败。  
    47.   
    48. 2.WSACleanup 函数  
    49. 这是 Socket 环境的退出函数,函数原型:  
    50. int  WSACleanup (void);  
    51. 返回值:  
    52. 返回值为0表示成功,SOCKET_ERROR 表示失败。  
    53.   
    54. 3.socket 函数  
    55. socket 套接字的创建函数,函数原型:  
    56. SOCKET socket(int af, int type, int protocol  );  
    57. 第一个参数为:int af,      代表网络地址族,目前只有一种取值有效,即 AF_INET, 代表 internet 地址族;  
    58. 第二个参数为:int type,    代表网络协议类型, SOCK_DGRAM 代表 UDP 协议, SOCK_STREAM 代表 TCP 协议。  
    59. 第三个参数为:int protocol,指定网络地址族特殊协议,目前无用,赋值0即可。  
    60. 返回值:  
    61. 返回值为 SOCKET, 若返回INVALID_SOCKET 则失败。  
    62.   
    63. 4.bind 函数  
    64. 用于将套接字绑定到一个已知地址上,函数原型:  
    65. int bind(SOCKET s, const struct sockaddr FAR *name, int namelen);  
    66. 第一个参数为:SOCKET s,            指定将被绑定的套接字。  
    67. 第二个参数为:SOCKADDR_IN *name,   是一个sockaddr结构指针,该结构中包含了要绑定的地址和端口。  
    68. 第三个参数为:int  namelen,         确定第二个参数的结构长度。  
    69.   
    70. 返回值:   成功返回0,失败返回SOCKET_ERROR。  
    71.   
    72. 下面对其涉及的类型作一番解析:  
    73. sockaddr 类型:  
    74. sockaddr 类型是用来表示 Socket 地址的类型,同上面的 socketaddr_in 类型相比,sockaddr 的适用范围更广,  
    75. 因为sockeaddr_in只适用于 TCP/IP 地址。sockaddr 的定义如下:  
    76. struct sockaddr  
    77. {  
    78.     ushort  sa_family;  
    79.     char    sa_data[14];  
    80. };  
    81. 可知sockaddr 的16个字节,而sockaddr_in也有16个字节,所以sockaddr_in是可以强制类型转换为sockadddr的。  
    82. 事实上也往往使用这种方法。  
    83.   
    84. sockaddr_in 定义了socket发送和接收数据包的地址,其定义如下:  
    85. strucr  sockaddr_in  
    86. {  
    87.     short       sin_family;  
    88.     u_short      sin_port;  
    89.     struct in_addr  sin_addr;  
    90.     char        sin_zero[8];  
    91. };  
    92.   
    93. 其中 in_addr 定义如下:  
    94. struct in_addr  
    95. {  
    96.     union  
    97.     {  
    98.         struct {u_char   s_b1, s_b2, s_b3, s_b4} S_un_b;  
    99.         struct {u_short  s_w1, s_w2} S_un_w;  
    100.         u_long S_addr;  
    101.     }S_un;  
    102. };  
    103. 首先阐述 in_addr 的信义。  
    104. 很显然它是一个存储 ip 地址的联合体,有三种表达方式:  
    105. 第一种用四个字节来表示IP地址的四个数字;  
    106. 第二种用两个双字节来表示IP地址;  
    107. 第三种用一个长整型来表示IP地址;  
    108. 给 in_addr 赋值的一种最简单方法是使用 inet_addr 函数, 它可以把一个代表IP地址的字符串赋值  
    109. 转换为in_addr类型。如:  
    110. addrServer.sin_addr = inet_addr("192.168.0.2");  
    111. 其反函数是 inet_ntoa,可以把一个 in_addr 类型转换为一个字符串。  
    112. sockaddr_in的含义比in_addr的含义要广泛,其各个字段的含义和取值如下:  
    113. 第一字段 short           sin_family,代表网络地址族,如前所述,只能取值AF_INET;  
    114. 第二字段 u_short         sin_port,  代表IP地址端口,由程序员指定;  
    115. 第三字段 struct in_addr  sin_addr,  代表IP地址;  
    116. 第四个字段char sin_zero[8],是为了保证sockaddr_in与SOCKADDR类型的长度相等而填充进来的字段。  
    117.   
    118. 5.listen 函数  
    119. 该函数让一个套接字在指定IP地址的指定端口处监听连接请求的到来,函数原型:  
    120. int listen(  SOCKET s,      int backlog  );  
    121. 该函数使得一个进程可以接受其他进程的请求,从而成为一个服务器进程。  
    122. 在TCP服务器编程中listen函数把进程变为一个服务器,并指定相应的套接字变为被动连接。  
    123. listen 函数一般在调用bind之后、调用accept之前调用。  
    124. 返回值:  成功则返回0,失败返回SOCKET_ERROR,可以调用函数WSAGetLastError来取得错误代码。  
    125.   
    126.   
    127. 6.accept函数  
    128. 该函数从连接请求队列中获得连接信息,并创建新的套接字用于收发数据,实现服务器与客户端的通信。函数原型:  
    129. SOCKET accept(SOCKET s,  struct sockaddr FAR *addr,  int FAR *addrlen);  
    130. 第一个参数:SOCKET          s,      监听套接字  
    131. 第二个参数:struct sockaddr addr,   存储请求连接的客户端IP地址、端口信息  
    132. 第三个参数:int             addrlen,第二个参数所占空间大小  
    133. 返回值:  
    134. 成功返回新套接字,失败返回错误信息  
    135.   
    136.   
    137. 7.connect 函数  
    138. 向指定的网络主机请求连接,函数原型:  
    139. int connect(SOCKET s, const struct sockaddr FAR *name, int namelen);  
    140. 第一个参数:SOCKET           s,       客户端用于收发数据的套接字。  
    141. 第二个参数:struct sockaddr  *name,   指定网络主机IP地址和端口号。  
    142. 第三个参数:int              namelen, 第二参数长度  
    143. 返回值:  
    144. 成功返回0,失败返回-1。  
    145.   
    146. 8.sendto、recvfrom、send、recv函数  
    147. 在 Socket 中有两套发送和接收函数。一是sendto 和recvfrom; 二是send 和 recv。  
    148. 前一套在函数参数中要指明地址(UDP协议),  
    149. 而后一套需要先将套接字和一个地址绑定,然后直接发送和接收,不需绑定地址。  
    150. 函数原型:  
    151. int sendto(  SOCKET s, const char FAR *buf, int len, int flags, const struct sockaddr FAR *to,   int      tolen);  
    152. int recvfrom(SOCKET s,       char FAR* buf, int len, int flags, struct sockaddr FAR       *from, int FAR *fromlen);  
    153.   
    154. int send(SOCKET s,const char FAR *buf,  int len, int flags);  
    155. int recv(SOCKET s,      char FAR *buf,  int len, int flags);  
    156.   
    157. 第一个参数: 套接字  
    158. 第二个参数: 数据指针  
    159. 第三个参数: 数据长度  
    160. 第四个参数: 收发数据方式的标识,如果不需要特殊要求可以设置为0,其他值可参考MSDN;  
    161. 第五个参数: 目标主机地址  
    162. 第六个参数: 地址的长度  
    163.   
    164. 返回值:   运行成功则返回收发数据的字节数,失败返回SOCKET_ERROR  
    165.   
    166. 9.closesocket 函数  
    167. 关闭套接字,函数原型:  
    168. int closesocket(  SOCKET s  );  
    169. 返回值:  成功返回0,失败返回SOCKET_ERROR。  

    from:http://blog.csdn.net/ltag0110rtag/article/details/7390304

  • 相关阅读:
    LeetCode120 Triangle
    LeetCode119 Pascal's Triangle II
    LeetCode118 Pascal's Triangle
    LeetCode115 Distinct Subsequences
    LeetCode114 Flatten Binary Tree to Linked List
    LeetCode113 Path Sum II
    LeetCode112 Path Sum
    LeetCode111 Minimum Depth of Binary Tree
    Windows下搭建PHP开发环境-WEB服务器
    如何发布可用于azure的镜像文件
  • 原文地址:https://www.cnblogs.com/lidabo/p/2598734.html
Copyright © 2011-2022 走看看