• 《UNIX网络编程》之点对点通信


    思路:

    点对点通信,其原理也比较简单,在前面回显服务器的基础上,我们分别在服务端和客户端都使用两个线程,一个线程负责发送数据包,一个线程负责接收数据包。

    代码如下:

    客户端:

    /*************************************************************************
        > File Name: p2pcli.c
        > Author: ma6174
        > Mail: ma6174@163.com 
        > Created Time: Sun 05 Oct 2014 09:26:40 PM HKT
     ************************************************************************/
    
    #include<stdio.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    
    
    #define ERR_EXIT(m) 
            do 
            { 
                perror(m); 
                exit(EXIT_FAILURE); 
            }while(0)
    
    void handler(int sig)
    {
        printf("recv a sigal sig = %d
    ", sig);
        printf("parent exit
    ");
        exit(0);
    }
    
    
    
    
    int main(int argc, char **argv)
    {
        int sockfd;
        struct sockaddr_in servaddr;
    
        if(argc != 2)
        {
            //printf("usage: p2pcli <IPaddress> ");
            //exit(0);
            ERR_EXIT("usage: p2pcli <IPaddress> ");
        }
    
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(5188);
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
        if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        {
            ERR_EXIT("connect");
        }
    
        pid_t pid;
        pid = fork();
        if(pid == -1)
        {
            ERR_EXIT("fork");
        }
        else if(pid == 0)
        {
            //child
            char recvbuf[1024] = {0};
            while(1)
            {
                memset(recvbuf, 0, sizeof(recvbuf));
                int ret = read(sockfd, recvbuf, sizeof(recvbuf));
                if(ret == -1)
                {
                    ERR_EXIT("read");
                    break;
                }
                else if(ret == 0)
                {
                    printf("peer client close.
    ");
                    break;
                }
                else
                {
                    fputs(recvbuf, stdout);
                }
            }
            printf("child thread exit
    ");
            kill(getppid(), SIGUSR1);        
            exit(EXIT_SUCCESS);
    
        }
        else
        {
            signal(SIGUSR1, handler);
            char sendbuf[1024] = {0};
            while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
            {
                //send to server.
                write(sockfd, sendbuf, strlen(sendbuf));
                memset(sendbuf, 0, sizeof(sendbuf));
            }
            exit(EXIT_SUCCESS);
        }
        //communication
        return 0;
    }

    服务端:

    /*************************************************************************
        > File Name: p2psrv.c
        > Author: ma6174
        > Mail: ma6174@163.com 
        > Created Time: Sun 05 Oct 2014 08:27:06 PM HKT
     ************************************************************************/
    
    #include<stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <unistd.h>
    #include <signal.h>
    
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <string.h>
    #include <arpa/inet.h>
    
    #define ERR_EXIT(m)
            do
            {
                perror(m);
                exit(EXIT_FAILURE);
            }while(0)
    /**
     *child thread signal exit function
     **/
    void handler(int sig)
    {
        printf("recv a signal sig=%d
    ", sig);
        printf("child exit
    ");
        exit(EXIT_SUCCESS);
    }
    
    
    int main()
    {
        int listenfd;
        if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        {
            ERR_EXIT("socket");
        }
    
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(5188);
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        //reuse address
        int on = 1;
        if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
        {
            ERR_EXIT("setsockopt");
        }
    
        if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        {
            ERR_EXIT("bind");
        }
    
        if(listen(listenfd, SOMAXCONN) < 0)
        {
            ERR_EXIT("listen");
        }
    
        struct sockaddr_in peeraddr;
        socklen_t peerlen = sizeof(peeraddr);
        int connfd;
    
        if( (connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0 )
        {
            ERR_EXIT("accept");
        }
    
        printf("ip=%s, port=%d
    ", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
    
        pid_t pid;
        pid = fork();
        if(pid == -1)
        {
            ERR_EXIT("fork");
        }
        else if(pid == 0)
        {
            //child
            signal(SIGUSR1, handler);
            char sendbuf[1024];
            memset(sendbuf, 0, sizeof(sendbuf));
            while(fgets(sendbuf, sizeof(sendbuf), stdin)  != NULL)
            {
                write(connfd, sendbuf, strlen(sendbuf));
                memset(sendbuf, 0, sizeof(sendbuf));
            }
            exit(EXIT_SUCCESS);
        }
        else
        {
            char recvbuf[1024];
            while(1)
            {
                memset(recvbuf, 0, sizeof(recvbuf));
                int ret = read(connfd, recvbuf, sizeof(recvbuf));
                if(ret == -1)
                {
                    ERR_EXIT("read");
                }
                else if(ret == 0)
                {
                    printf("peer client close.
    ");
                    break;
                }
                else
                {
                    fputs(recvbuf, stdout);
                }
            }
            printf("parent exit
    ");
            kill(pid, SIGUSR1);
            exit(EXIT_SUCCESS);
        }
    
        close(connfd);
        close(listenfd);
        return 0;
    }
  • 相关阅读:
    使用DBUtils获取Blob类型数据
    关于 JupyterLab 与 Pandas 资源整理
    关于 Conda 在 MacOS Catalina 环境变量问题
    推荐一个符合 OIDC 规范的 JAVA 客户端
    关于 Chrome 的 Kiosk 模式
    Kubernetes 中的服务发现与负载均衡
    Prometheus 监控领域最锋利的“瑞士军刀”
    CD 基金会、Jenkins、Jenkins X、Spinnaker 和 Tekton 的常问问题
    Installing on Kubernetes with NATS Operator
    升级 ASP.NET Core 3.0 设置 JSON 返回 PascalCase 格式与 SignalR 问题
  • 原文地址:https://www.cnblogs.com/wiessharling/p/4007494.html
Copyright © 2020-2023  润新知