最近网络实验课做了好几个实验,我来慢慢分享给大家,首先是做一个socket套接字编程,实现一个C/S模型的简单通信程序。其实是两个程序,一个client端,一个server端。需要从客户端发送字符,然后显示在服务端。这个还是比较简单的。

sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);基于TCP的socket编程是采用的流式套接字。

我这次创建的是TCP的socket。TCP和UDP当然是有区别的,协议方面的事自己去google吧。我就说说在这两种方式下socket编程有哪些区别吧:

  • 基于TCP的socket编程

服务器端程序设计步骤:

1. 加载套接字库(WSAStartup),创建套接字(socket)。

2. 将套接字绑定IP地址和一个端口(bind)。

3. 将套接字设为监听模式,准备接收客户请求(listen)。

4. 等待客户请求到来。当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。

5. 用返回的套接字和客户端进行通信(send/recv)。

6. 返回,等待另一个客户请求。

7. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。

客户端程序设计步骤:

1. 加载套接字库(WSAStartup),创建套接字(socket)。

2. 向服务器发出连接请求(connect)。

3. 和服务器端进行通信(send/recv)。

4. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。

  • 基于UDP的socket编程

服务器端程序设计步骤:

1. 加载套接字库(WSAStartup),创建套接字(socket)。

2. 将套接字绑定IP地址和一个端口(bind)。

3. 等待接收数据(recvfrom)。

4. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。

客户端程序设计步骤:

1. 加载套接字库(WSAStartup),创建套接字(socket)。

2. 向服务器发送数据(sendto)。

3. 关闭套接字(closesocket),关闭加载的套接字库(WSACleanup)。

  • 效果图:

p_w_picpath

