zoukankan      html  css  js  c++  java
  • 第十篇:基于TCP的一对回射客户/服务器程序及其运行过程分析( 上 )

    前言

           本文将讲解一对经典的客户/服务器回射程序,感受网络编程的大致框架( 该程序稍作改装即可演变成各种提供其他服务的程序 );同时,还将对其运行过程加以分析,观察程序背后协议的执行细节,学习调试网络程序的技巧。

    客户端

     1 #include    "unp.h"
     2 
     3 void str_cli(FILE *fp, int sockfd);
     4 
     5 int
     6 main(int argc, char **argv)
     7 {
     8     int                    sockfd;
     9     struct sockaddr_in    servaddr;
    10 
    11     if (argc != 2)
    12         err_quit("usage: tcpcli <IPaddress>");
    13 
    14     sockfd = Socket(AF_INET, SOCK_STREAM, 0);
    15 
    16     bzero(&servaddr, sizeof(servaddr));
    17     servaddr.sin_family = AF_INET;
    18     servaddr.sin_port = htons(SERV_PORT);
    19     Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
    20 
    21     Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));
    22 
    23     str_cli(stdin, sockfd);    
    24 
    25     exit(0);
    26 }
    27 
    28 /*
    29  * 事务函数
    30 */
    31 void
    32 str_cli(FILE *fp, int sockfd)
    33 {
    34     char    sendline[MAXLINE], recvline[MAXLINE];
    35 
    36     // 从标准输入读取字符串( 阻塞于用户 )    
    37     while (Fgets(sendline, MAXLINE, fp) != NULL) {
    38 
    39         // 往缓冲区写入字符串
    40         Writen(sockfd, sendline, strlen(sendline));
    41 
    42         // 从缓冲区读取字符串( 阻塞于服务器传回的数据 )
    43         if (Readline(sockfd, recvline, MAXLINE) == 0)
    44             err_quit("str_cli: server terminated prematurely");
    45 
    46         // 读取从服务器回射的消息并在终端打印
    47         Fputs(recvline, stdout);
    48     }
    49 }

    服务器端

     1 #include    "unp.h"
     2 
     3 void str_echo(int sockfd);
     4 
     5 int
     6 main(int argc, char **argv)
     7 {
     8     int                    listenfd, connfd;
     9     pid_t                childpid;
    10     socklen_t            clilen;
    11     struct sockaddr_in    cliaddr, servaddr;
    12 
    13     listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    14 
    15     bzero(&servaddr, sizeof(servaddr));
    16     servaddr.sin_family      = AF_INET;
    17     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    18     servaddr.sin_port        = htons(SERV_PORT);
    19 
    20     Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
    21 
    22     Listen(listenfd, LISTENQ);
    23 
    24     for ( ; ; ) {
    25         clilen = sizeof(cliaddr);
    26         connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
    27 
    28         if ( (childpid = Fork()) == 0) {    /* 子进程处理段 */
    29             Close(listenfd);    /* 关闭监听套接字 */
    30             str_echo(connfd);    /* 事务处理 */
    31             exit(0);
    32         }
    33         Close(connfd);            /* 父进程关闭连接套接字 */
    34     }
    35 }
    36 
    37 /*
    38  * 事务处理函数
    39 */
    40 void
    41 str_echo(int sockfd)
    42 {
    43     ssize_t        n;
    44     char        buf[MAXLINE];
    45 
    46 again:
    47     while ( (n = read(sockfd, buf, MAXLINE)) > 0)
    48         Writen(sockfd, buf, n);
    49 
    50     if (n < 0 && errno == EINTR)
    51         goto again;
    52     else if (n < 0)
    53         err_sys("str_echo: read error");
    54 }
  • 相关阅读:
    行锁原理 天高地厚
    unity c#
    (转)C#导出Excel源码
    c#.net]做tooltip给控件动态添加属性的做法、IExtenderProvider接口的使用
    自定义提供程序控件
    在C#中使用SQLite
    哈佛大学凌晨4点半的景象
    (转)SQLServer常见查询问题
    .NET组件编程
    窗体着色
  • 原文地址:https://www.cnblogs.com/muchen/p/6357425.html
Copyright © 2011-2022 走看看