点对点通信实例

  实现点对点通信,双方都能发送数据、接收数据,双方维护套接字。read对方数据和read键盘输入目前使用两个进程来实现。

 

  服务器进程

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/socket.h>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<netinet/in.h>
 9 #include<arpa/inet.h>
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)
17 void handler(int sig)
18 {
19     printf("recv a sig=%d\n",sig);
20     printf("ser child close");
21     exit(EXIT_SUCCESS);//退出子进程
22 
23 }
24 int main(void)
25 {
26     int listenfd;
27     if((listenfd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
28         ERR_EXIT("socket error");
29     //if((listenfd=socket(PF_INET,SOCK_STREAM,0))<0)
30     
31 
32     //本地协议地址赋给一个套接字
33     struct sockaddr_in servaddr;
34     memset(&servaddr,0,sizeof(servaddr));
35     servaddr.sin_family=AF_INET;
36     servaddr.sin_port=htons(5188);
37     servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//表示本机地址
38     //servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
39     //inet_aton("127.0.0.1",&servaddr.sin_addr);
40     
41     //开启地址重复使用,关闭服务器再打开不用等待TIME_WAIT
42     int on=1;
43     if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)
44         ERR_EXIT("setsockopt error");
45     //绑定本地套接字
46     if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
47         ERR_EXIT("bind error");
48     if(listen(listenfd,SOMAXCONN)<0)//设置监听套接字(被动套接字)
49         ERR_EXIT("listen error");
50     
51     struct sockaddr_in peeraddr;//对方套接字地址
52     socklen_t peerlen=sizeof(peeraddr);
53     int conn;//已连接套接字(主动套接字)
54     if((conn=accept(listenfd,(struct sockaddr*)&peeraddr,&peerlen))<0)
55         ERR_EXIT("accept error");
56     printf("IP=%s,port=%d\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port));
57     pid_t pid;
58     pid=fork();
59     if(pid==-1)
60         ERR_EXIT("fork");
61     if(pid==0)
62     {
63         signal(SIGUSR1,handler);
64         //子进程获取键盘输入,发送数据
65         char sendbuf[1024]={0};
66         while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL)
67         {
68             write(conn,sendbuf,strlen(sendbuf));
69             memset(sendbuf,0,sizeof(sendbuf));
70         }
71         //printf("child close\n");
72         exit(EXIT_SUCCESS);
73     }
74     else
75     {
76       //父进程获取对方数据
77         char recvbuf[1024];
78         while(1)
79         {
80             memset(recvbuf,0,sizeof(recvbuf));
81             int ret=read(conn,recvbuf,sizeof(recvbuf));
82             if(ret==-1)
83                 ERR_EXIT("read");
84             else if(ret==0)
85                 {
86                     printf("peer closed");
87                     break;
88                 }
89             fputs(recvbuf,stdout);
90         }
91         //printf("ser father close");
92         kill(pid,SIGUSR1);//通知子进程
93         exit(EXIT_SUCCESS);
94     }
95     return 0;
96 }

 

 

  客户端程序代码:

 

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/socket.h>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<netinet/in.h>
 9 #include<arpa/inet.h>
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)
17 void handler(int sig)
18 {
19     printf("recv a sig=%d\n",sig);
20     exit(EXIT_SUCCESS);
21 }
22 int main(void)
23 {
24     int sock;//客户端创建套接字
25     if((sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
26         ERR_EXIT("socket error");
27     
28     struct sockaddr_in servaddr;//本地协议地址赋给一个套接字
29     memset(&servaddr,0,sizeof(servaddr));
30     servaddr.sin_family=AF_INET;
31     servaddr.sin_port=htons(5188);
32     
33     servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器段地址
34     //inet_aton("127.0.0.1",&servaddr.sin_addr);
35     
36     if(connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
37         ERR_EXIT("connect");
38 
39 
40     pid_t pid;
41     pid=fork();
42     if(pid==-1)
43         ERR_EXIT("fork");
44     if(pid==0)
45     {
46         char recvbuf[1024];
47         //子进程接收对方数据,服务器端也能发送数据。
48         while(1)
49         {
50             memset(recvbuf,0,sizeof(recvbuf));
51             int ret=read(sock,recvbuf,sizeof(recvbuf));
52             if(ret==-1)
53                 ERR_EXIT("read");
54             else if(ret==0)
55                 {
56                     printf("peer closed\n");
57                     break;
58                 }
59             fputs(recvbuf,stdout);
60         }
61         close(sock);
62         //break跳出循环的话,说明服务端关闭了.那么给父进程发送信号通知父进程
63         //父进程是给对方发送数据的,对方关闭了,那么父进程收到信号后,退出进程,不再发送数据。
64         kill(getppid(),SIGUSR1);
65         exit(EXIT_SUCCESS);
66     }
67     else
68     {
69         signal(SIGUSR1,handler);//如果没有这个,父进程不会退出
70         //父进程发送数据
71         char sendbuf[1024]={0};
72         while(fgets(sendbuf,sizeof(sendbuf),stdin)!=NULL)//默认有换行符
73         {
74             write(sock,sendbuf,strlen(sendbuf));
75             memset(sendbuf,0,sizeof(sendbuf));
76         }
77         close(sock);
78         printf("cli father close\n");
79         exit(EXIT_SUCCESS);
80     }
81     return 0;
82 }

 

posted on 2018-02-03 19:14  wsw_seu  阅读(1335)  评论(0编辑  收藏  举报

导航