Linux网络中接收 "二进制" 流的那些事 --- 就recv的返回值和strlen库函数进行对话
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库函数进行对话的更多相关文章
- php从数据库中取二进制流文件转换为图片,图片以二进制流存入数据库实现
php从数据库中取二进制流文件转换为图片,图片以二进制流存入数据库实现 function data_uri($contents, $mime) { $base64 = base64_encode($c ...
- Selenium2学习-036-WebUI自动化实战实例-034-JavaScript 在 Selenium 自动化中的应用实例之六(获取 JS 执行结果返回值)
Selenium 获取 JavaScript 返回值非常简单,只需要在 js 脚本中将需要返回的数据 return 就可以,然后通过方法返回 js 的执行结果,方法源码如下所示: /** * Get ...
- 接收二进制流(ArrayBuffer) ,并且显示二进制流图片
1.调用接口,返回二进制流数据 var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { && xhr ...
- linux编程中接收主函数返回值以及错误码提示
程序A创建子进程,并调用进程B,根据不调用的不同情况,最后显示结果不同. #include <stdio.h> #include <unistd.h> #include < ...
- JSF页面中使用js函数回调后台bean方法并获取返回值的方法
由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...
- linux recv函数返回值分析
函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 该函数第一个参数制定接收端套接字描述符; 第二个参数指明一个缓冲区, ...
- 解决axios接收二进制流文件乱码问题
1. 须将axios 配置中的responseType设置为'arraybuffer',这样就不会让表格出现乱码现象: 2. 如果要动态设置文件名则需要让后台将名字设置到响应头中,否则将是一个乱码的文 ...
- net9:图片文件转换成二进制流存入SQL数据库,以及从数据库中读取二进制流输出文件
原文发布时间为:2008-08-10 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...
- 分析案例:应用服务无响应,任务管理器中发现大量w3wp僵尸进程----等待异构系统WebService返回值
问题描述: 某二次开发的项目反馈,不定期出现应用服务器无响应的情况,登录服务器发现任务管理器中有大量的w3wp僵尸进程. 分析过程: 针对同一进程每隔15秒抓取dump,连续抓取3个,对比 ...
随机推荐
- [Tjoi2013]循环格
[Tjoi2013]循环格 2014年3月18日1,7500 Description Input 第一行两个整数R,C.表示行和列,接下来R行,每行C个字符LRUD,表示左右上下. Output 一个 ...
- Python-MongoDB的驱动安装、升级
安装pip,并通过此来安装pymongo–Python mongodb驱动 1.下载pip安装包,下载地址:http://pypi.python.org/packages/source/p/pip/p ...
- C# JAVA成员访问修饰符比较
在面向对象的访问修饰符中常用的有public ,private ,protected C# 访问修饰符: private < protected internal < internal/p ...
- Echarts图表统计学习
史上最全的Echarts图表学习文档 http://echarts.baidu.com/doc/doc.html 勤加练习,多做总结! http://www.stepday.com/topic/?79 ...
- 实用的Jquery选项卡TAB
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Windows下编译Python2.7源码
本文开始一个系列文章,深入理解Python源码,算是阅读<Python源码剖析>一书的读书笔记,是一项长期进行的工作.一共分三个部分:Python对象模型,Python虚拟机,Python ...
- 云计算---openstack各服务端口使用情况
端口占用情况 端口情况可以使用ss -tanp命令进行查看 监听的所有端口ss -tanp | grep LISTEN 基础服务 22 --SSH 3306 --MariaDB(MySQL) 2701 ...
- jQuery Mobile事件,开发全解+完美注释
全栈工程师开发手册 (作者:栾鹏) jQuery Mobile事件全解 jQuery Mobile 所有class选项 jQuery Mobile 所有data-*选项 jQuery Mobile事件 ...
- Java策略模式以及来自lambda的优化
前言 设计模式是软件工程中一些问题的统一解决方案的模型,它的出现是为了解决一些普遍存在的,却不能被语言特性直接解决的问题,随着软件工程的发展,设计模式也会不断的进行更新,本文介绍的是经典设计模式 ...
- SAP 发送邮件 面向对象
REPORT ZMMR0068_YYN. CONSTANTS: gc_tab TYPE c VALUE cl_bcs_convert=>gc_tab, "CL_ABAP_CHAR_UT ...