网络编程---多客户端服务器

写一个服务器和两个客户端

运行服务器和2个客户端,实现聊天功能

客户端1 和 客户端2 进行聊天

客户端1将聊天数据发送给服务器

服务器将聊天数据转发给客户端2

要求: 服务器使用 select 模型实现 客户端1使用 poll 模型实现 客户端2使用 多线程实现

服务器:

cs 复制代码
1 
2 #include "head.h"
3 
4 #define PORT 12345
5 #define MAX_CLIENTS 10
6 #define BUFFER_SIZE 1024
7 
8 void handle_client_message(int client_sock, int *clients, int num_clients) {
9     char buffer[BUFFER_SIZE];
0     int bytes_received = recv(client_sock, buffer, sizeof(buffer), 0);
1     if (bytes_received <= 0) {
2         close(client_sock);
3         for (int i = 0; i < num_clients; i++) {
4             if (clients[i] == client_sock) {
5                 clients[i] = clients[num_clients - 1];
6                 break;
7             }
8         }
9         return;
0     }
1     buffer[bytes_received] = '\0';
2     printf("Received message: %s\n", buffer);
3 
4     // 广播消息给所有其他客户端
5     for (int i = 0; i < num_clients; i++) {
6         if (clients[i] != client_sock) {
7             send(clients[i], buffer, strlen(buffer), 0);
8         }
9     }
0 }
1 
2 void server() {
3     int server_sock, client_sock, max_fd;
4     struct sockaddr_in server_addr, client_addr;
5     socklen_t client_len = sizeof(client_addr);
6     fd_set read_fds, temp_fds;
7     int clients[MAX_CLIENTS];
8     int num_clients = 0;
9 
0     // 创建服务器socket
1     server_sock = socket(AF_INET, SOCK_STREAM, 0);
2     if (server_sock < 0) {
3         perror("Socket creation failed");
4         exit(EXIT_FAILURE);
5     }
6 
7     // 绑定服务器地址
8     memset(&server_addr, 0, sizeof(server_addr));
9     server_addr.sin_family = AF_INET;
0     server_addr.sin_addr.s_addr = INADDR_ANY;
1     server_addr.sin_port = htons(PORT);
2 
3     if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
4         perror("Binding failed");
5         exit(EXIT_FAILURE);
6     }
7 
8     // 监听客户端连接
9     listen(server_sock, 5);
0     FD_ZERO(&read_fds);
1     FD_SET(server_sock, &read_fds);
2     max_fd = server_sock;
3 
4     printf("Server listening on port %d...\n", PORT);
5 
6     while (1) {
7         temp_fds = read_fds;
8 
9         // 使用select等待活动的socket
0         if (select(max_fd + 1, &temp_fds, NULL, NULL, NULL) < 0) {
1             perror("Select error");
2             exit(EXIT_FAILURE);
3         }
4 
5         // 检查所有客户端连接
6         for (int i = 0; i <= max_fd; i++) {
7             if (FD_ISSET(i, &temp_fds)) {
8                 if (i == server_sock) {
9                     // 有新的客户端连接
0                     client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len);
1                     if (client_sock < 0) {
2                         perror("Accept failed");
3                         continue;
4                     }
5                     printf("New connection: %d\n", client_sock);
6 
7                     FD_SET(client_sock, &read_fds);
8                     clients[num_clients++] = client_sock;
9                     if (client_sock > max_fd) {
0                         max_fd = client_sock;
1                     }
2                 } else {
3                     // 处理现有客户端的消息
4                     handle_client_message(i, clients, num_clients);
5                 }
6             }
7         }
8     }
9                                                                                                                                   
0     close(server_sock);
1 }
2 
3 int main() {
4     server();
5     return 0;
6 }
7 
                                                                                                                                    

客户端1:

cs 复制代码
#include "head.h"

#define PORT 12345
#define BUFFER_SIZE 1024

