当前位置: 首页 > news >正文

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

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

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

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

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

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

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

服务器:

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:


#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:

#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;

}

                                                                                                                      

结果:

相关文章:

  • LCS算法(文本相似度计算)
  • springmvc 框架学习
  • 国思RDIF低代码快速开发框架 v6.2版本发布
  • 【Qt】Qt + Modbus 服务端学习笔记
  • 论数据结构
  • 基于单片机控制的电动汽车双闭环调速系统(论文+源码)
  • PowerShell 美化 增强教程
  • go语言中空结构体
  • [代码规范]1_良好的命名规范能减轻工作负担
  • golang+redis 实现分布式限流
  • 蓝桥杯 握手问题
  • 【C#高阶编程】—单例模式详解
  • MySQL性能优化,sql优化有哪些,数据库如何优化设计(二)
  • 【软件工程】08_结构化设计方法
  • Bash 脚本基础
  • numpy学习笔记15:模拟100次随机游走,观察平均行为
  • 数据处理专题(二)
  • vue2 el-table跨分页多选以及多选回显
  • Springboot的MultipartFile,获取不到inputStream
  • SeaCMS代码审计
  • 软硬件企业集中发布未成年人模式使用手册
  • 事关广大农民利益,农村集体经济组织法5月1日起施行
  • 王毅:为改革完善全球治理作出金砖贡献
  • 买新房可申领学位,广州南沙出台购房入学政策
  • 王毅:坚持金砖团结合作,改革完善全球治理
  • 赛力斯拟赴港上市:去年扭亏为盈净利59亿元,三年内实现百万销量目标