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 }

posted @ 2017-03-13 20:16  bkycrmn  阅读(178)  评论(0)    收藏  举报