1.    前言

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

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

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

2.    简单的网络服务器

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

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

3. 具体的例子

(服务端)

 #include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h> #define WEB_PORT 8080
#define MAX_CLIENT 5
#define MAX_RECV 1024 int main(int argc,char *argv[])
{
// 1. 创建网络套接字
int sock = socket(AF_INET,SOCK_STREAM,);
if( > sock)
{
fprintf(stderr,"socket: %s\n",strerror(errno));
return -;
} // 2. 设置端口立即释放,可以立即使用
int on = ;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); // 3. 绑定本地套接字到网络中
struct sockaddr_in localAddr;
socklen_t localAddrLen = sizeof(localAddr); localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(WEB_PORT);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY); if( > bind(sock,(struct sockaddr *)&localAddr,localAddrLen))
{
fprintf(stderr,"bind: %s\n",strerror(errno));
return -;
} // 4. 设置最大监听数目
if( > listen(sock,MAX_CLIENT))
{
fprintf(stderr,"bind: %s\n",strerror(errno));
return -;
} // 5. 监听客户端接入
struct sockaddr_in peerAddr;
socklen_t peerAddrLen = sizeof(peerAddr);
char cRecvDataBuf[MAX_RECV] = {};
ssize_t sRecvRet = ; while()
{
int connfd = accept(sock,(struct sockaddr *)&peerAddr,&peerAddrLen);
if( > connfd)
{
fprintf(stderr,"accept: %s\n",strerror(errno));
return -;
} memset(cRecvDataBuf,,sizeof(cRecvDataBuf));
sRecvRet = recv(connfd,cRecvDataBuf,sizeof(cRecvDataBuf),);
if( > sRecvRet)
{
fprintf(stderr,"recv: %s\n",strerror(errno));
return -;
} printf("\n**************************************\n");
printf("sRecvRet = %ld\n",sRecvRet);
printf("strlen(cRecvDataBuf) = %lu\n",strlen(cRecvDataBuf));
printf("**************************************\n"); printf("\ncRecvDataBuf :\n%s\n\n",cRecvDataBuf); close(connfd);
} close(sock); return ;
}

(客户端)

#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,);
if( > sock)
{
fprintf(stderr,"socket: %s\n",strerror(errno));
return -;
} // 2. 设置端口立即释放,可以立即使用
int on = ;
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( == connect(sock,(struct sockaddr *)&serverAddr,serverAddrLen))
{ FILE *pFile = fopen("./linux.bin.ub","rb");
if(NULL != pFile)
{
// 4. 获取二进制文件的数据大小
fseek(pFile,,SEEK_END);
long lFileSize = ftell(pFile);
rewind(pFile); // 5. 读取数据并发送
char *pSendBuf = (char *)malloc(lFileSize+);
if(NULL == pSendBuf)
{
fprintf(stderr,"malloc: %s\n",strerror(errno));
return -;
} memset(pSendBuf,,lFileSize+);
fread(pSendBuf,lFileSize,,pFile);
fclose(pFile); send(sock,pSendBuf,lFileSize,); free(pSendBuf);
close(sock);
} } return ; }

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

4.    比较结果:

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

5.    结论:

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

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

势。

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

  1. php从数据库中取二进制流文件转换为图片,图片以二进制流存入数据库实现

    php从数据库中取二进制流文件转换为图片,图片以二进制流存入数据库实现 function data_uri($contents, $mime) { $base64 = base64_encode($c ...

  2. Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)

    Selenium 获取 JavaScript 返回值非常简单,只需要在 js 脚本中将需要返回的数据 return 就可以,然后通过方法返回 js 的执行结果,方法源码如下所示: /** * Get ...

  3. 接收二进制流(ArrayBuffer) ,并且显示二进制流图片

    1.调用接口,返回二进制流数据 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { && xhr ...

  4. linux编程中接收主函数返回值以及错误码提示

    程序A创建子进程,并调用进程B,根据不调用的不同情况,最后显示结果不同. #include <stdio.h> #include <unistd.h> #include < ...

  5. JSF页面中使用js函数回调后台bean方法并获取返回值的方法

    由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...

  6. linux recv函数返回值分析

    函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 该函数第一个参数制定接收端套接字描述符; 第二个参数指明一个缓冲区, ...

  7. 解决axios接收二进制流文件乱码问题

    1. 须将axios 配置中的responseType设置为'arraybuffer',这样就不会让表格出现乱码现象: 2. 如果要动态设置文件名则需要让后台将名字设置到响应头中,否则将是一个乱码的文 ...

  8. net9:图片文件转换成二进制流存入SQL数据库,以及从数据库中读取二进制流输出文件

    原文发布时间为:2008-08-10 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...

  9. 分析案例:应用服务无响应,任务管理器中发现大量w3wp僵尸进程----等待异构系统WebService返回值

    问题描述:       某二次开发的项目反馈,不定期出现应用服务器无响应的情况,登录服务器发现任务管理器中有大量的w3wp僵尸进程. 分析过程: 针对同一进程每隔15秒抓取dump,连续抓取3个,对比 ...

随机推荐

  1. OpenJudge_1321:棋盘问题

    题目描述 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆 ...

  2. http://codeforces.com/contest/612/problem/D

    D. The Union of k-Segments time limit per test 4 seconds memory limit per test 256 megabytes input s ...

  3. fitnesse - 一个简单的例子(slim)

    fitnesse - 一个简单的例子(slim) 2017-09-30 目录1 编写测试代码(Fixture code)2 编写wiki page并运行  2.1 新建wikiPage  2.2 运行 ...

  4. docker镜像文件导入与导出

    工作中经常需要拉取一些国外的镜像,但是网络限制等原因在公司拉取很慢,所以我习惯用亚马逊服务器拉取镜像,导出后下载到本地再导入开发环境 1. 查看镜像id sudo docker images REPO ...

  5. git fsck -- 一致性检查

    格式:           git fsck  [选项] <path> 选项 git commit -a 提交所有改动的文件(a -- all) git commit -m 提交说明(m ...

  6. Python内置类型(2)——布尔运算

    python中bool运算符按优先级顺序分别有or.and.not, 其中or.and为短路运算符 not先对表达式进行真值测试后再取反 not运算符值只有1个表达式,not先对表达式进行真值测试后再 ...

  7. Hibernate 学习笔记 - 2

    五.映射一对多关联关系 1. 单向多对一 即 单向 n-1 1)单向 n-1 关联只需从 n 的一端可以访问 1 的一端 ① 域模型: 从 Order 到 Customer 的多对一单向关联需要在Or ...

  8. 使用Hexo+Github一步步搭建属于自己的博客(进阶)

    主题的配置:这里以NexT主题作为题材 1.安装NexT,在其文件夹中鼠标右键,点击Git Base Here.输入命令:git clone https://github.com/iissnan/he ...

  9. 【转】缓存淘汰算法系列之3——FIFO类

    原文地址:http://www.360doc.com/content/13/0805/16/13247663_304923435.shtml 1 FIFO 1.1. 原理 按照“先进先出(First ...

  10. LESS IS MORE

    学习完css部分,相信大家对通过css进行DOM元素的样式操作已经非常熟悉,也可以通过css的语法进行页面显示效果的添加和修改.如果你们对css报以崇高敬意,感觉它拯救了你的整个网页的话,其实你正在犯 ...