I\O复用

客户端的代码和前面的一样,所以这里只给出服务器端的代码,根据代码进行理解:

  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("连接中断\n");
 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("学号\t姓名\t分数\n");
 80     while(head!=NULL)
 81     {
 82         printf("%d\t%s\t%d\n",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...\n");
 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\n");
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...\n");
179         ret=select(maxfd+1,&rset,NULL,NULL,NULL);
180         printf("select over && ret= %d\n",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..\n");
192             nfd = accept(fd,(struct sockaddr*)&caddr,&addr_len);printf("nfd=%d\n",nfd);
193             if(nfd<0)
194             {
195                 perror("accept");
196             }
197             printf("accept over..\n");
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\n");
219                 FD_CLR(tfd,&set);
220             }
221             else
222             {
223                 continue;
224             }
225         }
226     }
227 END:
228     close(fd);
229     return 0;
230 }

猜你喜欢

转载自www.cnblogs.com/it8343/p/9275974.html