IO复用
Posted it8343
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IO复用相关的知识,希望对你有一定的参考价值。
客户端的代码和前面的一样,所以这里只给出服务器端的代码,根据代码进行理解:
1 #include "common.h" 2 3 struct cli_t 4 { 5 int cfd; 6 struct sockaddr_in caddr; 7 struct cli_t *next; 8 }; 9 10 11 typedef struct stu//学生结构体 12 { 13 int id; 14 char name[20]; 15 int score; 16 struct stu *next; 17 }Stu,*PStu; 18 19 20 21 void fun(int sig)//捕捉信号 22 { 23 printf("连接中断 "); 24 return; 25 } 26 27 28 unsigned int ListLength(PStu ptr) //计算链表长度 29 { 30 unsigned int l=0; 31 while(ptr!=NULL) 32 { 33 l++; 34 ptr=ptr->next; 35 } 36 return l; 37 } 38 39 PStu ListSort(PStu ptr) //链表排序 40 { 41 PStu sorthead=NULL; 42 unsigned int l=ListLength(ptr); 43 while(l>0) 44 { 45 PStu p1=ptr; 46 PStu p2=p1; 47 int max=p1->score; 48 while(p1!=NULL) 49 { 50 if(p1->score>max) 51 {max=p1->score; p2=p1;} 52 p1=p1->next; 53 } 54 PStu p3=ptr; 55 if (p3==p2) 56 ptr=p3->next; 57 else 58 { while(p3->next!=p2) 59 p3=p3->next; 60 61 p3->next=p2->next; 62 } 63 64 PStu r; 65 p2->next=NULL; 66 if(sorthead==NULL) 67 sorthead=p2; 68 else 69 r->next=p2; 70 71 r=p2; 72 l--; 73 } 74 return sorthead; 75 } 76 77 void show(PStu head)//打印链表函数 78 { 79 printf("学号 姓名 分数 "); 80 while(head!=NULL) 81 { 82 printf("%d %s %d ",head->id,head->name,head->score); 83 head=head->next; 84 } 85 return ; 86 } 87 88 int read_file(int agv)//接受信息(子线程) 89 { 90 PStu head=NULL; 91 Stu *ptr; 92 PStu r; 93 int nfd; 94 int ret; 95 nfd=(int)agv;//接收传参nfd 96 97 signal(SIGPIPE,fun); 98 printf("read... "); 99 while(1) 100 { 101 ptr=malloc(sizeof(Stu)); 102 ret=read(nfd,ptr,sizeof(Stu)); 103 if(ret<0) 104 { 105 perror("read");return -1; 106 } 107 if(ret==0) 108 { 109 head=ListSort(head); 110 show(head); 111 printf("read over "); 112 return 0; 113 } 114 if(ret>0);//把链表读出来 115 { 116 ptr->next=NULL; 117 if(head==NULL) 118 { 119 head=ptr; 120 } 121 else 122 { 123 r->next=ptr; 124 } 125 r=ptr; 126 } 127 } 128 return 1; 129 } 130 131 int main()//主线程,一直工作,接收客户端 132 { 133 PStu head=NULL; 134 pthread_t pthid; 135 int ret; 136 int fd,nfd; 137 struct sockaddr_in saddr,caddr; 138 int addr_len; 139 signal(SIGPIPE,fun); 140 fd = socket(AF_INET,SOCK_STREAM,0); 141 if(fd<0) 142 { 143 perror("socket"); 144 return -1; 145 } 146 saddr.sin_family = AF_INET; 147 saddr.sin_port = htons(9000); 148 inet_pton(AF_INET,"192.168.73.136",&saddr.sin_addr.s_addr); 149 ret = bind(fd,(struct sockaddr*)&saddr,sizeof(saddr)); 150 if(ret<0) 151 { 152 perror("bind"); 153 goto END; 154 } 155 ret = listen(fd,20); 156 if(ret<0) 157 { 158 perror("listen"); 159 goto END; 160 } 161 162 163 fd_set set,rset; 164 int *pfd; 165 struct cli_t *chead=NULL; 166 struct cli_t *pcli; 167 int maxfd; 168 169 170 FD_ZERO(&set);//将文件描述符集清空 171 FD_SET(fd,&set);//在文件描述符集合中增加一个新的文件描述符 172 maxfd=fd; 173 174 175 while(1)//循环接收多个客户端 176 { 177 rset=set; 178 printf("select... "); 179 ret=select(maxfd+1,&rset,NULL,NULL,NULL); 180 printf("select over && ret= %d ",ret); 181 182 if(ret<0) 183 { 184 perror("select"); 185 break; 186 } 187 if(FD_ISSET(fd,&rset))//检查fd是否在文件描述符集中, select将更新这个集合,只保留符合条件的套节字在这个集合里面 188 { 189 //接收连接 190 addr_len = sizeof(caddr); 191 printf("accept.. "); 192 nfd = accept(fd,(struct sockaddr*)&caddr,&addr_len);printf("nfd=%d ",nfd); 193 if(nfd<0) 194 { 195 perror("accept"); 196 } 197 printf("accept over.. "); 198 //加入集合 199 FD_SET(nfd,&set); 200 if(nfd>maxfd) 201 maxfd=nfd; 202 203 // 加入链表 204 pcli=malloc(sizeof(struct cli_t)); 205 pcli->cfd=nfd; 206 pcli->caddr=caddr; 207 pcli->next=chead; 208 chead=pcli; 209 } 210 for(pcli=chead;pcli!=NULL;pcli=pcli->next) 211 { 212 int tfd=pcli->cfd; 213 if(!FD_ISSET(tfd,&rset)) 214 continue; 215 ret=read_file(tfd); 216 if(ret<=0) 217 { 218 printf("read ret =0 tcp broken "); 219 FD_CLR(tfd,&set); 220 } 221 else 222 { 223 continue; 224 } 225 } 226 } 227 END: 228 close(fd); 229 return 0; 230 }
以上是关于IO复用的主要内容,如果未能解决你的问题,请参考以下文章
java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段