int select( int nfds, fd_set FAR* readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);

  nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1。在Windows中这个参数的值无所谓,可以设置不正确。
  readfds:(可选)指针,指向一组等待可读性检查的套接口。
  writefds:(可选)指针,指向一组等待可写性检查的套接口。
  exceptfds:(可选)指针,指向一组等待错误检查的套接口。
  timeout:select()最多等待时间,对阻塞操作则为NULL。
  如果对readfds、writefds或exceptfds中任一个组类不感兴趣,可将它置为空NULL。
在socket.h头文件中共定义了四个宏来操作描述字集。
  FD_ZERO(fd_set *fdset);将指定的文件描述符集清空,在对文件描述符集合进行设置前,必须对其进行初始化,如果不清空,由于在系统分配内存空间后,通常并不作清空处理,所以结果是不可知的。
     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复用的更多相关文章

  1. UNIX网络编程——I/O复用:select和poll函数

    我们看到TCP客户同时处理两个输入:标准输入和TCP套接字.我们遇到的问题是就在客户阻塞于(标准输入上)fgets调用,服务器进程会被杀死.服务器TCP虽然正确的给客户TCP发送了一个FIN,但是既然 ...

  2. 网络编程-I/O复用

    I/O模型 Unix下可用的I/O模型有五种: 阻塞式I/O 非阻塞式I/O I/O复用(select和poll.epoll) 信号驱动式I/O(SIGIO) 异步I/O(POSIX的aio_系列函数 ...

  3. 【Unix网络编程】chapter6IO复用

    chapter6  6.1 概述 I/O复用典型使用在下列网络应用场合. (1):当客户处理多个描述符时,必须使用IO复用 (2):一个客户同时处理多个套接字是可能的,不过不叫少见. (3):如果一个 ...

  4. socket网络编程-----I/O复用之poll函数

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/soc ...

  5. socket网络编程-----I/O复用之select函数

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/soc ...

  6. Linux网络编程——I/O复用之poll函数

    一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ...

  7. Linux网络编程-IO复用技术

    IO复用是Linux中的IO模型之一,IO复用就是进程预先告诉内核需要监视的IO条件,使得内核一旦发现进程指定的一个或多个IO条件就绪,就通过进程进程处理,从而不会在单个IO上阻塞了.Linux中,提 ...

  8. Linux网络编程——tcp并发服务器(poll实现)

    想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程——I/O复用之poll函数> 代码: #include <string.h> #include <st ...

  9. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

随机推荐

  1. ajax 常用功能 结构分解

    ajax 和后台交互基本结构 0.触发的事件. 1.获取参数 2.url 3.请求方法get/post 4.对返回结果的处理 .done如果有返加 .fail 失败 $(function () { / ...

  2. 牛客小白月赛13 小A的回文串(Manacher)

    链接:https://ac.nowcoder.com/acm/contest/549/B来源:牛客网 题目描述 小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的.所以小A只想知道给定的一个 ...

  3. python爬虫系列之初识爬虫

    前言 我们这里主要是利用requests模块和bs4模块进行简单的爬虫的讲解,让大家可以对爬虫有了初步的认识,我们通过爬几个简单网站,让大家循序渐进的掌握爬虫的基础知识,做网络爬虫还是需要基本的前端的 ...

  4. VBA XML信息提取

    Option Explicit Sub 读取XML节点() '后期绑定 'Dim xdoc As Object 'Set xdoc = CreateObject("MSXML2.DOMDoc ...

  5. [转]vue跨域解决方法

      vue跨域解决方法 vue项目中,前端与后台进行数据请求或者提交的时候,如果后台没有设置跨域,前端本地调试代码的时候就会报“No 'Access-Control-Allow-Origin' hea ...

  6. 爬虫利器 Puppeteer 实战

    Puppeteer 介绍 Puppeteer 翻译是操纵木偶的人,利用这个工具,我们能做一个操纵页面的人.Puppeteer是一个Nodejs的库,支持调用Chrome的API来操纵Web,相比较Se ...

  7. lombok的简单介绍

    ##lombok的使用 一直在使用lombok的set和get,对其他的功能用的比较少,蓦然发现这个库好用的功能不要太多啊 有必要深入理解一番. ###lombok安装 1 需要IDE支持,不然开发的 ...

  8. 深入理解JVM(七)JVM类加载机制

    7.1JVM类加载机制 虚拟机把数据从Class文件加载到内存,并且校验.转换解析和初始化最终形成可以被虚拟机使用的Java类型,这就是虚拟机的类加载机制. 7.2类加载的时机 1.类加载的步骤开始的 ...

  9. sqlserver全文检索

    转载地址:https://www.cnblogs.com/qianzf/p/7131741.html

  10. angular的json

    在angular从servlet中获取的list数据是字符串格式,需要转为json格式,于是使用语法: $scope.findOne=function(id){ typeTemplateService ...