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

news2025/7/8 6:20:34

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

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

}

                                                                                                                      

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2318331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode 2614.对角线上的质数:遍历(质数判断)

【LetMeFly】2614.对角线上的质数&#xff1a;遍历(质数判断) 力扣题目链接&#xff1a;https://leetcode.cn/problems/prime-in-diagonal/ 给你一个下标从 0 开始的二维整数数组 nums 。 返回位于 nums 至少一条 对角线 上的最大 质数 。如果任一对角线上均不存在质数&…

红日靶场(二)——个人笔记

靶场搭建 新增VMnet2网卡 **web&#xff1a;**需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMnet2网卡。 **PC&#xff1a;**跟web一样&#xff0c;也是需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMn…

实时视频分析的破局之道:蓝耘 MaaS 如何与海螺 AI 视频实现高效协同

一、蓝耘 MaaS 平台&#xff1a;AI 模型全生命周期管理的智能引擎 蓝耘 MaaS&#xff08;Model-as-a-Service&#xff09;平台是由蓝耘科技推出的 AI 模型全生命周期管理平台&#xff0c;专注于为企业和开发者提供从模型训练、推理到部署的一站式解决方案。依托云原生架构、高…

走进Java:String字符串的基本使用

❀❀❀ 大佬求个关注吧~祝您开心每一天 ❀❀❀ 目录 一、什么是String 二、如何定义一个String 1. 用双引号定义 2. 通过构造函数定义 三、String中的一些常用方法 1 字符串比较 1.1 字符串使用 1.2 字符串使用equals() 1.3 使用 equalsIgnoreCase() 1.4 cpmpareTo…

python系列之元组(Tuple)

不为失败找理由&#xff0c;只为成功找方法。所有的不甘&#xff0c;因为还心存梦想&#xff0c;所以在你放弃之前&#xff0c;好好拼一把&#xff0c;只怕心老&#xff0c;不怕路长。 python系列之元组&#xff08;Turple&#xff09; 一、元组是什么&#xff1f;——给新手的…

破解验证码新利器:基于百度OCR与captcha-killer-modified插件的免费调用教程

破解验证码新利器&#xff1a;基于百度OCR与captcha-killer-modified插件的免费调用教程 引言 免责声明&#xff1a; 本文提供的信息仅供参考&#xff0c;不承担因操作产生的任何损失。读者需自行判断内容适用性&#xff0c;并遵守法律法规。作者不鼓励非法行为&#xff0c;保…

批量删除 PPT 中的所有图片、某张指定图片或者所有二维码图片

PPT 文档中的图片如何删除呢&#xff1f;相信很多小伙伴或碰到类似的需求。比如我们需要删除 PPT 文档中的某一张图片或者某张二维码图片&#xff0c;如果每一页都有这张图片&#xff0c;或者有很多 ppt 都有同一张要删除的图片&#xff0c;我们应该怎么快速的完成删除呢&#…

大模型开发(六):LoRA项目——新媒体评论智能分类与信息抽取系统

LoRA项目——新媒体评论智能分类与信息抽取系统 0 前言1 项目介绍1.1 项目功能1.2 技术原理1.3 软硬件环境1.4 项目结构 2 数据介绍与处理2.1 数据集介绍2.2 数据处理2.3 数据导入器 3 模型训练3.1 配置文件3.2 工具函数3.3 模型训练3.4 模型评估 4 模型推理 0 前言 微调里面&…

mysql-innodb存储引擎主键索引叶子结点数据结构(非单纯的双向链表)

我们应该清楚行记录是放在页中的。 compact行记录格式&#xff1a; 主要介绍几个比较重要的参数 heap_no&#xff1a; 页号 record_type&#xff1a; 0 表示普通类型&#xff08;叶子结点&#xff09;&#xff0c;1表示B树的非叶子节点 &#xff0c;2 表示最小记录&#xff…

物联网为什么用MQTT不用 HTTP 或 UDP?

先来两个代码对比&#xff0c;上传温度数据给服务器。 MQTT代码示例 // MQTT 客户端连接到 MQTT 服务器 mqttClient.connect("mqtt://broker.server.com:8883", clientId) // 订阅特定主题 mqttClient.subscribe("sensor/data", qos1) // …

Vmware中的centos7连接上网

