• c++下基于windows socket的多线程服务器(基于TCP协议)


      之前用c++实现过基于windows socket的单线程TCP服务器(http://www.cnblogs.com/jzincnblogs/p/5170230.html),今天实现了一个多线程的版本,可以接受多个客户端的请求,原理与之前的单线程版本相似,只是在多线程版本中主线程用于监测客户端请求,每当有新客户端请求连接,主线程便新开一个线程用户处理客户端的请求。代码如下:

      头文件:

     1 #ifndef SERVER_H
     2 #define SERVER_H
     3 
     4 #include <Winsock2.h>
     5 #include <windows.h>
     6 
     7 #pragma comment (lib, "ws2_32.lib")
     8 
     9 #define IP_BUF_SIZE 129
    10 
    11 class Server
    12 {
    13 public:
    14     Server();
    15     ~Server();
    16     Server(const Server &) = delete;
    17     Server & operator=(const Server &) = delete;
    18     void WaitForClient();
    19 private:
    20     WORD winsock_ver;
    21     WSADATA wsa_data;
    22     SOCKET sock_svr;
    23     SOCKET sock_clt;
    24     HANDLE h_thread;
    25     SOCKADDR_IN addr_svr;
    26     SOCKADDR_IN addr_clt;
    27     int ret_val;
    28     int addr_len;
    29     char buf_ip[IP_BUF_SIZE];
    30 };
    31 
    32 #endif

      函数定义:

      1 #include "server.h"
      2 #include <iostream>
      3 #include <WS2tcpip.h>
      4 
      5 using std::cerr;
      6 using std::cout;
      7 using std::endl;
      8 
      9 #define SERVER_PORT 5000
     10 #define MSG_BUF_SIZE 1024
     11 
     12 Server::Server()
     13 {
     14     cout << "Initializing server...
    ";
     15     //
     16     winsock_ver = MAKEWORD(2, 2);
     17     addr_len = sizeof(SOCKADDR_IN);
     18     addr_svr.sin_family = AF_INET;
     19     addr_svr.sin_port = ::htons(SERVER_PORT);
     20     addr_svr.sin_addr.S_un.S_addr = ADDR_ANY;
     21     memset(buf_ip, 0, IP_BUF_SIZE);
     22     //
     23     ret_val = ::WSAStartup(winsock_ver, &wsa_data);
     24     if (ret_val != 0)
     25     {
     26         cerr << "WSA failed to start up!Error code: " << ::WSAGetLastError() << "
    ";
     27         system("pause");
     28         exit(1);
     29     }
     30     cout << "WSA started up successfully...
    ";
     31     //
     32     sock_svr = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     33     if (sock_svr == INVALID_SOCKET)
     34     {
     35         cerr << "Failed to create server socket!Error code: " << ::WSAGetLastError() << "
    ";
     36         ::WSACleanup();
     37         system("pause");
     38         exit(1);
     39     }
     40     cout << "Server socket created successfully...
    ";
     41     //
     42     ret_val = ::bind(sock_svr, (SOCKADDR*)&addr_svr, addr_len);
     43     if (ret_val != 0)
     44     {
     45         cerr << "Failed to bind server socket!Error code: " << ::WSAGetLastError() << "
    ";
     46         ::WSACleanup();
     47         system("pause");
     48         exit(1);
     49     }
     50     cout << "Server socket bound successfully...
    ";
     51     //
     52     ret_val = ::listen(sock_svr, SOMAXCONN);
     53     if (ret_val == SOCKET_ERROR)
     54     {
     55         cerr << "Server socket failed to listen!Error code: " << ::WSAGetLastError() << "
    ";
     56         ::WSACleanup();
     57         system("pause");
     58         exit(1);
     59     }
     60     cout << "Server socket started to listen...
    ";
     61     //
     62     cout << "Server started successfully..." << endl;
     63 }
     64 
     65 Server::~Server()
     66 {
     67     ::closesocket(sock_svr);
     68     ::closesocket(sock_clt);
     69     ::WSACleanup();
     70     cout << "Socket closed..." << endl;
     71 }
     72 
     73 DWORD WINAPI CreateClientThread(LPVOID lpParameter);
     74 //
     75 void Server::WaitForClient()
     76 {
     77     while (true)
     78     {
     79         sock_clt = ::accept(sock_svr, (SOCKADDR*)&addr_clt, &addr_len);
     80         if (sock_clt == INVALID_SOCKET)
     81         {
     82             cerr << "Failed to accept client!Error code: " << ::WSAGetLastError() << "
    ";
     83             ::WSACleanup();
     84             system("pause");
     85             exit(1);
     86         }
     87         ::InetNtop(addr_clt.sin_family, &addr_clt, buf_ip, IP_BUF_SIZE);
     88         cout << "A new client connected...IP address: " << buf_ip << ", port number: " << ::ntohs(addr_clt.sin_port) << endl;
     89         h_thread = ::CreateThread(nullptr, 0, CreateClientThread, (LPVOID)sock_clt, 0, nullptr);
     90         if (h_thread == NULL)
     91         {
     92             cerr << "Failed to create a new thread!Error code: " << ::WSAGetLastError() << "
    ";
     93             ::WSACleanup();
     94             system("pause");
     95             exit(1);
     96         }
     97         ::CloseHandle(h_thread);
     98     }
     99 }
    100 
    101 DWORD WINAPI CreateClientThread(LPVOID lpParameter)
    102 {
    103     SOCKET sock_clt = (SOCKET)lpParameter;
    104     char buf_msg[MSG_BUF_SIZE];
    105     int ret_val = 0;
    106     int snd_result = 0;
    107     do 
    108     {
    109         memset(buf_msg, 0, MSG_BUF_SIZE);
    110         ret_val = ::recv(sock_clt, buf_msg, MSG_BUF_SIZE, 0);
    111         if (ret_val > 0)
    112         {
    113             if (strcmp(buf_msg, "exit") == 0)
    114             {
    115                 cout << "Client requests to close the connection..." << endl;
    116                 break;
    117             }
    118             cout << "Message received: " << buf_msg << endl;
    119             snd_result = ::send(sock_clt, buf_msg, MSG_BUF_SIZE, 0);
    120             if (snd_result == SOCKET_ERROR)
    121             {
    122                 cerr << "Failed to send message to client!Error code: " << ::GetLastError() << "
    ";
    123                 ::closesocket(sock_clt);
    124                 system("pause");
    125                 return 1;
    126             }
    127         }
    128         else if (ret_val == 0)
    129         {
    130             cout << "connection closed..." << endl;
    131         }
    132         else
    133         {
    134             cerr << "Failed to receive message from client!Error code: " << ::GetLastError() << "
    ";
    135             ::closesocket(sock_clt);
    136             system("pause");
    137             return 1;
    138         }
    139     } while (ret_val > 0);
    140     //
    141     ret_val = ::shutdown(sock_clt, SD_SEND);
    142     if (ret_val == SOCKET_ERROR)
    143     {
    144         cerr << "Failed to shutdown the client socket!Error code: " << ::GetLastError() << "
    ";
    145         ::closesocket(sock_clt);
    146         system("pause");
    147         return 1;
    148     }
    149     return 0;
    150 }

      程序入口:

    1 #include "server.h"
    2 
    3 int main()
    4 {
    5     Server svr;
    6     svr.WaitForClient();
    7     system("pause");
    8     return 0;
    9 }
  • 相关阅读:
    C# 消息队列 RabbitMQ
    C# webapi简单学习
    Navicat Premium 12注册机使用教程
    .net WCF简单练习
    MSDN 我告诉你(资源库)
    Dapper查询返回Datatable
    day55 无连接,无状态,会话跟踪、cookie、django中操作cookie、session、django中操作session
    day54 锁和事务、ajax、中间件
    day53 url别名反向解析、ORM多表操作、聚合查询、分组查询、F查询、Q查询
    day52
  • 原文地址:https://www.cnblogs.com/jzincnblogs/p/5189636.html
Copyright © 2020-2023  润新知