poll实现echo服务器的并发

poll实现echo服务器的并发

代码实现

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/poll.h>

#define MAX_CLI 50

int clients[MAX_CLI];
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);

int socket_create(int port) {//创建并绑定网络监听的socket套接字
    int fd;
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    if (listen(fd, 20) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    return fd;
}
int recv_msg(int fd, char *buff, int size) { 

    int rsize = recv(fd, buff, sizeof(char ) * size, 0);
    if (rsize <= 0) {
        if (rsize == 0) return 0;
        return -1;
    }
    printf("Recv : %s\n", buff);
    return 1;
}

int send_msg(int fd, char *buff, int size) {
    int ssize = send(fd, buff, sizeof(char ) * size, 0);
    if (ssize <= 0) {
        if (ssize == 0) return 0;
        return -1;
    }
    printf("Send success!\n");
    return 1;
}

void echo_work(int server_listen) {
    struct pollfd fds[MAX_CLI + 1];
    fds[0].fd = server_listen;
    fds[0].events = POLLIN;
    int max_fd = server_listen;

    while (1) {
        int ret = poll(fds, MAX_CLI + 1, -1);
        if (ret == -1) {
            perror("poll");
            exit(EXIT_FAILURE);
        }

        //接受连接请求
        if (fds[0].revents & POLLIN) {
            int client_fd;
            if ((client_fd = accept(server_listen, (struct sockaddr *)&clientaddr, &len)) < 0) {
                perror("accept");
                exit(EXIT_FAILURE);
            }
            printf("one client connect success!\n");

            for (int i = 0; i < MAX_CLI; i++) {
                if (clients[i] == -1) {
                    clients[i] = client_fd;
                    break;
                }
            }

            //更新pollfd数组
            for (int i = 1; i  <= MAX_CLI; i++) {
                if (clients[i - 1] != -1) {
                    fds[i].fd = clients[i - 1];
                    fds[i].events = POLLIN;
                    max_fd = fds[i].fd > max_fd ? fds[i].fd : max_fd;
                }
            }
        }
        //检查客户端套接字是否有数据可读
        for (int i = 1; i <= MAX_CLI; i++) {
            if (fds[i].revents & POLLIN) {
                char buff[1024] = {0};
                if (recv_msg(fds[i].fd, buff, 1024) <= 0) {
                    printf("disconnect one client  OR error!\n");
                    close(fds[i].fd);
                    clients[i - 1] = -1;
                    continue;
                } 
                
                if (send_msg(fds[i].fd, buff, 1024) <= 0) {
                     printf("disconnect one client  OR error!\n");
                    close(fds[i].fd);
                    clients[i - 1] = -1;
                    continue;
                } 
            }
        }
    } 
    return ;
}


int main() {
    int server_listen;

    if ((server_listen = socket_create(8080)) < 0) {
        perror("socket_create");
        exit(EXIT_FAILURE);
    }
    for(int i = 0; i < MAX_CLI; i++) clients[i] = -1;
    echo_work(server_listen);

    return 0;
}

运行效果

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ 初识模板

目录 0.前言 1.泛型编程 2.函数模板 2.1概念 2.2格式 2.3原理 2.4函数模板的实例化 2.4.1隐式实例化 2.4.2显式实例化 2.5模板参数的匹配原则 3.类模板 3.1类模板的定义格式 3.2类模板的实例化 4.结语 &#xff08;图像由AI生成&#xff09; 0.前言 在 C 中&a…

密码学 | 承诺:常见的承诺方案

&#x1f951;原文&#xff1a;密码学原语如何应用&#xff1f;解析密码学承诺的妙用 - 知乎 1 简介 密码学承诺 涉及 承诺方、验证方 两个参与方&#xff0c;以及以下两个阶段&#xff1a; 承诺阶段&#xff1a;承诺方选择一个敏感数据 v v v&#xff0c;为它计算出相应…

【团体程序设计天梯赛】L2-052 吉利矩阵

思路&#xff1a; 直接回溯枚举每一个位置填的数&#xff0c;二维肯定是不方便的&#xff0c;我们转成一维&#xff0c;下标x从0到n*n-1。二维数组下标从0到n-1&#xff0c;在一维中下标为x的点在二维中对应行是x/n&#xff0c;列是x%n。 每个数最小能填的是0&#xff0c;最大…

总结线程池

目录 导言&#xff1a; 正文&#xff1a; 1.概念 2.线程池的组成和基本原理 3.使用ThreadPoolExecutor创建线程池 4.使用Executors 创建常见的线程池 总结&#xff1a; 导言&#xff1a; 虽然创建销毁线程比创建销毁进程更轻量&#xff0c; 但是在频繁创建销毁线程的时候…

深度学习transformer架构详细详解

一、transformer的贡献 transformer架构的贡献&#xff1a;该架构只使用自注意力机制&#xff0c;没有使用RNN或卷积网络。且可以实现并行计算&#xff0c;加快模型训练速度。 &#xff08;将所有的循环层全部换成&#xff1a;multi-headed self-attention&#xff09; 二、t…

JavaScript运算符(赋值、自增自减、比较、逻辑、展开、优先级)、分支语句(if、三元表达式、switch)、循环结构(while、for)、断点调试

目录 1. 运算符1.1 赋值运算符1.2 自增和自减运算符1.3 比较运算符1.4 逻辑运算符1.5 展开运算符1.6 运算符优先级 2. 分支语句2.1 if2.2 三元表达式2.3 switch 3. 循环结构3.1 while循环3.2 for循环 4. 断点调试 1. 运算符 1.1 赋值运算符 -*/% 1.2 自增和自减运算符 前置…

(C++) 树状数组

目录 一、介绍 二、一维树状数组 2.1 区间长度 2.2 前驱和后继 2.3 查询前缀和 2.4 点更新 三、一维数组的实现 3.1 区间长度函数 3.2 前缀和 3.3 插入/更新 3.4 封装成类 一、介绍 树状数组&#xff08;Binary Indexed Tree&#xff0c;BIT&#xff09;&#xff0c;又称为 …

ActiveMQ 如果数据处理出现异常会怎么样

我们有一个 Spring 的客户端&#xff0c;在处理消息的时候因为程序的原因出现消息处理异常。 对这种情况&#xff0c;ActiveMQ 会把出现异常的消息放在 DLQ 队列中进行持久化。 因此&#xff0c;在 ActiveMQ 消息处理队列中需要持续关注 DLQ 队列&#xff0c; DLQ 的队列都是无…

线段树汇总

线段树是一种二叉搜索树&#xff0c;与区间树相似&#xff0c;它将一个区间划分成一些单元区间&#xff0c;每个单元区间对应线段树中的一个叶结点。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数&#xff0c;时间复杂度为O(logN)。而未优化的空间复杂度为2N&a…

最新版的GPT-4.5-Turbo有多强

OpenAI再次用实力证明了&#xff0c;GPT依然是AI世界最强的玩家&#xff01;在最新的AI基准测试中&#xff0c;OpenAI几天前刚刚发布的GPT-4-Turbo-2024-04-09版本&#xff0c;大幅超越了Claude3 Opus&#xff0c;重新夺回了全球第一的AI王座&#xff1a; 值得一提的是&#xf…

【机器学习】重塑汽车设计与制造:实例与代码探索

机器学习重塑汽车设计与制造 一、机器学习在汽车设计中的应用二、机器学习在智能制造与生产中的应用 在数字化浪潮的推动下&#xff0c;机器学习技术正逐步成为汽车行业的创新引擎。从概念设计到智能制造&#xff0c;机器学习正以其独特的优势助力汽车产业的革新与发展。本文将…

实现基于RAG的QA应用程序

实现基于RAG的Q&A应用程序 LLM 支持的最强大的应用程序之一是复杂的 问答 &#xff08;Q&A&#xff09; 聊天机器人。这些应用程序可以 回答有关特定来源信息的问题。这些应用程序 使用一种称为检索增强生成 &#xff08;RAG&#xff09; 的技术。 什么是检索增强生成…

Golang | Leetcode Golang题解之第43题字符串相乘

题目&#xff1a; 题解&#xff1a; func multiply(num1 string, num2 string) string {if num1 "0" || num2 "0" {return "0"}m, n : len(num1), len(num2)ansArr : make([]int, m n)for i : m - 1; i > 0; i-- {x : int(num1[i]) - 0fo…

设计模式之访问者模式(上)

访问者模式 1&#xff09;概述 1.概念 访问者模式包含访问者和被访问元素两个主要组成部分。 处方单中的各种药品信息就是被访问的元素&#xff0c;而划价人员和药房工作人员就是访问者&#xff0c;被访问的元素通常具有不同的类型&#xff0c;且不同的访问者可以对它们进行…

上位机图像处理和嵌入式模块部署(树莓派4b处理类muduo网络编程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 既然是linux编程&#xff0c;那么自然少不了网络编程。在linux平台上面&#xff0c;有很多的网络编程库可以选择&#xff0c;大的有boost、qt&…

免费PNG素材网站推荐:设计效率倍增!

一、即时设计 新一代协同设计工具即时设计&#xff0c;内置丰富社区资源&#xff0c;可以在此获得设计前线的各类PNG图像&#xff0c;以及矢量图标&#xff0c;包括毛玻璃、3D混搭、全息投影、单色、平面化等&#xff0c;都是符合目前市场的主流风格。通过最近更新、作品、资源…

影响钕铁硼磁钢性能的因素及方法

钕铁硼永磁材料自问世以来&#xff0c;就以其优越的磁性能而备受关注&#xff0c;被称为“磁王“&#xff0c;在市场需求的不断地增长下&#xff0c;钕铁硼生产工艺及磁体性能也不断发展和提升。我们一般用剩磁、矫顽力和最大磁能积这几个指标来衡量磁性材料的磁性能。 剩磁 B…

【C++】:类和对象(上)

目录 一&#xff0c;面向过程和面向对象初步认识二&#xff0c;类的引入三&#xff0c;类的定义3.1 **类的说明**3.2 **类的访问限定符**3.3 **类的两种实现方式**3.4 **成员变量的命名规则 --- 加下划线** 四&#xff0c;类的作用域4.1 **类域的说明**4.2 **类域与命名空间域的…

分析经过j2k压缩的dicom文件经验分享

最近碰到一个问题&#xff0c;在网上搜到是用JPEG 2000压缩的DICOM文件 JPEG 2000对应的transfer syntax UID为 1.2.840.10008.1.2.4.91 参考:https://dicom.nema.org/medical/dicom/current/output/chtml/part18/sect_8.7.3.html 该文件是用专业德国老牌开发库DCMTK生成的 (…

虚拟机VMware安装与Ubuntu

1.虚拟机安装 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;2fr6 CG54H-D8D0H-H8DHY-C6X7X-N2KG6 2.Ubuntu下载 Download Ubuntu Desktop | Ubuntu 3.设置 如后续要下一些软件越大越好