有很多刚刚开始配置了centos7&#xff0c;然后发现不能上网现在来解决这个问题。 测试能不能上网 先还原这个设置&#xff0c;如果没有动过的话就不用&#xff0c;连接模式是NAT模式 然后进去设置网络环境&#xff0c;记得是用超级用户设置 vi /etc/sysconfig/network-script…

【AI知识】常见的优化器及其原理:梯度下降、动量梯度下降、AdaGrad、RMSProp、Adam、AdamW

常见的优化器 梯度下降&#xff08;Gradient Descent, GD&#xff09;局部最小值、全局最小值和鞍点凸函数和非凸函数动量梯度下降&#xff08;Momentum&#xff09;自适应学习率优化器AdaGrad&#xff08;Adaptive Gradient Algorithm&#xff09;​RMSProp&#xff08;Root M…

线性规划的标准形式

标准形式的定义 目标函数&#xff1a;最大化线性目标函数 其中&#xff0c;x 是决策变量向量&#xff0c;c 是目标系数向量。 约束条件&#xff1a;等式形式约束 A x b, 其中&#xff0c;A 是约束系数矩阵&#xff0c;b 是常数项向量。 变量非负约束&#xff1a; 。 因此…

网络安全应急入门到实战

奇安信&#xff1a;95015网络安全应急响应分析报告&#xff08;2022-2024年&#xff09;官网可以下载 https://github.com/Bypass007/Emergency-Response-Notes 应急响应实战笔记 网络安全应急响应技术实战指南 .pdf 常见场景 第4章 勒索病毒网络安全应急响应 第5章 挖矿木…

应用程序安全趋势:左移安全、人工智能和开源恶意软件

软件是大多数行业业务运营的核心&#xff0c;这意味着应用程序安全从未如此重要。 随着组织采用云原生架构、微服务和开源组件&#xff0c;攻击面不断扩大。结果是&#xff1a;攻击者渴望利用的易受攻击和恶意依赖项数量不断增加。 2025 年&#xff0c;安全团队将面临日益复杂…

ospf动态路由

一、为什么使用动态路由 OSPF&#xff08;open shortest path first开放最短路径优先&#xff09;是内部网关协议(IGP)的一种&#xff0c;基于链路状态算法(LS)。 OSPF企业级路由协议(RFC2328 OSPFv2)&#xff0c;核心重点协议 OSPF共三个版本&#xff0c;OSPFV1主要是实验室…

基于单片机控制的电动汽车双闭环调速系统(论文+源码)

2.1系统方案 在本次设计中&#xff0c;其系统整个框图如下图3.1所示&#xff0c;其主要的核心控制模块由电源供电模块&#xff0c;晶振电路&#xff0c;驱动电路模块&#xff0c;霍尔传感器&#xff0c;按键模块&#xff0c;复位电路&#xff0c;LCD液晶显示及直流电机等组成。…

【病毒分析】伪造微软官网+勒索加密+支付威胁,CTF中勒索病毒解密题目真实还原!

1.背景 该CTF挑战题目完整复现了黑客的攻击链路&#xff0c;攻击者通过伪造钓鱼页面引导受害者下载恶意软件。用户访问伪造的 Microsoft 365 官网后&#xff0c;在点击“Windows Installer (64-bit)”下载选项时&#xff0c;页面会自动跳转至伪造的 GitHub 项目链接&#xff0…

PDF Reader Pro for Mac v4.9.0 PDF编辑/批注/OCR/转换工具 支持M、Intel芯片

PDF Reader Pro 是一款用户必备的集管理、编辑、转换、阅读功能于一体的专业的全能PDF阅读专家。快速、易用、强大&#xff0c;让您出色完成 PDF 工作。 应用介绍 PDF Reader Pro&#xff0c;一款功能齐全且强大的PDF阅读和编辑软件。支持PDF阅读、批注、PDF编辑、PDF格式转换…

PowerShell 美化 增强教程

PowerShell Windows Terminal 美化 & 增强教程 Windows Terminal PowerShell 默认外观和功能较为基础&#xff0c;但通过 Oh My Posh 及其他增强工具&#xff0c;你可以打造一个更美观、更高效的终端环境。本教程提供完整的安装、美化和优化步骤&#xff0c;包括常见问题…