zoukankan      html  css  js  c++  java
  • UNIX网络编程第5章TCP客户服务器程序示例5.2 5.3 5.4 5.5 5.6 5.7

    _QT)SRO6`C]DGX0S[0[ZC6G

    5AA[2DAH}~TKJ)62R7VHJMK

    H6@K7~VW((7JYE~(E[8`_RJ

    #include <iostream>
    #include "../lib/unpsunyj.h"
    
    int main(int argc, char** argv)
    {
        int                listenfd;
        int                connfd;
        pid_t              childpid;
        socklen_t          clilen;
        struct sockaddr_in cliaddr;
        struct sockaddr_in servaddr;
    
        // listenfd = Socket(AF_INET, SOCK_STREAM, 0);
        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            err_sys("socket error");
    
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET; // 如果是多宿,我们将接受目的地址为任何本地接口的连接
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        std::cout << SERV_PORT << std::endl;
        servaddr.sin_port        = htons(SERV_PORT);
    
        // Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
        if (bind(listenfd, (sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        {
            err_sys("bind error");
        }
    
        // Listen(listenfd, LISTENQ); // 转换为监听套接字
        if (listen(listenfd, LISTENQ) < 0)
        {
            err_sys("listen error");
        }
    
        for ( ; ; )
        {
            clilen = sizeof(cliaddr);
            // connfd = Accept(listenfd, (SA *) &cliaddr, &len);
    again:
            if ((connfd = accept(listenfd, (sockaddr*)&cliaddr, &clilen)) < 0)
            {
    #ifdef  EPROTO
                if (errno == EPROTO || errno == ECONNABORTED)
    #else
                    if (errno == ECONNABORTED)
    #endif
                        goto again;
                    else
                        err_sys("accept error");
            }
    
            // clilen = sizeof(cliaddr);
            // 服务器阻塞于accept调用,等待客户连接的完成
            // connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
            // fork为每个客户派生一个处理它们的子进程,子关闭监听套接字,父关闭已连接套接字
            if ((childpid = fork()) == -1)
                err_sys("fork error");
            if (0 == childpid) /* child process */
            {
                // Close(listenfd);    /* close listening socket */
                if (close(listenfd) == -1)
                {
                    err_sys("close error");
                }
                str_echo(connfd);   /* process the request */
                std::cout << "exiting tcpserv01 child process" << std::endl;
                // 服务器子进程调用exit来终止。服务器子进程中打开的所有描述符随之关闭,
                // 这会导致TCP连接终止序列
                // 的最后两个分节:一个从服务器到客户的FIN,和,一个从客户到服务器的ACK,至此,
                // 连接完全终止,客户套结字进入TIME_WAIT状态。
    
                // 另一方面
                // when this child is existed, this process will send sigchild signal to parent process
                // and in the parent process, we did not handle this signal, so the child process,
                // this process will be a zombie process, we can see that by command ps ux
                // exit(0);
                return 0;
            }
            // Close(connfd); /* parent closes connected socket */
            if (close(connfd) == -1)
            {
                err_sys("close error");
            }
        }
    }
    

    Z[G1P4I@}$3NO4%WPRKF04O

    T`NP9GVI96]125A[`7[QJRA

    ZYPQ9((3PT]K7KNON3_$Q`H

    #include <iostream>
    #include "unpsunyj.h"
    
    // 从客户读入数据,并把数据回射给客户
    void str_echo(int sockfd)
    {
        ssize_t n;
        char    buf[MAXLINE];
    
    again:
        while ( (n = read(sockfd, buf, MAXLINE)) > 0) // 从套接字读入数据
            Writen(sockfd, buf, n);                   // 把其中内容回射给客户。如果客户关闭连接(这是正常情况),那么接收到客户的FIN将导致服务器子进程的read函数返回0
        // 这又导致str_echo函数的返回,从而在tcpserv01.c中终止子进程。
    
        if (n < 0 && errno == EINTR)
            goto again;
        else if (n < 0)
            err_sys("str_echo: read error");
    
        std::cout << "exiting str_echo" << std::endl;
    }
    

    )~[T]D%HX`]JO[FYL5Q8J0A

    RM3%RIH8_@HOF_(BQ$K[(GX

    )_(}]]G$Y[83FGGIN587`_1

    #include <iostream>
    #include "../lib/unpsunyj.h"
    
    int main(int argc, char** argv)
    {
        int sockfd;
        struct sockaddr_in servaddr;
    
        if (argc != 2)
            err_quit("usage: tcpcli <IPaddress>");
    
        // sockfd = Socket(AF_INET, SOCK_STREAM, 0);
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
            err_sys("socket error");
        }
    
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(SERV_PORT);
        // Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
        if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
        {
            err_quit("inet_pton error for %s", argv[1]);
        }
    
        // Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
        if (connect(sockfd, (sockaddr*)&servaddr, sizeof(servaddr)) < 0)
        {
            err_sys("connect error");
        }
    
        str_cli(stdin, sockfd); /* do it all */
    
        std::cout << "exiting tcpcli01 main" << std::endl;
        // when a program is exiting, part of this action is that 
        // the kernal will close all descriptors opened,
        // including all the sockets.
        // 1, the client tcp(this program) will send FIN to server(tcpserv),
        // 2, the server tcp send ack to respond, then the server socket will be in CLOSE_WAIT status
        //    客户端套结字则处于FIN_WAIT_2状态
        // 3, 当服务器TCP接收FIN时,服务器子进程阻塞于readline调用,于是readline返回0,这导致
        //    str_echo函数返回服务器子进程的main函数
        // 4,服务器子进程调用exit来终止。服务器子进程中打开的所有描述符随之关闭,这会导致TCP连接终止序列
        //    的最后两个分节:一个从服务器到客户的FIN,和,一个从客户到服务器的ACK,至此,
        //    连接完全终止,客户套结字进入TIME_WAIT状态。
        // 
        // so the server will detect that this client is closing.
        exit(0);
    }
    

    WK]LV``6XZ]BT8))1UNDZ46

    Y}ZQWUO`TE49OA]J4%SMVVP

    #include "unpsunyj.h"
    
    void str_cli(FILE *fp, int sockfd)
    {
        char sendline[MAXLINE];
        char recvline[MAXLINE];
    
        // 从标准输入读入一行文本
        // 当遇到文件结束符或错误时,fgets将返回一个空指针,于是客户处理终止循环。我们的Fgets包裹函数检查是否发生错误,若发生则中止进程,因此Fgets只是在遇到文件结束符时
        // 才返回一个空指针
        while (Fgets(sendline, MAXLINE, fp) != NULL)
        {
            // 写到服务器上
            Writen(sockfd, sendline, strlen(sendline));
            // 读入服务器对该行的回射
            if (Readline(sockfd, recvline, MAXLINE) == 0)
                err_quit("str_cli: server terminated prematurely");
            // 把回射写到标准输出
            Fputs(recvline, stdout);
        }
        Fputs("exiting str_cli
    ", stdout);
    }
    

    R{%~U5CMY3T1YCUJKTZD$K1

    _TI3]O_[])R%W[)U086[`31

    W]U[XFT2]5IS579LLARXBNT

    ps -t pts/6 -o pid,ppid,tty,stat,args,wchan

    V6Y3{ZXWY@R4LD4_3T_X[XR

    }H7%LR2SRH@%_V6HEVWNY7B

    ROSI_004_020

    ROSI_004_021ROSI_004_022ROSI_004_023ROSI_004_024ROSI_004_025ROSI_004_026ROSI_004_027ROSI_004_028

    ROSI_004_029

    ROSI_004_030

    ROSI_004_031ROSI_004_032ROSI_004_033ROSI_004_034ROSI_004_035ROSI_004_036

    ROSI_004_037

    ROSI_004_038

    ROSI_004_039ROSI_004_040ROSI_004_041

    ROSI_004_042ROSI_004_043ROSI_004_044

    ROSI_004_045ROSI_004_046

  • 相关阅读:
    Apache ActiveMQ 远程代码执行漏洞 (CVE-2016-3088)案例分析
    linux 软中断过高性能优化案例
    jvm默认的并行垃圾回收器和G1垃圾回收器性能对比
    JVM性能参数优化
    一次压测中tomcat生成session释放不及时导致的频繁fullgc性能优化案例
    sed命令实现文件内容替换总结案例
    You have new mail in /var/spool/mail/root消除提示的方法
    zookeeper常用命令
    mongodb输错命令后不能删除问题
    centos环境gcc版本升级
  • 原文地址:https://www.cnblogs.com/sunyongjie1984/p/4342621.html
Copyright © 2011-2022 走看看