zoukankan      html  css  js  c++  java
  • TCP之简单回传(二)

    鉴于TCP之简单回传(一)   中所出现的问题,本博文所要采取的一种方法是:

    客户端:先向服务器传送一个 int32_t 大小的数据,表示随后所要发送数据的真实长度; 
    
    服务器:先接收一个int32_t 大小的数据,再接收真实的数据

    本程序中所用到的函数都可以在 TCP之函数封装 中找到;

    server服务器端具体实现: 

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m);
            exit(EXIT_FAILURE);
        }while(0)
    
    void do_server(int fd);
    
    int main(int argc, const char *argv[])
    {
    //socket    
        int listenfd = socket(AF_INET, SOCK_STREAM, 0 );
        if( -1 == listenfd)
            ERR_EXIT("socket");
    //地址复用
        int on = 1;
        if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0)
            ERR_EXIT("setsockopt");
    //bind
        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8888); //主机字节序转化为网络字节序
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");//点分十进制转化成网络字节序
        if( -1 == bind( listenfd, (struct sockaddr*)&addr, sizeof(addr)))
            ERR_EXIT("bind");
    
    //listen
        if( -1 == listen(listenfd,SOMAXCONN ))
            ERR_EXIT("listen");
        
    //accept    
        int peerfd = accept(listenfd, NULL, NULL);//对方的IP&PORT
    
    //read&write    
        do_server(peerfd);
    
    //close
        close(peerfd);
        close(listenfd);
        return 0;
    }
    
    void do_server(int  fd)
    {
        char recvbuf[1024100] = {0};
        int cnt =0;
        while(1)
        {
            int32_t len = recv_int32(fd);//先接收一个表示真是长度的int型数据    
            int nread = readn(fd, recvbuf, len);//读取数据
            if(nread == -1)//err
            {
                if(errno == EINTR)
                    continue;
                ERR_EXIT("read");
            }else if (nread == 0 || nread < len )//write close
            {
                printf("close...
    ");
                exit(EXIT_FAILURE);
            }
            
            // ok 
            printf("count = %d recv size = %d
    ",++cnt, nread);
            memset(recvbuf, 0, sizeof(recvbuf));
        }
    }
    View Code

    client客户端具体实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <errno.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m);
            exit(EXIT_FAILURE);
        }while(0)
    void do_server(int fd);
    
    int main(int argc, const char *argv[])
    {
    //socket
        int peerfd = socket(AF_INET, SOCK_STREAM,0);
        if( -1 == peerfd)
            ERR_EXIT("socket");
    //connect
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8888);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        
        if( -1 == connect(peerfd,(struct sockaddr*)&addr, sizeof(addr) ))
            ERR_EXIT("connect");
    
    //read&write
        do_server(peerfd);
    
        return 0;
    }
    
    void do_server(int fd)
    {
        #define SIZE 1024
        char sendbuf[SIZE +1]= {0};
        int i ;
        for (i = 0; i < SIZE; i++) 
        {
            sendbuf[i]= 'a';    
        }
        int cnt =0;
        while(1)
        {
            int i;
            for (i = 0; i < 10; i++) 
            {
                send_int32(fd, SIZE);//先发送一个表示真实长度的int型数据
                int nwrite =writen(fd, sendbuf, SIZE);//写数据
                if( nwrite != SIZE)//err
                    ERR_EXIT("writen");
                printf("cout = %d,write %d bytes
    ",++cnt, SIZE);
            }
            nano_sleep(4.5);
        }
    }
    View Code


    测试结果:

    ./server
    count = 1 recv size = 1024
    count = 2 recv size = 1024
    count = 3 recv size = 1024
    count = 4 recv size = 1024
    count = 5 recv size = 1024
    count = 6 recv size = 1024
    count = 7 recv size = 1024
    count = 8 recv size = 1024
    count = 9 recv size = 1024
    count = 10 recv size = 1024
    count = 11 recv size = 1024
    count = 12 recv size = 1024
    count = 13 recv size = 1024
    count = 14 recv size = 1024
    count = 15 recv size = 1024
    count = 16 recv size = 1024
    count = 17 recv size = 1024
    count = 18 recv size = 1024
    count = 19 recv size = 1024
    count = 20 recv size = 1024
    View Code
    ./client
    cout = 1,write 1024 bytes
    cout = 2,write 1024 bytes
    cout = 3,write 1024 bytes
    cout = 4,write 1024 bytes
    cout = 5,write 1024 bytes
    cout = 6,write 1024 bytes
    cout = 7,write 1024 bytes
    cout = 8,write 1024 bytes
    cout = 9,write 1024 bytes
    cout = 10,write 1024 bytes
    cout = 11,write 1024 bytes
    cout = 12,write 1024 bytes
    cout = 13,write 1024 bytes
    cout = 14,write 1024 bytes
    cout = 15,write 1024 bytes
    cout = 16,write 1024 bytes
    cout = 17,write 1024 bytes
    cout = 18,write 1024 bytes
    cout = 19,write 1024 bytes
    cout = 20,write 1024 bytes
    View Code
  • 相关阅读:
    EntityFramework 迁移遇到的问题
    Eclipse下使用PySpark报Could not find valid SPARK_HOME while searching
    Eclipse下使用PySpark报Could not find valid SPARK_HOME while searching
    Eclipse下使用PySpark报Could not find valid SPARK_HOME while searching
    Eclipse下使用PySpark报Could not find valid SPARK_HOME while searching
    通过fiddler抓取IDEA的请求
    Visual Studio中你所不知道的智能感知
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    区块链的诞生及演化
  • 原文地址:https://www.cnblogs.com/xfxu/p/4027508.html
Copyright © 2011-2022 走看看