c语言实现io多路复用(select),进程,线程并发服务器

io多路复用(select)代码

#include<myhead.h>
#include <sys/select.h>
#define PORT 8888 
#define IP   "192.168.250.100"
int main(int argc, char const *argv[])
{    //创建套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd == -1){perror("socket error");return -1;}//端口重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);struct sockaddr_in sin;sin.sin_family     = AF_INET;         //表明是ipv4sin.sin_port     = htons(PORT);        //端口号sin.sin_addr.s_addr = inet_addr(IP);     //IP地址//绑定端口if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1){perror("bind error");return -1;}printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//监听模式if(listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);struct sockaddr_in cin;             //客户端地址信息结构体cin.sin_family     = AF_INET;socklen_t socklen = sizeof(cin);          //客户端地址信息的大小//定义文件描述符集合fd_set readfds, tempfds;//清空readfdsFD_ZERO(&readfds);//将套接字和标准输入放入集合FD_SET(sfd,&readfds);FD_SET(0,&readfds);//定义信息容器char buf[128] = "";int res = 0;             //接收select的返回值int newfd = -1;          //存放用于最新连接客户端的套接字int maxfd = sfd;          //定义控制select函数中最大文件描述符struct sockaddr_in saveCin[1024];       //用于存放客户端地址信息结构体
while (1){将集合内容复制一份tempfds = readfds;使用select阻塞等待集合中的文件描述符有事件产生res = select(maxfd+1, &tempfds, NULL, NULL, NULL);if(res == -1){perror("select error");return -1;}else if(res == 0){printf("time out\n");return -1;}for(int i=0; i<=maxfd; i++){if(!FD_ISSET(i, &tempfds)){continue;}if( i == sfd){newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);if(newfd == -1){perror("accept error");return -1;}printf("accept success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//将新的套接字放入select集合           FD_SET(newfd , &readfds);//更新maxfdif(newfd > maxfd){maxfd = newfd;}saveCin[newfd] = cin;}else if(i == 0 ){char buf1[128] = "";bzero(buf, sizeof(buf));fgets(buf, sizeof(buf), stdin);       buf[strlen(buf)-1]='\0';printf("终端输入:%s\n", buf);sprintf(buf1, "%s%s", "系统消息:", buf);//将数据发送给所有客户端,群发功能相当于将整个套接字集中的每一可客户端都发一遍for(int j=4; j<=maxfd; j++){send(j, buf1,sizeof(buf1), 0);}}else{//收发数据使用newfd完成通信char buf[128] = "";//清空字符串bzero(buf, sizeof(buf));int ret = recv(i, buf, sizeof(buf), 0);        //从套接字中读取客户端发来的消息//判断收到的结果if(ret == 0){printf("客户端已经下线\n");    close(i);             //关闭通信的套接字将当前的文件描述符从集合中删除FD_CLR(i, &readfds);更新maxfdfor(int j=maxfd; j>=0; j--){//判断当前的j是否在集合中,如果在,则为maxfdif(FD_ISSET(j, &readfds)){maxfd = j;break;}}continue;           //继续判断下一个}else if(ret < 0){perror("recv error");return -1;}printf("[%s:%d]:%s\n", inet_ntoa(saveCin[i].sin_addr), ntohs(saveCin[i].sin_port), buf);send(i, buf, sizeof(buf), 0); } }}return 0;
}

io多路复用(select)结果图

进程代码

#include<myhead.h>
#define PORT 8888 
#define IP   "192.168.250.100"
//处理客户端请求
int cli_msg(int newfd,struct sockaddr_in cin)
{char buf[128]="";while (1){bzero(buf, sizeof(buf));int res = recv(newfd, buf, sizeof(buf), 0);if (res==0){printf("客户端已经下线\n");break;}else if(res<0){perror("recv error");return -1;}printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);send(newfd, buf, sizeof(buf), 0); }close(newfd);   return 0;}
//回收僵尸进程
void handler(int signo)
{if(signo == SIGCHLD){while(waitpid(-1, NULL, WNOHANG) > 0);       }
}int main(int argc, char const *argv[])
{//创建套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);if(sfd == -1){perror("socket error");return -1;}//设置端口重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//设定地址信息结构体struct sockaddr_in sin;sin.sin_family     = AF_INET;         //表明是ipv4sin.sin_port     = htons(PORT);        //端口号sin.sin_addr.s_addr = inet_addr(IP);     //IP地址//绑定地址if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1){perror("bind error");return -1;}printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//开启监听if(listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);struct sockaddr_in cin;             //客户端地址信息结构体cin.sin_family     = AF_INET;socklen_t socklen = sizeof(cin);          //客户端地址信息的大小pid_t pid;//绑定进程的信号,信号触发就执行handler函数if(signal(SIGCHLD, handler) == SIG_ERR){perror("signal error");return -1;}while (1){//阻塞接收客户端请求int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);if(newfd == -1){perror("accept error");return -1;}//创建子进程pid = fork();//父进程负责连接if(pid > 0){//父进程不用newfd,回收newfdclose(newfd);}//子进程负责请求响应else if(pid==0){//子进程不用sfd,就回收sfdclose(sfd);cli_msg(newfd, cin);//回收子进程exit(EXIT_SUCCESS);}else{perror("fork error");return -1;}}//关闭所有套接字并关闭监听close(sfd);return 0;
}

进程的结果图

线程代码

 

#include<myhead.h>
#define PORT 8888 
#define IP   "192.168.250.100"
//定义存储客户端地址信息结构体和连接请求套接字的结构体
struct msg_info{int newfd;struct sockaddr_in cin;
};//定义线程体
void *task1(void *arg)
{//将外部值传入int newfd=((struct msg_info*)arg)->newfd;struct sockaddr_in cin=((struct msg_info*)arg)->cin;//定义收发容器char buf[128]="";while (1){//响应客户端请求bzero(buf,sizeof(buf));int res=recv(newfd,buf,sizeof(buf),0);if(res==0){printf("客户端已经下线");break; }else if(res>0){printf("[%s:%d]:%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);send(newfd,buf,sizeof(buf),0);}else{perror("recv error:");return NULL;}}//关闭连接套接字close(newfd);//退出线程pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{pthread_t tid;int sfd=socket(AF_INET,SOCK_STREAM,0);int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("设置端口快速重用成功 _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//绑定的地址信息结构体struct sockaddr_in sin;sin.sin_family     = AF_INET;         //表明是ipv4sin.sin_port     = htons(PORT);        //端口号sin.sin_addr.s_addr = inet_addr(IP);     //IP地址if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))==-1){perror("bind error");return -1;}printf("bind success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//将套接字设置成监听状态if(listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);struct sockaddr_in cin;             cin.sin_family     = AF_INET;socklen_t socklen = sizeof(cin);          while(1){//阻塞接收客户端的链接请求,并且获取客户端的地址信息int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);if(newfd == -1){perror("accept error");return -1;}printf("accept success _%d_ %s_ %s_\n", __LINE__, __FILE__, __func__);//定义用于向线程体传参的结构体变量struct msg_info info = {newfd, cin};//线程创建,并向线程体传参的结构体pthread_create(&tid,NULL,task1,&info);//线程分离if(pthread_detach(tid) != 0){printf("分离失败\n");return -1;}}close(sfd);return 0;
}

线程结果图

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

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

相关文章

常见的 MIME(媒体)类型速查

一、简介 MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型&#xff0c;是设定某种扩展名的文件用一种应用程序来打开的方式类型&#xff0c;当该扩展名文件被访问的时候&#xff0c;浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文…

P1808 单词分类

P1808 单词分类 题目描述 Oliver 为了学好英语决定苦背单词&#xff0c;但很快他发现要直接记住杂乱无章的单词非常困难&#xff0c;他决定对单词进行分类。 两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等。 例如 AABAC&#xff0c;它和 CBAAA 就可以…

时序预测 | MATLAB实现基于CNN-BiLSTM-AdaBoost卷积双向长短期记忆网络结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于CNN-BiLSTM-AdaBoost卷积双向长短期记忆网络结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于CNN-BiLSTM-AdaBoost卷积双向长短期记忆网络结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.Matlab实现…

SpringBoot3整合Mybatis-Plus,自定义动态数据源starter

文章目录 前言正文一、项目总览二、核心代码展示2.1 自定义AbstractRoutingDataSource2.2 动态数据源DynamicDataSource2.3 动态数据源自动配置2.4 动态数据源上下文DynamicDataSourceContextHolder2.5 动态数据源修改注解定义2.6 修改切面DynamicDataSourceAspect2.7 动态数据…

多维时序 | MATLAB实现基于CNN-LSSVM卷积神经网络-最小二乘支持向量机多变量时间序列预测

多维时序 | MATLAB实现基于CNN-LSSVM卷积神经网络-最小二乘支持向量机多变量时间序列预测 目录 多维时序 | MATLAB实现基于CNN-LSSVM卷积神经网络-最小二乘支持向量机多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于CNN-LSSVM卷积神经…

vue+vite项目,动态导入静态资源的几种方式

博主的桌面工具软件已经正式开发&#xff0c;获取方式&#xff1a; 可以关注我的小程序【中二少年工具箱】获取。&#xff08;若小程序更新有延迟&#xff0c;可先收藏小程序&#xff09; 通过下载链接 百度网盘: 链接&#xff1a;https://pan.baidu.com/s/15zDnSoEzJGSZLjpD…

跟着pink老师前端入门教程-day20

二、移动WEB开发之flex布局 1、flex 布局体验 1.1 传统布局与flex布局 传统布局&#xff1a;兼容性好、布局繁琐、局限性、不能再移动端很好的布局 flex弹性布局&#xff1a;操作方便&#xff0c;布局极为简单&#xff0c;移动端应用很广泛&#xff1b;PC 端浏览器支持情况…

SpringbootV2.6整合Knife4j 3.0.3 问题记录

参考 https://juejin.cn/post/7249173717749940284 近期由于升级到springboot2.6X&#xff0c;所以服务端很多组件都需要重新导入以及解决依赖问题。 下面就是一个很经典的问题了&#xff0c; springboot2.6与knife4j的整合。 版本对应 springboot2.6与knife4j 3.0.3 坑 …

c++二叉树寒假特训题目(1)

大家好&#xff0c;我是周曦&#xff0c;今天给大家推荐一些二叉树题目。 题目 二叉树存储 这道题是道水题&#xff0c;找找规律ok&#xff0c;本人代码10行。 淘汰赛 这道题推荐使用桶数组 做比较合适&#xff08;就是有点绕&#xff09;。 二叉树深度 这题是一道深搜题&a…

eclipse使用google的Java代码格式

插件下载地址 1.下载eclipse的插件 2.下载的jar包放到eclipse安装目录的dropins文件夹 D:\install_package\STS\sts-4.10.0.RELEASE\dropins&#xff13;.重启后设置 eclipse - windows - preference - java - code style - formatter -

MySQL篇----第十二篇

系列文章目录 文章目录 系列文章目录前言一、可以使用多少列创建索引?二、NOW()和 CURRENT_DATE()有什么区别?三、什么是非标准字符串类型?四、什么是通用 SQL 函数?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转…

【蓝桥杯冲冲冲】Invasion of the Milkweed G

【蓝桥杯冲冲冲】Invasion of the Milkweed G 蓝桥杯备赛 | 洛谷做题打卡day30 文章目录 蓝桥杯备赛 | 洛谷做题打卡day30[USACO09OCT] Invasion of the Milkweed G题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题解代码我的一些话 [USACO09OCT] Invasion of the Mi…

linux centos 安装teleport

效果 安装 1.创建目录 mkdir -p /opt/teleport/data cd /opt/teleport/2.下载解压文件 wget https://tp4a.com/static/download/teleport-server-linux-x64-3.6.4-b3.tar.gz tar -xvf teleport-server-linux-x64-3.6.4-b3.tar.gz3.安装 cd /opt/teleport/teleport-server-l…

Python学习路线 - Python高阶技巧 - 拓展

Python学习路线 - Python高阶技巧 - 拓展 闭包闭包注意事项 装饰器装饰器的一般写法(闭包写法)装饰器的语法糖写法 设计模式单例模式工厂模式 多线程进程、线程并行执行多线程编程threading模块 网络编程Socket客户端和服务端Socket服务端编程实现服务端并结合客户端进行测试 S…

D音等短视频为什么这么吸引人?长期沉迷刷D音的危害 彻底戒掉刷D音上瘾 占用大量时间 注意力分散 思维浅薄 焦虑、抑郁 干扰睡眠 视力疲劳

这是你吗&#xff1f; 人生最爽的事是&#xff1a;刷痘印。 人生最不爽的事是&#xff1a;刷完&#xff0c;什么也没有得到&#xff0c;事也没做。 吸引法则 1. 内容碎片化&#xff0c;符合快节奏时代需求 短视频的时长通常只有几秒到十几分钟&#xff0c;内容简短精悍&…

苹果macbook电脑删除数据恢复该怎么做?Mac电脑误删文件的恢复方法

苹果电脑删除数据恢复该怎么做&#xff1f;Mac电脑误删文件的恢复方法 如何在Mac上恢复误删除的文件&#xff1f;在日常使用Mac电脑时&#xff0c;无论是工作还是娱乐&#xff0c;我们都会创建和处理大量的文件。然而&#xff0c;有时候可能会不小心删除一些重要的文件&#x…

Spring Boot3,启动时间缩短 10 倍!

前面松哥写了一篇文章和大家聊了 Spring6 中引入的新玩意 AOT&#xff08;见Spring Boot3 新玩法&#xff0c;AOT 优化&#xff01;&#xff09;。 文章发出来之后&#xff0c;有小伙伴问松哥有没有做性能比较&#xff0c;老实说&#xff0c;这个给落下了&#xff0c;所以今天…

Linux的计划任务(crontab)环境变量问题解决

1、背景 新上了个python服务&#xff0c;里面有调用oracle&#xff0c;其中有个需求需要定时去调用&#xff0c;贪方便想用crontab&#xff0c;出现了环境变量问题&#xff0c;于是跟他杠上了&#xff0c;势必要解决它&#xff01; 2、现象 尽管我在计划任务里写全了脚本路径…

使用 KITTI数据集训练YOLOX

1. 现在KITTI集后&#xff0c;首先将数据集转换为COCO数据集格式。 kitti_vis.py import os from pathlib import Path import numpy as np import cv2def anno_vis(img, anno_list):for anno in anno_list:points np.array(anno[4:8], dtypenp.float32)cv2.rectangle(img, (…

疯狂的2023年已过,聊聊我对大模型微调技术几点实践思考

大家好&#xff0c;今天聊聊我对大模型微调技术几点实践看法&#xff0c;喜欢记得收藏、关注、点赞。 更多技术交流&#xff0c;资料&#xff0c;文末加入我们技术群获取。 为什么要对大模型进行微调&#xff08;Fine-tuning&#xff09; 与其说对 LLM 大模型进行微调&#xf…