网络编程——I/O复用
int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);
FD_SET(fd_set *fdset);用于在文件描述符集合中增加一个新的文件描述符。
FD_CLR(fd_set *fdset);用于在文件描述符集合中删除一个文件描述符。
FD_ISSET(int fd,fd_set *fdset);用于测试指定的文件描述符是否在该集合中。
#include "common.h" struct cli_t
{
int cfd;
struct sockaddr_in caddr;
struct cli_t *next;
}; typedef struct stu//学生结构体
{
int id;
char name[];
int score;
struct stu *next;
}Stu,*PStu; void fun(int sig)//捕捉信号
{
printf("连接中断\n");
return;
} unsigned int ListLength(PStu ptr) //计算链表长度
{
unsigned int l=;
while(ptr!=NULL)
{
l++;
ptr=ptr->next;
}
return l;
} PStu ListSort(PStu ptr) //链表排序
{
PStu sorthead=NULL;
unsigned int l=ListLength(ptr);
while(l>)
{
PStu p1=ptr;
PStu p2=p1;
int max=p1->score;
while(p1!=NULL)
{
if(p1->score>max)
{max=p1->score; p2=p1;}
p1=p1->next;
}
PStu p3=ptr;
if (p3==p2)
ptr=p3->next;
else
{ while(p3->next!=p2)
p3=p3->next; p3->next=p2->next;
} PStu r;
p2->next=NULL;
if(sorthead==NULL)
sorthead=p2;
else
r->next=p2; r=p2;
l--;
}
return sorthead;
} void show(PStu head)//打印链表函数
{
printf("学号\t姓名\t分数\n");
while(head!=NULL)
{
printf("%d\t%s\t%d\n",head->id,head->name,head->score);
head=head->next;
}
return ;
} int read_file(int agv)//接受信息(子线程)
{
PStu head=NULL;
Stu *ptr;
PStu r;
int nfd;
int ret;
nfd=(int)agv;//接收传参nfd signal(SIGPIPE,fun);
printf("read...\n");
while()
{
ptr=malloc(sizeof(Stu));
ret=read(nfd,ptr,sizeof(Stu));
if(ret<)
{
perror("read");return -;
}
if(ret==)
{
head=ListSort(head);
show(head);
printf("read over\n");
return ;
}
if(ret>);//把链表读出来
{
ptr->next=NULL;
if(head==NULL)
{
head=ptr;
}
else
{
r->next=ptr;
}
r=ptr;
}
}
return ;
} int main()//主线程,一直工作,接收客户端
{
PStu head=NULL;
pthread_t pthid;
int ret;
int fd,nfd;
struct sockaddr_in saddr,caddr;
int addr_len;
signal(SIGPIPE,fun);
fd = socket(AF_INET,SOCK_STREAM,);
if(fd<)
{
perror("socket");
return -;
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons();
inet_pton(AF_INET,"192.168.6.128",&saddr.sin_addr.s_addr);
ret = bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));
if(ret<)
{
perror("bind");
goto END;
}
ret = listen(fd,);
if(ret<)
{
perror("listen");
goto END;
} fd_set set,rset;//创建文件描述符集合
int *pfd;
struct cli_t *chead=NULL;
struct cli_t *pcli;
int maxfd; FD_ZERO(&set);//将文件描述符集清空
FD_SET(fd,&set);//在文件描述符集合中增加一个新的文件描述符
maxfd=fd; while()//循环接收多个客户端
{
rset=set;//把set的文件描述符拷贝给reset,防止set发生改变
printf("select...\n");
ret=select(maxfd+,&rset,NULL,NULL,NULL);//对读进行操作等待(无限等待)
printf("select over && ret= %d\n",ret); if(ret<)
{
perror("select");
break;
}
if(FD_ISSET(fd,&rset))//检查fd是否在文件描述符集中, select将更新这个集合,只保留符合条件的套节字在这个集合里面
{
//接收连接
addr_len = sizeof(caddr);
printf("accept..\n");
nfd = accept(fd,(struct sockaddr*)&caddr,&addr_len);
if(nfd<)
{
perror("accept");
}
printf("accept over..\n");
//加入集合
FD_SET(nfd,&set);//把nfd加入到set集合中
if(nfd>maxfd)
maxfd=nfd; // 加入链表
pcli=malloc(sizeof(struct cli_t));
pcli->cfd=nfd;
pcli->caddr=caddr;
pcli->next=chead;
chead=pcli;
}
for(pcli=chead;pcli!=NULL;pcli=pcli->next)//循环遍历,哪个客户端准备好了(写入并传输了数据就读出数据)
{
int tfd=pcli->cfd;
if(!FD_ISSET(tfd,&rset))//防止客户端没写入数据时阻塞在read里面
continue;
ret=read_file(tfd);
if(ret<=)
{
printf("read ret =0 tcp broken\n");
FD_CLR(tfd,&set);//客户端读取完毕且关闭,清空集合
}
}printf("asd");
}
END:
close(fd);
return ;
}
网络编程——I/O复用的更多相关文章
- UNIX网络编程——I/O复用:select和poll函数
我们看到TCP客户同时处理两个输入:标准输入和TCP套接字.我们遇到的问题是就在客户阻塞于(标准输入上)fgets调用,服务器进程会被杀死.服务器TCP虽然正确的给客户TCP发送了一个FIN,但是既然 ...
- 网络编程-I/O复用
I/O模型 Unix下可用的I/O模型有五种: 阻塞式I/O 非阻塞式I/O I/O复用(select和poll.epoll) 信号驱动式I/O(SIGIO) 异步I/O(POSIX的aio_系列函数 ...
- 【Unix网络编程】chapter6IO复用
chapter6 6.1 概述 I/O复用典型使用在下列网络应用场合. (1):当客户处理多个描述符时,必须使用IO复用 (2):一个客户同时处理多个套接字是可能的,不过不叫少见. (3):如果一个 ...
- socket网络编程-----I/O复用之poll函数
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/soc ...
- socket网络编程-----I/O复用之select函数
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/soc ...
- Linux网络编程——I/O复用之poll函数
一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...
- Linux网络编程-IO复用技术
IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...
- Linux网络编程——tcp并发服务器(poll实现)
想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程——I/O复用之poll函数> 代码: #include <string.h> #include <st ...
- 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数
本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...
随机推荐
- ACM学习之路
2018-10-18 11:03:00 今天开始踏上实现梦想的道路,希望自己不要懈怠. 坚持做简单的事,坚持下来就会变得不简单.
- MySQL索引原理以及查询优化
转载自:https://www.cnblogs.com/bypp/p/7755307.html MySQL索引原理以及查询优化 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且 ...
- Redis分布式缓存
Redis 主 slave 数据库优化-- 加inex, 分区 JVM调优--参数设置,比如偏向于计算的如何设置? 线程池:queue放满了之后,有什么方式能让他不拒绝掉?blockqueue就等在那 ...
- 获取txt md5值上传文件完整性校验
网络上传文件到服务器 做md5 校对.判断文件是否破坏 首先求txt文件的md5值 ,1万条数据 求出的值 文件MD5:e5467b6a8e3c26af8c5af0bda3739280 服务器处理程序 ...
- VMware NAT做端口映射
转自百度 原文地址: https://jingyan.baidu.com/article/c35dbcb0d1ff248916fcbc0d.html 注意事项:Window宿主电脑要调整防火墙.
- hdfs数据采集场景示意图
- Python学习:经典编程例题
九九乘法表 ,): ,i+): print(i,'*',j,'=',i*j,end='\t') print() 水仙花数问题描述:100-999之间每个数的立方相加等于原数例如:153=1 ^ 3 + ...
- C语言错题集
1.输入两个int型数a.b,求a/b的商c,不必考虑b为0的情况,输出c(保留两位小数) include<stdio.h> int main() { int a,b; float c; ...
- C#写入Oracle 中文乱码问题
这个问题是我刚踏入工作觉得最坑的一个问题,找了很多方法.也问过不少人,但还是没能解决,偶然间返现了新大陆.... 具体问题描述是这样的: 我可以读取Oracle数据库中已有的中文内容,并能正确显示(O ...
- 记录mysql安装过程遇到问题
1. 远程连接授权 登陆mysql数据库 (如果安装在系统盘可以直接命令, 否则要切换到安装目录..bin/) mysql -u root -p mysql> use mysql; - ...