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. Apache shiro的简单介绍与使用(与spring整合使用)

    apache shiro框架简介 Apache Shiro是一个强大而灵活的开源安全框架,它能够干净利落地处理身份认证,授权,企业会话管理和加密.现在,使用Apache Shiro的人越来越多,因为它 ...

  2. CPU工作方式、多核心、超线程技术详解[转贴]

    CPU是一台电脑的灵魂,决定电脑整体性能.现在的主流CPU都是多核的,有的运用了多线程技术(Hyper-threading,简称HT).多核可能还容易理解些,相信不少玩家都能说出个所以然.但超线程是个 ...

  3. 访问 IIS 元数据库失败

    问题: 访问 IIS 元数据库失败.说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息. 异常详细信息: System.Web ...

  4. 聊聊Java语言中的单例

    package com.xinke.mybatis.test; public class TestSingleton { private static TestSingleton ts = null; ...

  5. ZOJ1654 Place the Robots

    Zoj1654 标准解法:二分匈牙利. 写法各异嘛,看不懂或者懒得看也正常,如果想了解我思路的可以和我讨论的. 在练习sap,所以还是写了一遍: #include<cstdio> #inc ...

  6. ZOJ2975 伪数组压缩+组合数

    Kinds of Fuwas Time Limit: 2 Seconds      Memory Limit:65536 KB In the year 2008, the 29th Olympic G ...

  7. zoj 1884 简单 键盘 字符 处理

    WERTYU Time Limit: 2 Seconds      Memory Limit: 65536 KB A common typing error is to place the hands ...

  8. kazoo python zookeeper 选主

    本文讲述基于zookeeper选主与故障切换的方法.我们的例子使用的是python. 使用的库是kazoo,安装方式 pip install kazoo  应用场景: 多个实例部署,但不是" ...

  9. commons-pool与commons-pool2连接池

    commons-pool和commons-pool2是用来建立对象池的框架,提供了一些将对象池化必须要实现的接口和一些默认动作.对象池化之后可以通过pool的概念去管理其生命周期,例如对象的创建,使用 ...

  10. gitlab实时备份方案(非官方命令)

    gitlab自带的备份功能做不到实时备份,为了尽可能减少意外情况导致的丢失数据,自己搞了一个实时备份的功能. 备份的大头主要是两部分,数据库和代码库.数据库由DBA配置主备. 仓库经过测试,通过lsy ...