您的位置:首页 > 理论基础 > 计算机网络

用select实现1对多的网络通信,多线程实现,且可以实现退出,相互间对话消息不受干扰

2014-12-22 11:04 399 查看
/*用select实现多线程并行网络通信,1对多通信*/

#include <stdlib.h>  

#include <stdio.h>  

#include <errno.h>  

#include <string.h>

#include <netdb.h>  

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <pthread.h> 

#include <unistd.h> 

#include <semaphore.h>

#define portnumber 3333

#define MAXCLIENTNUM 5

static int totalNum = 0;

static sem_t sem; //信号量

 

void Process(void *arg)

{     

       printf("processstarting... Thread ID: %d\n", pthread_self());

       fd_set readfd;

       int nbytes;

       char buffer[1024];

       int fd = (int) arg;

       while(1)

              {

                     FD_ZERO(&readfd);

                     FD_SET(fd,&readfd);

                     FD_SET(0,&readfd);

                     int i,maxfd = fd + 1;

                     int r= select(maxfd, &readfd, NULL, NULL, NULL);

                     if(r>= 0)

                     {

                        //服务器接收消息

                        if(FD_ISSET(fd, &readfd))

                        {

                             sem_wait(&sem); //获取信号量

                             if((nbytes = read(fd, buffer, 1024)) == -1)


                             {

                                   fprintf(stderr,"ReadError:%s\n",strerror(errno));


                                   exit(1);

                             }

                             if(nbytes == 0)

                             {

                                   printf("client%d has exit!\n", maxfd);

                                   sem_post(&sem);  //一定要释放信号量

                                   break;

                             }

                            buffer[nbytes]='\0';

                            printf("client%d say: %s\n", maxfd, buffer);

                            sem_post(&sem);//释放信号量

                            sleep(1);

                            }

                            //服务器发送消息

                            if(FD_ISSET(0,&readfd)) //从服务器终端输入数据

                            {

                                   sem_wait(&sem);//获取信号量

                                   memset(buffer,0, sizeof(buffer));

                                   fgets(buffer,1024, stdin);


                                   if(strncmp(buffer,"quit", 4) == 0)

                                   {

                                          printf("areyou sure to quit: yes or no \n");

                                          memset(buffer, 0, sizeof(buffer));

                                          fgets(buffer,1024, stdin);

                                          if(strncmp(buffer,"yes", 3)== 0)

                                          {

                                                 write(fd, "server has quit",15);

                                                 sleep(3); //睡眠3秒,保证把要退出的信号告诉客户端

                                                 FD_CLR(fd,&readfd);

                                                 close(fd);

                                                 exit(0);

                                          }

                                          else

                                                 continue;

                                   }

                                   write(fd,buffer,strlen(buffer));

                                   sem_post(&sem);//释放信号量

                                   sleep(1);

                            }

                     }

                     else

                     {

                            printf("select error!\n");

                            exit(-1);

                     }

                     sleep(1);//实现一对多通信

              }

              FD_CLR(fd,&readfd);

              close(fd);

              pthread_exit(NULL);

              /* 循环下一个 */


}

 

int main(int argc, char *argv[])

