
服务器端:server.c
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <arpa/inet.h>6 #include <pthread.h>7 void* working(void *arg);8 //信息结构体9 struct sockinfo10 {11     struct sockaddr_in addr;//用来存储地址信息12     int fd;//用来存储文件描述符13 };14 //创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表15 //在C++中可以维护一个STL16 struct sockinfo infos[512];17 int main()18 {19     //创建监听的套接字20     int lfd=socket(AF_INET,SOCK_STREAM,0);21     if(lfd==-1)22     {23         perror("socket");24         return -1;25     }26     struct sockaddr_in addr;27     addr.sin_family=AF_INET;28     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序29     addr.sin_addr.s_addr=INADDR_ANY;30     int ret=bind(lfd,(struct sockaddr*)&addr,sizeof(addr));31     if(ret==-1)32     {33         perror("bind");34         return -1;35     }36     //设置监听37     ret=listen(lfd,128);//设置最大监听数量为128个38     if(ret==-1)39     {40         perror("listen");41         return -1;42     }4344     //初始化结构数组45     int max=sizeof(infos)/sizeof(infos[0]);//计算数组的大小46     //将结构体数组中每个元素初始化为047     int i=0;48     for(i=0;i<max;++i)49     {50         bzero(&infos[i],sizeof(infos[i]));51         //memset(infos,0,sizeof(infos));52         //将结构体中的文件描述符修改为-153         infos[i].fd=-1;//通过文件描述符的值是否为-1来判断当前数组元素是否是被占用的5455     }5657     //阻塞并等待客户端的连接58     int clilen=sizeof(struct sockaddr_in);59     while(1)60     {61         struct sockinfo* pinfo;62         int i=0;63         for(i=0;i<max;++i)64         {65             if(infos[i].fd==-1)//此时说明该元素是可以使用的66             {67                 pinfo=&infos[i];68                 break;69             }70         }71         int cfd=accept(lfd, (struct sockaddr*)&pinfo->addr,&clilen);72         pinfo->fd=cfd;//保存返回的文件描述符73         if(cfd==-1)74         {75             perror("accept");76             break;77         }78         //与客户端建立连接后,需要与客户端进行通信。与客户端的通信需要一个子线程来连接79         //创建子线程80         pthread_t tid;81         pthread_create(&tid,NULL,working,pinfo);//pinfo就是需要传递给working函数的参数82         //任务执行完毕之后,子线程需要退出。此时,需要由主线程来释放子线程的资源83         //此时,需要调用detach()函数来使主线程与子线程进行资源分离84         pthread_detach(tid);85     }86     close(lfd);87     return 0;88 }8990 //子线程的任务函数·91 void* working(void *arg)92 {93     struct sockinfo* pinfo=(struct sockinfo*)arg;94     //打印客户端地址95     char ip[1024]={0};96     printf("客户端IP地址:%s,端口:%d\n",inet_ntop(AF_INET,&pinfo->addr.sin_addr.s_addr,ip,sizeof(ip)),ntohs(pinfo->addr.sin_port));97     //和客户建立通信98     while(1)99     {
100         char buf[1024];
101         memset(buf,0,sizeof(buf));
102         int len=read(pinfo->fd,buf,sizeof(buf));
103         if(len>0)
104         {
105             printf("客户端say:%s\n",buf);
106             write(pinfo->fd,buf,len);
107         }
108         else if(len==0)
109         {
110             printf("客户端断开了连接...\n");
111             break;
112         }
113         else
114         {
115             perror("read");
116             break;
117         }
118     }
119     close(pinfo->fd);
120     pinfo->fd=-1;//将通信描述符再次初始化为-1
121     return NULL;
122 }客户端:client.c
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <string.h>5 #include <arpa/inet.h>6 int main()7 {8     //创建监听的套接字9     int fd=socket(AF_INET,SOCK_STREAM,0);10     if(fd==-1)11     {12         perror("socket");13         exit(0);14     }15     struct sockaddr_in addr;16     addr.sin_family=AF_INET;17     addr.sin_port=htons(999);  //主机字节序转换为网络字节序,即小端字节序转换成为大端字节序18     inet_pton(AF_INET,"192.168.64.134",&addr.sin_addr.s_addr);19     int ret=connect(fd,(struct sockaddr*)&addr,sizeof(addr));20     if(ret==-1)21     {22         perror("connetc");23         exit(0);24     }25     //和服务器通信26     int number=0;27     while(1)28     {   //发送数据29         char buf[1024];30         sprintf(buf,"你好,服务器...%d\n",number++);31         write(fd,buf,strlen(buf)+1);32         //接收数据33         memset(buf,0,sizeof(buf));34         int len=read(fd,buf,sizeof(buf));35         if(len>0)36         {37             printf("服务器say:%s\n",buf);38             write(fd,buf,len);39         }40         else if(len==0)41         {42             printf("服务器断开了连接...\n");43             break;44         }45         else46         {47             perror("read");48             break;49         }50         sleep(1);51     }52     close(fd);53     return 0;54 }编译:gcc server.c -lpthread -o server
gcc client.c -lpthread -o client
启动运行:
先运行服务器端./server,再运行客户端./client