服务器端: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