• 点对点通信实例


      实现点对点通信,双方都能发送数据、接收数据,双方维护套接字。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
    ",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
    ",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
    ");
    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
    ",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
    ");
    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
    ");
    79         exit(EXIT_SUCCESS);
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    java 并发性和多线程 -- 读感 (一 线程的基本概念部分)
    [翻译]Spring框架参考文档(V4.3.3)-第二章Spring框架介绍 2.1 2.2 翻译--2.3待继续
    java 内存模型
    控制反转容器& 依赖注入模式 ---读感。
    go json null字段的转换
    分布式数据库----数据同步
    java 多线程--- Thread Runnable Executors
    go runtime.Gosched() 和 time.Sleep() 做协程切换
    sql 里面 join in 的差别,join的用法
    定时器
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/8410488.html
Copyright © 2020-2023  润新知