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. ES查询-match VS match_phrase

    我们以一个查询的示例开始,我们在student这个type中存储了一些学生的基本信息,我们分别使用match和match_phrase进行查询. 首先,使用match进行检索,关键字是“He is”: ...

  2. windows批量停止服务

    此代码适合有一定windows操作系统基础的人使用 @echo off for %%i in ( mysql OracleDBConsoleleak OracleMTSRecoveryService ...

  3. git安装包解压后没有configure

    今天在linux上安装git客户端,解压了tar包后,发现没有configure,无法安装.经查,原来是要先执行autoconf命令,执行后出现configure

  4. jmeter导入DB数据再优化

    由于同一个迭代中每天都在执行.之前设计的思路是同个迭代只执行一次插入DB操作!! 因而没有在插入数据前没有做版本.产品类型.页面类型.接口名.接口名是否相等判断操作. 因此,若是这些条件相等,数据不是 ...

  5. 递归,re,time,random

    递归函数 1.在函数中调用自己 2.超过递归的最大深度报错,递归的最大深度:998大概 3.递归的缺点:占内存 4.优点:代码简单 import sys sys.setrecursionlimit(2 ...

  6. jquery操作select下拉框的多种方法(选中,取值,赋值等)

    Query获取Select选择的Text和Value: 语法解释: 1. $("#select_id").change(function(){//code...}); //为Sel ...

  7. Python之路(第三十二篇) 网络编程:udp套接字、简单文件传输

    一.UDP套接字 服务端 # udp是无链接的,先启动哪一端都不会报错 # udp没有链接,与tcp相比没有链接循环,只有通讯循环 server = socket.socket(socket.AF_I ...

  8. 服务管理之openssh

    1. 使用 SSH 访问远程命令行 1.1 OpenSSH 简介 OpenSSH这一术语指系统中使用的Secure Shell软件的软件实施.用于在远程系统上安全运行shell.如果您在可提供ssh服 ...

  9. python 常忘代码查询 和autohotkey补括号脚本和一些笔记和面试常见问题

    笔试一些注意点: --,23点43 今天做的京东笔试题目: 编程题目一定要先写变量取None的情况.今天就是因为没有写这个边界条件所以程序一直不对.以后要注意!!!!!!!!!!!!!!!!!!!!! ...

  10. 在anguler项目中引用fullCalendar

    1.css文件引用 <link href="/CSS/Fullcalendar.css" rel="stylesheet" /> <!--插件 ...