{

       int sockfd,new_fd;

       struct sockaddr_inserver_addr;


       struct sockaddr_inclient_addr;


       int sin_size;

      

       /* 服务器端开始建立sockfd描述符 */


       if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

       {

              fprintf(stderr,"Socketerror:%s\n\a",strerror(errno));


              exit(1);

       }

       printf("Socketsuccess.....\n");

       /* 服务器端填充 sockaddr结构 */


       bzero(&server_addr,sizeof(structsockaddr_in)); //
初始化,置0


       server_addr.sin_family=AF_INET;                 // Internet

       server_addr.sin_addr.s_addr=htonl(INADDR_ANY);  // (将本机器上的long数据转化为网络上的long数据)和任何主机通信 
//INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP


       //server_addr.sin_addr.s_addr=inet_addr("192.168.1.1");  //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip

       server_addr.sin_port=htons(portnumber);         // (将本机器上的short数据转化为网络上的short数据)端口号

      

       /* 捆绑sockfd描述符到IP地址
*/


       printf("startbindding.....\n");

       if(bind(sockfd,(structsockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)


       {

              fprintf(stderr,"Binderror:%s\n\a",strerror(errno));


              exit(1);

       }

      

       /* 设置允许连接的最大客户端数 */


       printf("startlistening.....\n");

       printf("The maxnumber of client to allow to connect with server is:%d.....\n",MAXCLIENTNUM);

       if(listen(sockfd,MAXCLIENTNUM)==-1)


       {

              fprintf(stderr,"Listenerror:%s\n\a",strerror(errno));


              exit(1);

       }

      

       printf("serverworking.....\n");

       sem_init(&sem,0, 1); //初始化信号量

       while(1)

       {

                     sin_size=sizeof(structsockaddr_in);


                     if((new_fd=accept(sockfd,(structsockaddr *)(&client_addr),&sin_size))==-1)


                     {

                                   fprintf(stderr,"Accepterror:%s\n\a",strerror(errno));


                                   exit(1);

                     }

fprintf(stderr,"Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));//
将网络地址转换成.字符串


 

                     //创建工作者线程

                     pthread_tpwork;

                     interr = pthread_create(&pwork, NULL, (void*)Process, (void*)new_fd);

                     if(err!= 0)

                     {

                            printf("pthread_createerror!\n");

                            exit(0);

                     }

       }

      

       /* 结束通讯 */


       close(sockfd);

       exit(0);

}

 

/*客户端程序*/

#include<stdlib.h>  

#include<stdio.h>  

#include<errno.h>

#include<string.h>  

#include<netdb.h>  

#include<sys/types.h>

#include<netinet/in.h>  

#include<sys/socket.h>

#defineportnumber 3333

 

 

intmain(int argc, char *argv[])

{

       int sockfd;

       char buffer[1024];

       struct sockaddr_in server_addr;

       struct hostent *host;

 

    /* 使用hostname查询host 名字 */

       if(argc!=2)

       {

              fprintf(stderr,"Usage:%shostname \a\n",argv[0]);

              exit(1);

       }

 

       if((host=gethostbyname(argv[1]))==NULL)

       {

              fprintf(stderr,"Gethostnameerror\n");

              exit(1);

       }

 

       /* 客户程序开始建立sockfd描述符 */

       if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)//

       {

              fprintf(stderr,"SocketError:%s\a\n",strerror(errno));

              exit(1);

       }

 

       /* 客户程序填充服务端的资料*/

       bzero(&server_addr,sizeof(server_addr));// 初始化,置0

       server_addr.sin_family=AF_INET;          // IPV4

       server_addr.sin_port=htons(portnumber);  // (将本机器上的short数据转化为网络上的short数据)端口号

       server_addr.sin_addr=*((struct in_addr*)host->h_addr); // IP地址

      

       /* 客户程序发起连接请求*/

       if(connect(sockfd,(struct sockaddr*)(&server_addr),sizeof(struct sockaddr))==-1)


       {

              fprintf(stderr,"ConnectError:%s\a\n",strerror(errno));

              exit(1);

       }

 

       printf("Start totalking...\n");

      

 

       while(1)

              {

                     fd_set readfd;

                     FD_ZERO(&readfd);

                     FD_SET(sockfd,&readfd);

                     FD_SET(0,&readfd);  //把标准输入描述符加入描述符集

                     int maxfd = ((0 >sockfd) ? 0 : sockfd);

                     fd_set tmpfd = readfd;

                    

                     /* 发送数据 */

                     int r = select(maxfd + 1,&readfd, NULL, NULL, NULL);

                     if(r < 0)

                            {

                                   printf("selecterror!\n");

                                   exit(0);

                            }

                     else if(r == 0)

                            {

                                   printf("Waitingserver reply!\n");

                                   continue;

                            }

                     else

                            {

                                   //客户端输入数据

                                   if(FD_ISSET(0,&readfd))

                                          {

                                                 memset(buffer,0, sizeof(buffer));

                                                 fgets(buffer,1024, stdin);


                                                 if(strncmp(buffer,"quit", 4) == 0)

                                                        {

                                                               write(sockfd,"I will quit", 20);

                                                               printf("areyou sure to quit: yes or no \n");

                                                               memset(buffer,0, sizeof(buffer));

                                                               fgets(buffer,1024, stdin);

                                                               if(strncmp(buffer,"yes", 3)== 0)

                                                               {

                                                                      write(sockfd,"BYE BYE!^ ^", 15);

                                                                      sleep(3);

                                                                      FD_CLR(sockfd,&readfd);

                                                                      close(sockfd);

                                                                      exit(0);

                                                               }

                                                               else

                                                                      continue;

                                                        }     

                                                 /*连接成功了 */

                                                 write(sockfd,buffer,strlen(buffer));

                                          }

                                   //接收从服务器发来的数据

                                   if(FD_ISSET(sockfd,&readfd))

                                          {

                                                 intnbytes;

                                                 memset(buffer,0, sizeof(buffer));

                                                 if((nbytes= read(sockfd, buffer, 1024)) == -1)


                                                        {

                                                               fprintf(stderr,"ReadError:%s\n",strerror(errno));


                                                               exit(1);

                                                        }

                                                 if(nbytes== 0)

                                                        {

                                                               printf("serverhas exit!\n");

                                                               close(sockfd);

                                                               exit(0);

                                                        }

                                                 buffer[nbytes]='\0';

                                                 printf("serversay: %s\n", buffer);

                                          }

                            }

              }

       /* 结束通讯*/

       close(sockfd);

       exit(0);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息