
服务器端: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 sockinfo
 10 {
 11     struct sockaddr_in addr;//用来存储地址信息
 12     int fd;//用来存储文件描述符
 13 };
 14 //创建一个信息数组,即同时支持与512个客户端进行通信,若想让其无上限,需要维护一个链表
 15 //在C++中可以维护一个STL
 16 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     }
 43
 44     //初始化结构数组
 45     int max=sizeof(infos)/sizeof(infos[0]);//计算数组的大小
 46     //将结构体数组中每个元素初始化为0
 47     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         //将结构体中的文件描述符修改为-1
 53         infos[i].fd=-1;//通过文件描述符的值是否为-1来判断当前数组元素是否是被占用的
 54
 55     }
 56
 57     //阻塞并等待客户端的连接
 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 }
 89
 90 //子线程的任务函数·
 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         else
 46         {
 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







![洛谷 P1216 [USACO1.5] [IOI1994]数字三角形题解](https://img-blog.csdnimg.cn/6744dd4a7e5a4921b44b637a4122c13f.png)










