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

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

运行服务器和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;

}

                                                                                                                      

结果:

相关推荐
zzzzzz3101 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode1 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220702 天前
如何搭建本地yum源(上)
运维
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质5 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz5 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工5 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智5 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_5 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化