Linux网络中接收 "二进制" 流的那些事 --- 就recv的返回值和strlen库函数进行对话

小说:正规兼职打字员作者:侯顺秉更新时间:2018-12-11字数:43876

纪太虚身上琉璃光芒一闪,猛然从地上跳起来,空中的五个骷髅头一震,五张嘴同时吼道:“早知道你不老实,白某早有准备。”

淘宝联盟分享赚互刷

韩洁的叔叔说道:“我们当时是分开寻找的,只有我到了那个地方,后来才让他们也来的”。
那边跟周极大战的纪太虚已经是将周极狠狠的压制了住。一旁的韩凌霄跟支太皇立在半空之中虎视眈眈的看着周极,以防周极忽然逃脱!

“我给你三个选择,第一个我会在天焚炼气塔每一层布下一个阵法,进去的人都会陷入幻境当中,一旦陷入幻境和现实是没区别的,每一层的幻境都对应不同程度的实力,在环境中他会经历世间百态,或是战场厮杀,或是人间百态等等。

Linux网络中接收 "二进制" 流的那些事 --- 就recv的返回值和strlen库函数进行对话


1.    前言

  很多朋友在做网络编程开发的时候可能都遇到这样的问题,在进行接收二进制流的数据的时候,使用strlen库函数来得到

二进制数据长度的时候并不准确。为什么呢??首先,使用strlen进行统计长度的为字符串,并非二进制流数据,因此在

获取二进制数据流的定长中并不适合。解决的问题必然使用网络接收函数的返回值来进行判断,如recv和recvfrom等。

2.    简单的网络服务器

  Linux中简单的网络服务器做起来很简单,无非就是以下几个步骤

  创建网络套接字(socket) --> 绑定本地套接字到网络中(bind) --> 设置最大监听数目(listen) --> 监听客户端接入(accept)

3. 具体的例子

(服务端)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <errno.h>
 4 #include <sys/types.h>   
 5 #include <sys/socket.h>
 6 #include <arpa/inet.h>
 7 #include <unistd.h>
 8 
 9 #define  WEB_PORT      8080
10 #define  MAX_CLIENT     5
11 #define  MAX_RECV      1024
12 
13 int main(int argc,char *argv[])
14 {
15     // 1. 创建网络套接字
16     int sock = socket(AF_INET,SOCK_STREAM,0);
17     if(0 > sock)
18     {
19         fprintf(stderr,"socket: %s
",strerror(errno));
20         return -1;
21     }
22 
23     // 2. 设置端口立即释放,可以立即使用
24     int on = 1;
25     setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
26 
27     // 3. 绑定本地套接字到网络中
28     struct sockaddr_in localAddr;
29     socklen_t localAddrLen = sizeof(localAddr);
30 
31     localAddr.sin_family = AF_INET;
32     localAddr.sin_port = htons(WEB_PORT);
33     localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
34 
35     if(0 > bind(sock,(struct sockaddr *)&localAddr,localAddrLen))
36     {
37         fprintf(stderr,"bind: %s
",strerror(errno));
38         return -1;
39     }
40 
41     // 4. 设置最大监听数目
42     if(0 > listen(sock,MAX_CLIENT))
43     {
44         fprintf(stderr,"bind: %s
",strerror(errno));
45         return -1;
46     }
47 
48     // 5. 监听客户端接入
49     struct sockaddr_in peerAddr;
50     socklen_t peerAddrLen = sizeof(peerAddr);
51     char cRecvDataBuf[MAX_RECV] = {0};
52     ssize_t sRecvRet = 0;
53 
54     while(1)
55     {
56         int connfd = accept(sock,(struct sockaddr *)&peerAddr,&peerAddrLen);
57         if(0 > connfd)
58         {
59             fprintf(stderr,"accept: %s
",strerror(errno));
60             return -1;    
61         }
62 
63         memset(cRecvDataBuf,0,sizeof(cRecvDataBuf));
64         sRecvRet = recv(connfd,cRecvDataBuf,sizeof(cRecvDataBuf),0);
65         if(0 > sRecvRet)
66         {
67             fprintf(stderr,"recv: %s
",strerror(errno));
68             return -1;    
69         }
70 
71         printf("
**************************************
");
72         printf("sRecvRet = %ld
",sRecvRet);
73         printf("strlen(cRecvDataBuf) = %lu
",strlen(cRecvDataBuf));
74         printf("**************************************
");
75 
76         printf("
cRecvDataBuf :
%s

",cRecvDataBuf);
77 
78         close(connfd);
79     }
80 
81     close(sock);
82 
83     return 0;
84 }

(客户端)

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>   
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>

#define  WEB_PORT      8080

int main(int argc,char *argv[])
{
    // 1. 创建网络套接字
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(0 > sock)
    {
        fprintf(stderr,"socket: %s
",strerror(errno));
        return -1;
    }

    // 2. 设置端口立即释放,可以立即使用
    int on = 1;
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

    // 3. 设置服务器的地址和链接发送二进制流数据
    struct sockaddr_in serverAddr;
    socklen_t serverAddrLen = sizeof(serverAddr);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(WEB_PORT);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(0 == connect(sock,(struct sockaddr *)&serverAddr,serverAddrLen))
    {

        FILE *pFile = fopen("./linux.bin.ub","rb");
        if(NULL != pFile)
        {
            // 4. 获取二进制文件的数据大小            
            fseek(pFile,0,SEEK_END);
            long lFileSize = ftell(pFile);
            rewind(pFile);

            // 5. 读取数据并发送
            char *pSendBuf = (char *)malloc(lFileSize+1);
            if(NULL == pSendBuf)
            {
                fprintf(stderr,"malloc: %s
",strerror(errno));    
                return -1;
            }

            memset(pSendBuf,0,lFileSize+1);
            fread(pSendBuf,lFileSize,1,pFile);
            fclose(pFile);

            send(sock,pSendBuf,lFileSize,0);

            free(pSendBuf);
            close(sock);
        }

    }

    return 0;

}

(二进制流数据 : 9.27 MB (9,728,804 字节) )

4.    比较结果:

  首先本人在服务器端只是接受一次的数据,最大长度为1024字节,那么如何收到的二进制数据的程度实际上应该为1024字节(假设网路正常,只接收一次,由于文件的二进制流数据大小为9728804字节,所以收到的数据长度为1024字节),具体的结果如下:

5.    结论:

  从结果图可以看出,如果使用strlen进行获取数据的话只有12字节,使用返回值来定长度的话,确实1024字节,这个返回值才是正确的。因

此,在网络编程中,建议大家在发送二进制文件流或者在接收二进制文件流的时候,切记不要使用strlen进行定长,否则容易出错。但是如果发送的是字符串流的数据的话,这倒不是什么问题,但是为了系统安全和数据的准确性,使用返回值比strlen更加有优

势。

当前文章:http://0477auto.com/html_61712/index.html

发布时间:2018-12-11 05:51:59

英魂之刃赚钱秘籍 梦幻休闲玩家怎么赚钱 信用卡羊毛群什么意思 佛山微信兼职群 荣成会计兼职工作 ps在线图片处理兼职 有没有手机兼职 在家就可以做的ps兼职

编辑:侯开徒帝

我要说两句: (0人参与)

发布