网络编程——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 ...
随机推荐
- SQl 执行效率总结
SQL执行效率总结 1.关于SQL查询效率,100w数据,查询只要1秒,与您分享: 机器情况 p4: 2.4 内存: 1 G os: windows 2003 数据库: ms sql server 2 ...
- c# 通过URl 获取返回的json格式数据
方法一 http://blog.csdn.net/angle_greensky110/article/details/52209497 protected string GetJson(string ...
- jQuery轮播图--不使用插件
说明:引入jquery.min.js 将轮播图放入imgs文件夹 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...
- input控制输入保留一位小数
function zlip(obj){ obj.value = obj.value.replace(/[^\d.]/g,""); //清除“数字”和“.”以外的字符 obj.val ...
- jsp4
SESSION ID=B564A2D318ECDF70EB94C6DE2080E951 SESSION ID=B564A2D318ECDF70EB94C6DE2080E951 SESSION ID=B ...
- node.js的Promise库-bluebird示例
前两天公司一哥们写了一段node.js代码发给我,后面特意提了一句“写的不太优雅”.我知道,他意思是回调嵌套回调,因为当时比较急也就没有再纠结.然而内心中总记得要解决这个问题.解决node.js的回调 ...
- sqoop mysql导入hive 数值类型变成null的问题分析
问题描述:mysql通过sqoop导入到hive表中,发现有个别数据类型为int或tinyint的列导入后数据为null.设置各种行分隔符,列分隔符都没有效果. 问题分析:hive中单独将有问题的那几 ...
- V2019 Super DSP3 Odometer Correction Vehicle List
Comparing v2017 Super DSP3 mileage programmer, the newest V2019 Super DSP III adds newer vehicles, i ...
- Mad Libs游戏,华氏与摄氏转换
华氏温度 与 摄氏温度的相互转换 公式:摄氏 ℃=5/9(°F-32) 华氏°F= ℃×9/5+32 # -*- coding: UTF-8 -*- num=input('输入摄氏温度:') num ...
- MIUI通过xposed自动设置root权限
在小米手机上,每次安装一个自己的插件总需要打开安全中心进行root权限授权,非常的麻烦,总共需要电5次确认,每次需要等5秒 因为插件开发的需求,希望重启计算机时候判断是否已经root,未root则自动 ...