• c++下基于windows socket的单线程服务器客户端程序(基于TCP协议)


    今天自己编写了一个简单的c++服务器客户端程序,注释较详细,在此做个笔记。

    windows下socket编程的主要流程可概括如下:初始化ws2_32.dll动态库-->创建套接字-->绑定地址信息-->服务器进行监听/客户端连接服务器-->数据交换-->关闭套接字对象。

    服务器端:

      1 #include <Winsock2.h>
      2 #include <Ws2tcpip.h>
      3 #include <iostream>
      4 
      5 #pragma comment(lib, "ws2_32.lib") //socket编程需要引用该库
      6 
      7 using std::cerr;
      8 using std::cout;
      9 using std::endl;
     10 
     11 const char DEFAULT_PORT[] = "4000";
     12 const int RECV_BUF_SIZE = 256;
     13 const size_t IP_BUF_SIZE = 65;
     14 
     15 //服务器
     16 int main() {
     17     WSADATA wsa_data; //WSADATA变量,包含windows socket执行的信息
     18     int i_result = 0; //接收返回值
     19     SOCKET sock_server = INVALID_SOCKET; //创建服务器套接字
     20     SOCKET sock_client = INVALID_SOCKET; //创建客户端套接字
     21     //addrinfo是getaddrinfo()函数用来保存主机地址信息的结构体
     22     addrinfo *result = nullptr; //result是存储地址信息的链表
     23     addrinfo hints;
     24     //初始化winsock动态库(ws2_32.dll),MAKEWORD(2, 2)用于请求使用winsock2.2版本
     25     i_result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
     26     if (i_result != 0) {
     27         cerr << "WSAStartup() function failed: " << i_result << "
    ";
     28         system("pause");
     29         return 1;
     30     }
     31     //用0填充内存区域,是ZeroMemory的更安全版本
     32     SecureZeroMemory(&hints, sizeof(addrinfo));
     33     hints.ai_family = AF_INET;
     34     hints.ai_socktype = SOCK_STREAM; //流式套接字用于TCP协议
     35     hints.ai_protocol = IPPROTO_TCP;
     36     hints.ai_flags = AI_PASSIVE; //socket的地址会被用于bind()函数的调用
     37     //确定服务器的地址与端口,将相关信息写入result中
     38     i_result = getaddrinfo(nullptr, DEFAULT_PORT, &hints, &result);
     39     if (i_result != 0) {
     40         cerr << "getaddrinfo() function failed with error: " << WSAGetLastError() << "
    ";
     41         WSACleanup();
     42         system("pause");
     43         return 1;
     44     }
     45     //创建服务器套接字
     46     sock_server = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
     47     //套接字创建失败
     48     if (sock_server == INVALID_SOCKET) {
     49         cerr << "socket() function failed with error: " << WSAGetLastError() << "
    ";
     50         //将getaddrinfo()函数动态分配的addrinfo中的地址信息释放掉
     51         freeaddrinfo(result);
     52         //释放套接字资源
     53         WSACleanup();
     54         system("pause");
     55         return 1;
     56     }
     57     //将服务器套接字与地址对象绑定,result->ai_addr是结构体的指针
     58     i_result = bind(sock_server, result->ai_addr, static_cast<int>(result->ai_addrlen));
     59     //绑定失败
     60     if (i_result == SOCKET_ERROR) {
     61         cerr << "bind() function failed with error: " << WSAGetLastError() << "
    ";
     62         freeaddrinfo(result);
     63         closesocket(sock_server);
     64         WSACleanup();
     65         system("pause");
     66         return 1;
     67     }
     68     freeaddrinfo(result);
     69     cout << "server started successfully..." << endl;
     70     //开始监听
     71     cout << "start listening..." << endl;
     72     i_result = listen(sock_server, SOMAXCONN);
     73     if (i_result == SOCKET_ERROR) {
     74         cerr << "listen() function failed with error: " << WSAGetLastError() << "
    ";
     75         closesocket(sock_server);
     76         system("pause");
     77         return 1;
     78     }
     79     //接收客户端请求,获取客户端ip地址
     80     SOCKADDR_IN addr_client;
     81     int len_addr = sizeof(SOCKADDR_IN);
     82     char ip_buf[IP_BUF_SIZE];
     83     SecureZeroMemory(ip_buf, IP_BUF_SIZE);
     84     sock_client = accept(sock_server, (SOCKADDR*)&addr_client, &len_addr);
     85     if (sock_client == INVALID_SOCKET) {
     86         cerr << "accept() function failed with error: " << WSAGetLastError() << "
    ";
     87         closesocket(sock_server);
     88         WSACleanup();
     89         system("pause");
     90         return 1;
     91     }
     92     cout << "client connected..." << endl;
     93     //ip地址转换
     94     inet_ntop(AF_INET, &addr_client, ip_buf, IP_BUF_SIZE);
     95     cout << "client ip address: " << ip_buf << endl;
     96     //接收和发送数据
     97     char recv_buf[RECV_BUF_SIZE];
     98     int send_result = 0;
     99     do {
    100         //不可缺少,若不将内存空间清零会输出乱码,这是因为输送过来的信息未必有256个字节
    101         SecureZeroMemory(recv_buf, RECV_BUF_SIZE);
    102         //标志位一般设置为0
    103         i_result = recv(sock_client, recv_buf, RECV_BUF_SIZE, 0);
    104         if (i_result > 0) {
    105             //exit表示客户端请求断开连接
    106             if (strcmp(recv_buf, "exit") == 0) {
    107                 cout << "client requests to close the connection..." << endl;
    108                 break;
    109             }
    110             //输出接收的字节数
    111             cout << "Bytes received: " << i_result << endl;
    112             cout << "message received: " << recv_buf << endl;
    113             //向客户端发送接收到的数据
    114             send_result = send(sock_client, recv_buf, i_result, 0);
    115             if (send_result == SOCKET_ERROR) {
    116                 cerr << "send() function failed with error: " << WSAGetLastError() << "
    ";
    117                 closesocket(sock_client);
    118                 WSACleanup();
    119                 system("pause");
    120                 return 1;
    121             }
    122         }
    123         //i_result的值为0表示连接已经关闭
    124         else if (i_result == 0) {
    125             cout << "connection closed..." << endl;
    126         }
    127         else {
    128             cerr << "recv() function failed with error: " << WSAGetLastError() << "
    ";
    129             closesocket(sock_client);
    130             WSACleanup();
    131             system("pause");
    132             return 1;
    133         }
    134     } while (i_result > 0); //do...while语句后注意要有分号
    135     //shutdown()禁用套接字的接收或发送功能
    136     i_result = shutdown(sock_client, SD_SEND);
    137     if (i_result == SOCKET_ERROR) {
    138         cerr << "shutdown() function failed with error: " << WSAGetLastError() << "
    ";
    139         closesocket(sock_client);
    140         WSACleanup();
    141         system("pause");
    142         return 1;
    143     }
    144     //关闭套接字
    145     i_result = closesocket(sock_server);
    146     WSACleanup();
    147     cout << "socket closed..." << endl;
    148     system("pause");
    149     return 0;
    150 }

    客户端:

      1 #include <iostream>
      2 #include <WinSock2.h>
      3 #include <Ws2tcpip.h>
      4 
      5 #pragma comment(lib, "ws2_32.lib")
      6 
      7 using std::cin;
      8 using std::cerr;
      9 using std::cout;
     10 using std::endl;
     11 using std::flush;
     12 
     13 const char DEFAULT_PORT[] = "4000";
     14 const int SEND_BUF_SIZE = 256;
     15 
     16 //客户端
     17 int main() {
     18     WSADATA wsa_data; //WSADATA变量,包含windows socket执行的信息
     19     int i_result = 0; //接收返回值
     20     SOCKET sock_client = INVALID_SOCKET;
     21     addrinfo *result = nullptr, hints;
     22     //初始化winsock动态库(ws2_32.dll),MAKEWORD(2, 2)用于请求使用winsock2.2版本
     23     i_result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
     24     if (i_result != 0) {
     25         cerr << "WSAStartup() function failed: " << i_result << "
    ";
     26         system("pause");
     27         return 1;
     28     }
     29     SecureZeroMemory(&hints, sizeof(hints));
     30     hints.ai_family = AF_UNSPEC;
     31     hints.ai_socktype = SOCK_STREAM;
     32     hints.ai_protocol = IPPROTO_TCP;
     33     //
     34     i_result = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
     35     if (i_result != 0) {
     36         cerr << "getaddrinfo() function failed with error: " << WSAGetLastError() << "
    ";
     37         WSACleanup();
     38         system("pause");
     39         return 1;
     40     }
     41     //创建套接字
     42     sock_client = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
     43     if (sock_client == INVALID_SOCKET) {
     44         cerr << "socket() function failed with error: " << WSAGetLastError() << "
    ";
     45         WSACleanup();
     46         system("pause");
     47         return 1;
     48     }
     49     //连接服务器
     50     i_result = connect(sock_client, result->ai_addr, result->ai_addrlen);
     51     if (i_result == SOCKET_ERROR) {
     52         cerr << "connect() function failed with error: " << WSAGetLastError() << "
    ";
     53         WSACleanup();
     54         system("pause");
     55         return 1;
     56     }
     57     cout << "connect server successfully..." << endl;
     58     //
     59     freeaddrinfo(result);
     60     //
     61     char send_buf[SEND_BUF_SIZE];
     62     int recv_result = 0;
     63     //SecureZeroMemory(send_buf, SEND_BUF_SIZE);
     64     do {
     65         cout << "enter the message that you want to send: " << flush;
     66         cin.getline(send_buf, SEND_BUF_SIZE);
     67         i_result = send(sock_client, send_buf, static_cast<int>(strlen(send_buf)), 0);
     68         if (i_result == SOCKET_ERROR) {
     69             cerr << "send() function failed with error: " << WSAGetLastError() << "
    ";
     70             closesocket(sock_client);
     71             WSACleanup();
     72             system("pause");
     73             return 1;
     74         }
     75         cout << "Bytes sent: " << i_result << endl;
     76         //接收服务器返回的数据
     77         recv_result = recv(sock_client, send_buf, SEND_BUF_SIZE, 0);
     78         if (recv_result > 0) {
     79             cout << "feedback from server: " << send_buf << endl;
     80         }
     81         else if (recv_result == 0) {
     82             cout << "connection closed..." << endl;
     83         }
     84         else {
     85             cerr << "recv() function failed with error: " << WSAGetLastError() << "
    ";
     86             closesocket(sock_client);
     87             WSACleanup();
     88             system("pause");
     89             return 1;
     90         }
     91     } while (recv_result > 0);
     92     //
     93     i_result = shutdown(sock_client, SD_SEND);
     94     if (i_result == SOCKET_ERROR) {
     95         cerr << "shutdown() function failed with error: " << WSAGetLastError() << "
    ";
     96         closesocket(sock_client);
     97         WSACleanup();
     98         system("pause");
     99         return 1;
    100     }
    101     closesocket(sock_client);
    102     WSACleanup();
    103     cout << "socket closed..." << endl;
    104     system("pause");
    105     return 0;
    106 }
  • 相关阅读:
    IBM实习
    软件测试——一些想法
    ftp文件上传下载实用命令
    Json解析,Json-lib
    eclipse Swt编程—窗口小部件widget
    Java 泛型
    我的理想与现实
    Java泛型介绍——HashMap总结
    Java语言面向对象的一些基本特点
    Java的一些常见问题,JRE,JDK,JVM,包等概念理解
  • 原文地址:https://www.cnblogs.com/jzincnblogs/p/5170230.html
Copyright © 2020-2023  润新知