4/12作业

select服务器与客户端

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include
 10 #include
 11 
 12 #define ERR_MSG(msg) do{\
 13     fprintf(stderr,"line:%d ",__LINE__);\
 14     perror(msg);\
 15 }while(0);
 16 
 17 #define IP "192.168.2.145"      //本机IP
 18 #define PORT 6767       //端口号1024~49151
 19 
 20 int main(int argc, const char *argv[])
 21 {
 22     //创建流式套接字
 23     int sfd = socket(AF_INET,SOCK_STREAM,0);
 24     if(sfd < 0)
 25     {
 26         ERR_MSG("socket");
 27         return -1;
 28     }
 29 
 30     //允许端口快速重用
 31     int reuse = 1;
 32     if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
 33     {
 34         ERR_MSG("setsockopt");
 35         return -1;
 36     }
 37     printf("允许端口快速重用成功\n");
 38 
 39 
 40 
 41     //填充地址信息结构体
 42     struct sockaddr_in sin;
 43     sin.sin_family      = AF_INET;       //必须填AF_INET
 44     sin.sin_port        = htons(PORT);   //端口号
 45     sin.sin_addr.s_addr = inet_addr(IP); //本机IP
 46 
 47     //将IP和端口绑定到套接字上
 48     if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
 49     {
 50         ERR_MSG("bind");
 51         return -1;
 52     }
 53     printf("bind success __%d__\n",__LINE__);
 54 
 55     //将套接字设置为被动监听状态,监听是否有客户端连接成功;
 56     if(listen(sfd,128) < 0)
 57     {
 58         ERR_MSG("listen");
 59         return -1;
 60     }
 61     printf("listen sucess __%d__\n",__LINE__);
 62 
 63 
 64     struct sockaddr_in cin;//存储连接成功的客户端地址信息
 65     struct sockaddr_in home_cin[1024-4];//存储连接成功的客户端地址信息
 66     socklen_t addrlen = sizeof(cin);
 67 
 68     //阻塞函数,从已完成连接的队列头中获取一个客户端信息,生成一个新的文件描述符
 69     //该文件描述符才是与客户端通信的文件描述符
 70 
 71 
 72 
 73     //设置一个读集合
 74     fd_set readfds,tmpfds;
 75     FD_ZERO(&readfds);
 76     FD_ZERO(&tmpfds);
 77 
 78     //将需要的文件描述符添加到集合中
 79     FD_SET(0,&readfds);
 80     FD_SET(sfd,&readfds);
 81 
 82     int maxfd = sfd;
 83 
 84     int s_res = 0;
 85     char buf[128] = "";
 86     ssize_t res = 0;
 87     int newfd = -1;
 88     while(1)
 89     {
 90         tmpfds = readfds;
 91         s_res = select(maxfd+1,&tmpfds,NULL,NULL,NULL);
 92         if(s_res < 0)
 93         {
 94             ERR_MSG("select");
 95             return -1;
 96         }
 97 
 98         else if(0 == s_res)
 99         {
100             printf("time out...\n");
101             return -1;
102         }
103 
104         //能运行到当前位置,则代表有文件描述符准备就绪
105         //走触发事件的文件描述符对应的处理函数
106 
107         //当集合中有文件描述符准备就绪了,集合中只保留产生事件的文件描述符
108         //当0准备就绪,集合中会只保留0
109         //当sfd准备就绪,集合中会只保留sfd
110         //当0和sfd都准备就绪,,集合中会保留0和sfd
111         //所以只需要判断集合中剩下哪个文件描述符,走对于函数即可
112 
113         for( int i = 0;i<=maxfd;i++)
114         {
115             if(!FD_ISSET(i,&tmpfds))  //如果不在集合中,则直接往后继续变量
116             {
117                 continue;
118             }
119 
120 
121             //能运行到当前位置,则说明i所代表的文件描述符在tmpfds中
122             //要判断i所代表的文件描述符需要走什么对应的函数
123             if(0 == i)
124             {
125                 printf("触发键盘输入事件>>>");
126                 scanf("%s",buf);
127                 while(getchar() != 10);
128                 printf(":%s\n",buf);
129 
130             }
131                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
132             else if(sfd == i)
133             {
134                 printf("触发客户端连接事件>>>");
135                 fflush(stdout);
136                 newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
137                 if(newfd < 0)
138                 {
139                     ERR_MSG("accept");
140                     return -1;
141                 }
142                 home_cin[newfd-4]=cin;
143                 printf("[%s:%d] newfd = %d 连接成功__%d__\n",inet_ntoa(cin.sin_addr),ntohs(home_cin[i-4].sin_port),newfd,__LINE__);
144 
145                 //将newfd添加到读集合中
146                 FD_SET(newfd,&readfds);
147                 //更新maxfd
148                 maxfd = maxfd>newfd?maxfd:newfd;
149             }
150 
151             else
152             {
153                 bzero(buf,sizeof(buf));
154                 //接收
155                 res  = recv(i,buf,sizeof(buf),0);
156                 if(res < 0)
157                 {
158                     ERR_MSG("recv");
159                     return -1;
160                 }
161                 else if(0 == res)
162                 {
163                     printf("[%s:%d] newfd=%d 客户端下线 __%d__\n",inet_ntoa(cin.sin_addr),ntohs(home_cin[i-4].sin_port),newfd,__LINE__);
164                     //关闭文件描述符
165                     close(i);
166                     //从集合中提出该文件描述符
167                     FD_CLR(i,&readfds);
168 
169                     //更新maxfd,
170                     //从目前最大的文件描述符往小的判断,直到判断在集合中
171                     //那么该文件描述符就是最大的
172                     int j = 0;
173                     for(j=maxfd;j>=0;j--)
174                     {
175                         if(FD_ISSET(j,&readfds))
176                         {
177                             maxfd=j ;
178                             break;
179                         }
180                     }
181                     if(j < 0)
182                         maxfd = -1;
183 
184                     continue;
185 
186                 }
187                 strcat(buf,"*.*");
188                 send(i,buf,sizeof(buf),MSG_DONTWAIT);
189                 printf("[%s:%d] newfd = %d:%s\n",inet_ntoa(cin.sin_addr),ntohs(home_cin[i-4].sin_port),i,buf);
190             }
191         }
192 
193 
194     }
195 
196 
197 
198 
199 /*
200 
201 
202 
203         //发送
204         strcat(buf,"*_*");
205         if(send(newfd,buf,sizeof(buf),0) < 0)
206         {
207             ERR_MSG("send");
208             return -1;
209         }
210         printf("发送成功\n");
211 */
212 
213     return 0;
214 }
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
~                                                                                                                                                                            
  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include
 10 #include
 11 
 12 
 13 #define ERR_MSG(msg) do{\
 14     fprintf(stderr,"line:%d ",__LINE__);\
 15     perror(msg);\
 16 }while(0);
 17 
 18 #define IP "192.168.2.145"      //服务器IP
 19 #define PORT 6767       //端口号1024~49151
 20 
 21 int main(int argc, const char *argv[])
 22 {
 23     //创建流式套接字
 24     int cfd = socket(AF_INET,SOCK_STREAM,0);
 25     if(cfd < 0)
 26     {
 27         ERR_MSG("socket");
 28         return -1;
 29     }
 30 
 31 
 32     //绑定客户端的地址信息结构体,非必须绑定的
 33     //如果不绑定,则由操作系统自动选择一个端口号,以及本机可用IP绑定到套接字上
 34     //将IP和端口绑定到套接字上
 35     /*
 36     if(bind(cfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
 37     {
 38         ERR_MSG("bind");
 39         return -1;
 40     }
 41     printf("bind success __%d__\n",__LINE__);
 42     */
 43     //填充服务器地址信息结构体
 44     struct sockaddr_in sin;
 45     sin.sin_family      = AF_INET;       //必须填AF_INET
 46     sin.sin_port        = htons(PORT);   //端口号
 47     sin.sin_addr.s_addr = inet_addr(IP); //本机IP
 48 
 49     //连接服务器
 50     if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin)) < 0)
 51     {
 52         ERR_MSG("connect");
 53         return -1;
 54     }
 55     printf("connect sucess __%d__\n",__LINE__);
 56 
 57     char buf[128] = "";
 58     ssize_t res = 0;
 59     while(1)
 60     {
 61         //发送
 62         bzero(buf,sizeof(buf));
 63         fscanf(stdin,"%s",buf);
 64         buf[strlen(buf)] = 0;
 65         if(send(cfd,buf,sizeof(buf),0) < 0)
 66         {
 67             ERR_MSG("send");
 68             return -1;
 69         }
 70         printf("发送成功\n");
 71 
 72         //终端输入quit后退出程序
 73         if(strcasecmp(buf,"quit") == 0)
 74             break;
 75 
 76         //接收
 77         bzero(buf,sizeof(buf));
 78         res  = recv(cfd,buf,sizeof(buf),0);
 79         if(res < 0)
 80         {
 81             ERR_MSG("recv");
 82             return -1;
 83         }
 84         else if(0 == res)
 85         {
 86             printf("cfd = %d服务器下线 __%d__\n",cfd,__LINE__);                                                                                                                                                                                                                                               
 87             break;
 88         }
 89         printf("cfd = %d:%s\n",cfd,buf);
 90 
 91 
 92     }
 93 
 94 
 95 
 96     close(cfd);
 97 
 98 
 99     return 0;
100 }

你可能感兴趣的:(网络,服务器,linux)