附上代码:

 
  
  1. Server.cpp  
  2. #pragma comment (lib, "ws2_32.lib")  
  3. #include <winsock2.h>  
  4. #include <iostream.h>  
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7.  
  8. #define VERSION_LOW   2  
  9. #define VERSION_HIGH  0  
  10. #define PORT          7777  
  11. #define TEXT_LENGTH   1024  
  12. #define REQUEST_LINE  4  
  13.  
  14. void main(void)  
  15. {     
  16.     //1、加载socket库,版本为2.0  
  17.     WORD wVersionRequested; //版本  
  18.     WSADATA wsaData;  
  19.     int err;  
  20.       
  21.     wVersionRequested = MAKEWORD(VERSION_LOW, VERSION_HIGH);  
  22.  
  23.     err = WSAStartup(wVersionRequested, &wsaData);  
  24.     if (err != 0)   
  25.     {  
  26.         cout << "Socket2.0 Loading Error, Exit!" << endl;  
  27.         return;  
  28.     }  
  29.  
  30.     //验证版本是否相符  
  31.     if (LOBYTE(wsaData.wVersion) != VERSION_LOW || HIBYTE(wsaData.wVersion) != VERSION_HIGH)  
  32.     {  
  33.         WSACleanup();  
  34.         return;   
  35.     }  
  36.  
  37.     //2、创建套接字  
  38.     SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM使用的是TCP协议  
  39.     if (sockSrv == INVALID_SOCKET)   
  40.     {  
  41.         cout << "Socket Creating Error, Exit!" << endl;  
  42.         WSACleanup();  
  43.         return;  
  44.     }  
  45.  
  46.     //3、绑定IP地址和端口  
  47.     SOCKADDR_IN addrSrv;   
  48.     memset(&addrSrv, 0, sizeof(addrSrv));  
  49.  
  50.     addrSrv.sin_family = AF_INET;  
  51.     //绑定本地,inet_addr函数把IP转成in_addr结构  
  52.     addrSrv.sin_addr.s_addr = INADDR_ANY;   
  53.     //端口号必须和客户发往的端口号一致  
  54.     addrSrv.sin_port = htons(PORT); //htons函数把×××数转成网络字节序,大端数  
  55.  
  56.     bind(sockSrv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));  
  57.  
  58.     //4、监听端口,连接请求队列为REQUEST_LINE  
  59.     if (listen(sockSrv, REQUEST_LINE) == SOCKET_ERROR)  
  60.     {  
  61.         closesocket(sockSrv);  
  62.         WSACleanup();  
  63.         return;  
  64.     }  
  65.     else 
  66.     {  
  67.         cout << "listening port succeed!" << endl;  
  68.     }  
  69.  
  70.     //5、循环accept客户端来的信息  
  71.     SOCKADDR_IN addrCli;  
  72.     int len = sizeof(addrCli);  
  73.       
  74.     char sendBuf[TEXT_LENGTH];  
  75.     char recvBuf[TEXT_LENGTH];  
  76.       
  77.     SOCKET sockCom = accept(sockSrv, (SOCKADDR *)&addrCli, &len);  
  78.     if (sockCom < 0)  
  79.     {  
  80.         cout << "Communication socket error, exit!" << endl;  
  81.         WSACleanup();  
  82.         return;  
  83.     }  
  84.     else 
  85.     {  
  86.         cout << "Accepted client socket successd!" << endl;  
  87.         cout << "The current connect user is from "   
  88.              << inet_ntoa(addrCli.sin_addr) << " " 
  89.              << htons(addrCli.sin_port) << endl;  
  90.         sprintf(sendBuf, "Welcome %s to here!\nYou can type words to me now!\n",   
  91.                 inet_ntoa(addrCli.sin_addr));  
  92.         send(sockCom, sendBuf, TEXT_LENGTH, 0);  
  93.     }  
  94.     while (1)  
  95.     {  
  96.         recv(sockCom, recvBuf, TEXT_LENGTH, 0);  
  97.         printf("%s\n", recvBuf);  
  98.     }  
  99.  
  100.     if (!closesocket(sockCom))  
  101.     {  
  102.         WSAGetLastError();  
  103.         return;  
  104.     }  
  105.     if (!closesocket(sockSrv))   
  106.     {  
  107.         WSAGetLastError();  
  108.         return;  
  109.     }  
  110.     if (!WSACleanup())  
  111.     {  
  112.         WSAGetLastError();  
  113.         return;  
  114.     }  
 
  
  1. Client.cpp  
  2. #include <stdlib.h>  
  3. #include <winsock2.h>  
  4. #include <iostream.h>  
  5. #include <stdio.h>  
  6.  
  7. #define VERSION_LOW   2  
  8. #define VERSION_HIGH  0  
  9. #define SRV_IP_ADDR   "127.0.0.1"  
  10. #define PORT          7777  
  11. #define TEXT_LENGTH   1024  
  12.  
  13. #pragma comment (lib, "ws2_32.lib")  
  14.  
  15. //void main(int argc, char **argv)  
  16. void main(void)  
  17. {     
  18.     //1、加载socket库,版本为2.0  
  19.     WORD wVersionRequested; //版本  
  20.     WSADATA wsaData;  
  21.     int err;  
  22.  
  23.     wVersionRequested = MAKEWORD(VERSION_LOW, VERSION_HIGH);  
  24.       
  25.     err = WSAStartup(wVersionRequested, &wsaData);  
  26.     if (err != 0)   
  27.     {  
  28.         cout << "Socket2.0 Loading Error, Exit!" << endl;  
  29.         return;  
  30.     }  
  31.  
  32.     //验证版本是否相符  
  33.     if (LOBYTE(wsaData.wVersion) != VERSION_LOW || HIBYTE(wsaData.wVersion) != VERSION_HIGH)  
  34.     {  
  35.         WSACleanup();  
  36.         return;   
  37.     }  
  38.       
  39.     //2、创建套接字  
  40.     SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0); //SOCK_STREAM使用的是TCP协议  
  41.     if (sockCli == INVALID_SOCKET)   
  42.     {  
  43.         cout << "Socket Creating Error, Exit!" << endl;  
  44.         WSACleanup();  
  45.         return;  
  46.     }  
  47.  
  48.  
  49. //  char server_IP[TEXT_LENGTH];  
  50. /*  
  51.     if (argc < 2)  
  52.     {  
  53.         printf("Please enter the server's IP!\n");  
  54.         return;  
  55.     }  
  56.     strncpy(server_IP, argv[1], 16);  
  57.  
  58. */ 
  59. //  strcpy(server_IP, "192.168.1.100");  
  60.  
  61.     //3、设置socket的IP地址和端口  
  62.     SOCKADDR_IN addrSrv;  
  63.     memset(&addrSrv, 0, sizeof(addrSrv));  
  64.  
  65.     addrSrv.sin_family = AF_INET;  
  66.     //绑定本地,inet_addr函数把IP转成in_addr结构  
  67.     addrSrv.sin_addr.s_addr = inet_addr(SRV_IP_ADDR);  
  68.     addrSrv.sin_port = htons(PORT); //htons函数把×××数转成网络字节序,大端数  
  69.  
  70.     char sendBuf[TEXT_LENGTH];  
  71.     char recvBuf[TEXT_LENGTH];  
  72.  
  73.     if (connect(sockCli, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR)) != 0)  
  74.     {  
  75.         closesocket(sockCli);  
  76.         WSACleanup();  
  77.         return;  
  78.     }  
  79.     else 
  80.     {  
  81.         cout << "Connecting server succeed!" << endl;  
  82.         recv(sockCli, recvBuf, TEXT_LENGTH, 0);  
  83.         printf("%s\n", recvBuf);  
  84.     }  
  85.  
  86.     printf("Please input the message you want send to server:\n");  
  87.     while (1)  
  88.     {  
  89.         //scanf("%s", sendBuf);  
  90.         gets(sendBuf);  
  91.         send(sockCli, sendBuf, TEXT_LENGTH, 0);  
  92.     }  
  93.  
  94.     if (!closesocket(sockCli))   
  95.     {  
  96.         WSAGetLastError();  
  97.         return;  
  98.     }  
  99.     if (!WSACleanup())   
  100.     {  
  101.         WSAGetLastError();  
  102.         return;  
  103.     }