1.2 UDP协议下客户端和服务器端实现通信/聊天
head.h
1 //UDP协议下客户端和服务器端实现通信/聊天 2 #include <stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<error.h> 6 #include<errno.h> 7 #include<sys/types.h> 8 #include<sys/socket.h> 9 #include<netinet/in.h> 10 #include<netinet/ip.h> 11 #include<arpa/inet.h> 12 #include<signal.h> 13 #define error_exit(_errmsg_) error(EXIT_FAILURE,errno,_errmsg_) 14 #define SER_PORT 50000 15 #define SER_ADDR "192.168.1.104"
Makefile
1 ALL:client server 2 client:client.c 3 gcc $< -o $@ 4 server:server.c 5 gcc $< -o $@ 6 7 clean: 8 rm client server
client.c
1 #include "head.h" 2 int main()//client 3 { 4 int sockfd=0; 5 char buff[1024]={0}; 6 struct sockaddr_in seraddr; 7 seraddr.sin_family=AF_INET; 8 seraddr.sin_port=htons(SER_PORT); 9 seraddr.sin_addr.s_addr=inet_addr(SER_ADDR); 10 //创建一个用来通信的文件描述符 11 if(-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0))) 12 error_exit("fail to socket!"); 13 //创建父子进程 14 pid_t pid,pid1; 15 if(-1==(pid=fork())) 16 error_exit("fail to fork!"); 17 if(pid==0)//子进程负责发送 18 { 19 //client(); 20 while(1) 21 { //从终端读取数据到buff/ fgets 读到字符串尾加'\0' 22 fgets(buff,sizeof(buff),stdin); 23 //sendto有绑定功能,绑定客户端自己的IP地址和端口号发送出去的。/必须先发送让服务器端接受识别 24 if(-1==sendto(sockfd,buff,strlen(buff)+1,0, 25 (struct sockaddr*)&seraddr,sizeof(seraddr))) 26 error_exit("fail to sendto!"); 27 if(!strncmp(buff,"quit",4))break;//发quit退出 28 } 29 pid1=getppid(); 30 } 31 else if(pid>0)//父进程负责接收 32 { 33 while(1) 34 { 35 //if(-1==recvfrom(sockfd,buff,sizeof(buff),0, 36 // (struct sockaddr *)&cltaddr,&addrlen)) 37 //收到服务器端回复,可以不显示对方IP地址 38 //多路复用IO解决TCP协议下并发性问题 39 if(-1==recvfrom(sockfd,buff,sizeof(buff),0,NULL,NULL)) 40 error_exit("fail to recvfrom!"); 41 //printf("%s:%d-->buff=%s\n",inet_ntoa(cltaddr.sin_addr), 42 // ntohs(cltaddr.sin_port),buff); 43 if(!strncmp(buff,"quit",4))break; 44 printf("RECV:%s",buff); 45 } 46 pid1=pid; 47 } 48 kill(pid1,SIGKILL);//杀死父子进程 49 close(sockfd);//关闭套接字文件描述符 50 return 0; 51 }
server.c
1 #include "head.h" 2 int main()//server 3 { 4 int sockfd=0; 5 char buff[1024]={0}; 6 struct sockaddr_in seraddr; 7 struct sockaddr_in cltaddr; 8 socklen_t addrlen=sizeof(cltaddr); 9 10 seraddr.sin_family=AF_INET; 11 seraddr.sin_port=htons(SER_PORT); 12 seraddr.sin_addr.s_addr=inet_addr(SER_ADDR); 13 //创建一个用来通信的文件描述符 14 if(-1==(sockfd=socket(AF_INET,SOCK_DGRAM,0))) 15 error_exit("fail to socket!"); 16 //绑定文件描述符和服务器(自身)IP地址 17 if(-1==bind(sockfd,(struct sockaddr*)&seraddr,sizeof(seraddr))) 18 error_exit("fail to bind!"); 19 //服务器第一次收到某客户端信息,可以确认其IP地址 20 if(-1==recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr*)&cltaddr,&addrlen)) 21 error_exit("fail to recvfrom!"); 22 if(!strncmp(buff,"quit",4))exit(EXIT_SUCCESS); 23 printf("RECV:%s",buff); 24 25 pid_t pid,pid1; 26 if(-1==(pid=fork())) 27 error_exit("fail to fork!"); 28 if(pid==0)//子进程负责发送 29 { 30 //client(); 31 while(1) 32 { 33 fgets(buff,sizeof(buff),stdin); 34 //服务器端回复客户端信息 35 if(-1==sendto(sockfd,buff,strlen(buff)+1,0, 36 (struct sockaddr*)&cltaddr,sizeof(cltaddr))) 37 error_exit("fail to sendto!"); 38 if(!strncmp(buff,"quit",4))break; 39 } 40 pid1=getppid(); 41 } 42 else if(pid>0)//父进程负责接收 43 { 44 while(1) 45 { 46 //if(-1==recvfrom(sockfd,buff,sizeof(buff),0, 47 // (struct sockaddr *)&cltaddr,&addrlen)) 48 //收到客户端信息,可以不显示对方IP地址 49 if(-1==recvfrom(sockfd,buff,sizeof(buff),0,NULL,NULL)) 50 error_exit("fail to recvfrom!"); 51 //printf("%s:%d-->buff=%s\n",inet_ntoa(cltaddr.sin_addr), 52 // ntohs(cltaddr.sin_port),buff); 53 if(!strncmp(buff,"quit",4))break; 54 printf("RECV:%s",buff); 55 } 56 pid1=pid; 57 } 58 kill(pid1,SIGKILL); 59 close(sockfd); 60 return 0; 61 }

浙公网安备 33010602011771号