📜  使用 CC++ 中的套接字编程通过多线程处理服务器上的多个客户端(1)

📅  最后修改于: 2023-12-03 15:06:45.536000             🧑  作者: Mango

使用 CC++ 中的套接字编程通过多线程处理服务器上的多个客户端

在计算机网络中,套接字(Socket)是应用程序进程间进行双向通信的一种机制。在 C 和 C++ 中,我们可以使用套接字编程实现网络通信,包括服务端和客户端。本文主要介绍如何利用 CC++ 中的套接字编程通过多线程处理服务器上的多个客户端。

套接字编程基础

在 CC++ 中使用套接字编程,需要引入头文件 sys/types.hsys/socket.hnetinet/in.h。其中,sys/types.hsys/socket.h 定义了套接字相关的类型和函数,netinet/in.h 定义了互联网地址族相关的常量和函数。

创建服务器的步骤如下:

  1. 创建套接字(socket):调用 socket() 函数创建一个套接字,该函数返回一个整型值,表示创建的套接字描述符。
  2. 绑定地址(bind):使用 bind() 函数将创建的套接字与本机的 IP 地址和端口号绑定起来。这里的端口号需要确认该端口是否可用,如果无法使用,则需要选择其他端口。
  3. 监听(listen):使用 listen() 函数将套接字设为监听模式,指示该套接字可以接受来自客户端的连接请求。
  4. 接受连接(accept):当有客户端连接请求到达时,使用 accept() 函数接受客户端的连接请求,并返回一个新的套接字描述符,用于与该客户端进行通信。
  5. 数据交换(read/write):使用 read() 函数从客户端读取数据,使用 write() 函数将数据发送给客户端。

客户端的步骤如下:

  1. 创建套接字(socket):调用 socket() 函数创建一个套接字,该函数返回一个整型值,表示创建的套接字描述符。
  2. 连接服务器(connect):使用 connect() 函数向服务器发送连接请求,如果连接成功,返回值为 0。
  3. 数据交换(read/write):使用 read() 函数从服务器读取数据,使用 write() 函数将数据发送给服务器。
多线程处理多个客户端

在服务器端,当有多个客户端同时连接时,可以使用多线程来处理多个客户端的请求。具体实现方法为,在接受连接请求时,每连接一个客户端,创建一个新的线程来处理该客户端的请求。

首先,在服务器端,需要引入头文件 pthread.h,使用 pthread_t 类型来定义线程,使用 pthread_create() 函数创建新的线程,使用 pthread_join() 函数等待新线程完成。

服务器端的代码示例如下:

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>

#define PORT 8080

void *handle_client(void *arg)
{
    int client_fd = *(int*)arg;
    char buffer[1024] = {0};
    read(client_fd, buffer, sizeof(buffer));
    std::cout << "Received message: " << buffer << std::endl;
    write(client_fd, "Hello from server", 17);
    close(client_fd);
    pthread_exit(NULL);
}

int main()
{
    int server_fd, client_fd;
    struct sockaddr_in address, client_address;
    int addrlen = sizeof(address);
    pthread_t newthread;

    // Create socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);

    // Bind address
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));

    // Listen for connections
    listen(server_fd, 5);
    std::cout << "Server started, listening on port " << PORT << std::endl;

    while(1)
    {
        // Accept connection
        client_fd = accept(server_fd, (struct sockaddr *)&client_address, (socklen_t*)&addrlen);
        std::cout << "New connection from " << inet_ntoa(client_address.sin_addr) << ":" << ntohs(client_address.sin_port) << std::endl;

        if(pthread_create(&newthread, NULL, handle_client, (void*)&client_fd) != 0)
            std::cerr << "Error creating thread" << std::endl;

        pthread_join(newthread, NULL);
    }
}

在上面的代码中,handle_client() 函数用于处理客户端的请求。其中,arg 参数是一个指向客户端套接字描述符的指针,首先使用 read() 函数读取客户端发送的数据,然后使用 write() 函数向客户端返回一条消息。最后,使用 pthread_exit() 函数退出子线程。

在主函数中,当有客户端连接时,创建一个新的线程,并将客户端套接字描述符作为参数传递给子线程处理。使用 pthread_join() 函数等待子线程执行完成。

结语

本文介绍了如何使用 CC++ 中的套接字编程通过多线程处理服务器上的多个客户端。通过多线程处理客户端请求可以提升服务器的并发能力,实现高效的网络通信。