网络编程——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 ...
随机推荐
- Linux-01
Linux各目录的作用 /bin/ 存放系统命令的目录,普通用户和超级用户都可以执行.不过放在/bin下的命令在单用户模式下也可以执行 /sbin/ 保存和系统环境设置相关的命令,只有超级用户可以使用 ...
- Golang学习---test写法和benchmark写法
一.Test 1. 每一个test文件须import一个testing 2. test文件下的每一个test case 均必须用Test开头并且符合TestXxxx形式,否则go test会直接跳过测 ...
- 十五、Collections.sort(<T>, new Comparator<T>() {})针对字符串排序
1.排序对象全是字母组成,可以根据ASCII编码表排序 package com.abcd; public class Person{ private String name; private int ...
- 微信小程序发送ajax
微信小程序通过 wx.request发送ajax请求 1. GET wx.request({ url: app.globalData.pubSiteUrl + 'user-information/ge ...
- RDMA RC UC UD
RC:面向连接的可靠服务 UC:面向连接的不可靠服务 UD:面向数据报的不可靠服务 RD:面向非连接(类似UDP)的可靠服务 面向连接 vs 面向数据报 相同点:两者的通信均包括双方QP对的参与 不同 ...
- linux wc使用详解
转载:https://www.cnblogs.com/peida/archive/2012/12/18/2822758.html Linux系统中的wc(Word Count)命令的功能为统计指定文件 ...
- 第一二次java实训作业
1. 声明一个整型变量a,并赋初值5,在程序中判断a是奇数还是偶数,然后输出判断的结果. package java1; public class java1 { static int a=5; pub ...
- mysql读写分离——中间件ProxySQL的简介与配置
mysql实现读写分离的方式 mysql 实现读写分离的方式有以下几种: 程序修改mysql操作,直接和数据库通信,简单快捷的读写分离和随机的方式实现的负载均衡,权限独立分配,需要开发人员协助. am ...
- 使用rar把程序打包成一个exe
根目录--全部文件--右键添加到压缩文件 常规--创建自解压压缩文件 高级--自解压选项 解压路径--Finger(自己写)--在"Program Files"中创建 设置--解压 ...
- Django模板标签
一.模板标签 1.模板标签是在模板中运用python语言的实现,如for循环,if语句 2.模板标签的运用 2.1在teacher模板下创建students_list模板, 在teacher视图中国创 ...