深入理解计算机系统-----echo客户端服务器

版权声明: https://blog.csdn.net/zl6481033/article/details/86242035

1、客户端

        echo客户端,在和服务器连接以后,客户端应该进入一个循环,反复从标准输入读取文本行,发送文本行给服务器,从服务器读取回送的行,并输出结果到标准输出。当fgets在标准输入上遇到EOF时,或者因为用户在键盘上输入ctrl+D,或者在遇到一个重定向的输入文件中用尽了所有的文本行时,循环截止。

//CSAPP中的一些辅助函数的定义
#include "csapp.h"  
  
int main(int argc, char **argv)   
{  

    int clientfd, port;  
    char *host, buf[MAXLINE];  
    rio_t rio;  
    // 客户端需要传进参数,IP地址和端口
    if (argc != 3)   
    {  
        fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);  
        exit(0);  
    }  
    host = argv[1];  
    //将字符串转为int,书上没有转换是错的
    port = atoi(argv[2]);  
    //打开
    clientfd = Open_clientfd(host, port);  
   //初始化RIO读写
    Rio_readinitb(&rio, clientfd);  
  
    while (Fgets(buf, MAXLINE, stdin) != NULL)   
    {  
        
        Rio_writen(clientfd, buf, strlen(buf));  
        Rio_readlineb(&rio, buf, MAXLINE);  
        Fputs(buf, stdout);  
    }  
    Close(clientfd); //line:netp:echoclient:close  
    exit(0);  
}  

2、服务器        

        服务器主程序,打开监听描述符,进入循环,等待一个来自客户端的连接请求,输出已连接的客户端域名和IP地址,并调用echo函数为这个客户端服务,在echo程序返回之后,主程序关闭已连接的描述符,一旦客户端和服务器都关闭了他们各自的描述符,连接终止。

#include "csapp.h"  
//服务器为客户端服务函数
void echo(int connfd);  
  
int main(int argc, char **argv)   
{  
    int listenfd, connfd, port, clientlen;  
    struct sockaddr_in clientaddr;  
    struct hostent *hp;  
    char *haddrp;  
    //需要传入一个端口号
    if (argc != 2)   
    {  
        fprintf(stderr, "usage: %s <port>\n", argv[0]);  
        exit(0);  
    }  
    //字符串转换为int
    port = atoi(argv[1]);  
     //打开一个监听描述符
    listenfd = Open_listenfd(port);  
    while (1)   
    {  
        clientlen = sizeof(clientaddr); 
       // 服务器通过调用accept函数来等待来自客户端的连接请求
        connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);  
  
        /* determine the domain name and IP address of the client */  
        hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,   
                sizeof(clientaddr.sin_addr.s_addr), AF_INET);  
        haddrp = inet_ntoa(clientaddr.sin_addr);  
        printf("server connected to %s (%s)\n", hp->h_name, haddrp);  
  
        echo(connfd);  
        Close(connfd);  
    }  
    exit(0);  
}  
//服务函数
void echo(int connfd)   
{  
    size_t n;   
    char buf[MAXLINE];   
    rio_t rio;  
  
    Rio_readinitb(&rio, connfd);  
    while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0)   
    { //line:netp:echo:eof  
        printf("server received %d bytes\n", n);  
        Rio_writen(connfd, buf, n);  
    }  
}  

3、结果 

        客户端发送接收到服务器回显。

        服务器显示接收到的数据大小。

        这里是简单的一个echo服务器一次只能一个客户端,这种类型的服务器一次一个的在客户端间迭代,称为迭代服务器,如果需要建立更复杂的并发的服务器,他能够同时处理多个客户端。

猜你喜欢

转载自blog.csdn.net/zl6481033/article/details/86242035