void client1() {
    int sock;
    struct sockaddr_in server_addr;
    struct pollfd fds[2];
    char buffer[BUFFER_SIZE];

    // 创建客户端socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(PORT);

    // 连接到服务器
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        exit(EXIT_FAILURE);
    }

    printf("Connected to server. Type your messages.\n");

    // 设置poll结构
    fds[0].fd = sock; // 服务器socket
    fds[0].events = POLLIN;
    fds[1].fd = STDIN_FILENO; // 标准输入
    fds[1].events = POLLIN;

    while (1) {
        // 使用poll模型
        int ret = poll(fds, 2, -1);
        if (ret < 0) {
            perror("Poll failed");
            exit(EXIT_FAILURE);
        }

        if (fds[0].revents & POLLIN) {
            // 服务器发送消息
            int n = recv(sock, buffer, sizeof(buffer), 0);
            if (n <= 0) {
                printf("Server disconnected\n");
                break;
            }
            buffer[n] = '\0';
            printf("Server: %s\n", buffer);
        }

        if (fds[1].revents & POLLIN) {
            // 用户输入消息
            if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
                send(sock, buffer, strlen(buffer), 0);
            }
        }
    }

    close(sock);
}

int main() {                                                                                                      
    client1();
    return 0;
}

客户端2:

cs 复制代码
#include "head.h"

#define PORT 12345
#define BUFFER_SIZE 1024

void *receive_messages(void *socket_desc) {
    int sock = *(int *)socket_desc;
    char buffer[BUFFER_SIZE];
    while (1) {
        int n = recv(sock, buffer, sizeof(buffer), 0);
        if (n <= 0) {
            printf("Server disconnected\n");
            break;
        }
        buffer[n] = '\0';
        printf("Server: %s\n", buffer);
    }
    return NULL;
}

void client2() {
    int sock;
    struct sockaddr_in server_addr;
    pthread_t thread_id;
    char buffer[BUFFER_SIZE];

    // 创建客户端socket
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(PORT);

    // 连接到服务器
    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        exit(EXIT_FAILURE);
    }

    printf("Connected to server. Type your messages.\n");

    // 创建接收消息线程
    if (pthread_create(&thread_id, NULL, receive_messages, (void *)&sock) < 0) {
        perror("Could not create thread");
        exit(EXIT_FAILURE);
    }
                                                                                                                      
    // 发送消息
    while (1) {
        fgets(buffer, sizeof(buffer), stdin);
        send(sock, buffer, strlen(buffer), 0);
    }

    close(sock);
}

int main() {
    client2();
     return 0;

}

                                                                                                                      

结果:

相关推荐
晚风_END几秒前
kubernetes|云原生|部署单master的kubernetes 1.25.5版本集群完全记录(使用contained 运行时)
java·运维·开发语言·云原生·容器·golang·kubernetes
三朝看客1 小时前
docker利用ollama +Open WebGUI在本地搭建部署一套Deepseek-r1模型
运维·docker·容器
Kaede61 小时前
在Ubuntu上安装MEAN Stack的4个步骤
linux·运维·ubuntu
SecPulse2 小时前
xss注入实验(xss-lab)
服务器·前端·人工智能·网络安全·智能路由器·github·xss
szxinmai主板定制专家4 小时前
基于FPGA轨道交通6U机箱CPCI脉冲板板卡
大数据·运维·人工智能·fpga开发·边缘计算
踩踩踩从踩4 小时前
Tengine:高性能Web 服务器与反向代理
运维·服务器·前端
v维焓4 小时前
网络编程之客户端聊天(服务器加客户端共三种方式)
运维·服务器·网络
nihuhui6665 小时前
Vlan初级实验
服务器·网络·网络协议
IT小饕餮5 小时前
Linux 安装apache服务
linux·运维·apache
大叔是90后大叔8 小时前
Centos编译升级libcurl
linux·运维·centos