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

小说:乐彩彩金赠送作者:伯密更新时间:2018-10-19字数:43169

唐三看着大师,道:“老师,我打算明天一早就上路了。虽然和兄弟们重聚的机会不多,可是,我很担心小舞。五年不见,也不知道她怎么样了。不如这样,我们再定下一个五年之约。五年之后,我们依旧在学院重聚。那时候小奥应该也回来了,我在带上小舞,我们史莱克七怪也能再次凑齐。”

博彩注册送23元体验金可提现

“这个你是不用想了,已经有人和你抢了。”刘皓掌心中跳跃出了一朵火莲,美杜莎看了都忍不住后退半步,可想而知美杜莎对这一朵火莲的忌惮到了什么地步,就算是斗尊强者美杜莎也不会如此忌惮,但是这一朵小小的火莲却让她忌惮无比。
叶扬将导弹发射器扔到一旁,提着枪便是走了进去。他见人就杀,根本无需去问,只要是在这个山庄里的任何人,都将是他今晚的杀戮对象。若你只是客人,那对不起,算你今天倒霉。

张宣听了点点头:“形势糜烂到这种地步也只能如此了,我再以钦差身份向湖广、淮河、剑南、岭南四道发出符牒,凡是有净土教妖孽妖言惑众者——杀无赦!凡是散播妖言者——杀无赦!凡是信奉邪教者——杀无赦!凡是藏匿邪教妖孽、藏匿邪教典籍仪仗,为邪教通风报信者——杀无赦!从明日起,捣毁切邪教聚会之地点,查封查抄邪教一切财物,敢有违抗、阻拦、鸣冤者——杀无赦!”

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更加有优

势。

编辑:华海

发布:2018-10-19 14:04:43

当前文章:http://www.leetaemin.cn/32978.html

辉煌国际开户送40元彩金 什么网站开户送现金了 注册送现金 无需申请 必赢亚洲注册送30元现金 不限ip开户即送40元现金 赌场新注册绑卡送现金 注册送钱马上提现 娱乐手机客户端下载777

15388 84436 20570 44291 23568 9934641750 78855 65283

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

发布