socket传送二进制流的一些总结

第一次实质性的接触socket通信方面的工作,所以遇到的问题还真不少,写篇博客记录一下,提升下记忆。

需求是通过私有协议进行二进制数据的传输,必须保证数据包不能被丢失,所以选择tcp的socket进行通信。

1. 遇到的第一个问题是客户端与服务端的socket通信没有保持持续的连接状态

这个是一个想当然的错误。想当然的以为TCP是有连接的通信,但是你如果长时间不通信,服务端一直保持着通信,这对服务器资源是一种极大的浪费。客户端与服务端的连接是需要占用一定资源的,而服务端的资源是有限的。如果一直保持连接状态,那么你的服务器的性能肯定是有问题的。

解决这个问题的办法是保活。服务端发送心跳包,客户端接受到之后进行回应。客户端告诉服务器,还在线,不要断开连接。如果客户端长时间没有回应,服务器断开与此客户端的连接,减少资源占用。

2. 二进制文件的读写问题

第一次尝试读取二进制文件采取了分段读取的方式。测试过程中发现一个很大的问题:文件读取到部分就会中断读取。debug下,得出是读取到了空字符(‘\0‘)。这个直接导致一次读取到内容在发送前丢失,甚至有些情况下会有空字符,客户端接受时会产生崩溃现象。

既然分段不行,就干脆全部读取,然后在分段发送。boost.asio库支持对vector包装发送,分段发送时,把一块二进制流拷贝到vector中,然后整体发送。

3. 提高二进制流的传输效率

直接传输二进制流不是一个高效的行为,也不是一个安全的行为。直接发送一个二进制流很容易被截获,从而导致信息泄露。

提高二进制流传输效率的办法就是加密压缩再发送。服务器加密压缩,客户端解密解压缩。可采取两种方式:

1)整体压缩,分段发送

2)分段压缩,分段发送

要求不是很高的话,采取方式一比较好。简单粗暴。。

贴一些代码,整体读取二进制文件的:

先是C++的:

 1     string fileName = "D:/XtAmpClient/XtAmpTradeClient_x64_3.0.1.14473.exe";
 2     ifstream ifs(fileName, ios_base::binary);
 3
 4     filebuf* pbuf = ifs.rdbuf();
 5     int size = pbuf->pubseekoff(0, ios_base::end, ios_base::in);
 6     pbuf->pubseekpos(0, ios_base::in);
 7
 8     char* buf = new char[size];
 9     pbuf->sgetn(buf, size);
10     ifs.close();
11     delete []buf;

最后是C的:

 1     const char* fileName = "D:/XtAmpClient/XtAmpTradeClient_x64_3.0.1.14473.exe";
 2     FILE* fp = fopen(fileName, "rb");
 3     if (NULL == fp)
 4     {
 5         cout << "open file failed" << endl;
 6         return ;
 7     }
 8
 9     fseek(fp, 0, SEEK_END);
10     long size = ftell(fp);
11     rewind(fp);
12
13     char* buffer = (char*)malloc(sizeof(char) * size);
14     if (NULL == buffer)
15     {
16         cout << "malloc failed" << endl;
17         return ;
18     }
19
20     int ret = fread(buffer, 1, size, fp);
21     if (ret != size)
22     {
23         cout << "reading failed" << endl;
24         return ;
25     }
26
27     fclose(fp);
28     free(buffer);

性能上C比C++好一点点,但是C++的代码明显更简洁。

原文地址:https://www.cnblogs.com/zhugaopeng/p/9688882.html

时间: 2024-11-04 16:29:32

socket传送二进制流的一些总结的相关文章

WCF传送二进制流数据基本实现步骤详解

引用:http://www.cnblogs.com/lusunqing/p/3399594.html WCF传送二进制流数据的相关操作方法在实际应用中是一个比较基础的操作应用.我们在这里将会针对此做一个详细介绍. 我们知道,在实现WCF传送二进制流数据这一操作过程中,会有一些限制因素.我们在实际应用中要特别注意这一点.今天我们就会针对这方面的问题做一个详细的介绍,希望对大家有所帮助. WCF释放服务对象最直接方式解读 WCF分布事务保证数据完整性 Silverlight调用WCF出现异常解决方案

java socket传送和接受byte[]

数据发送端(客户端):   //创建一个Socket对象,连接IP地址为192.168.101.56的服务器的9002端口               Socket s = new Socket("192.168.101.56",9002); byte[] content=new byte[100];    content[0]=(byte) 0xE2;     content[1]=(byte) 0x5C; String fix="HHCYFI"; byte[]

TCP二进制流接收

前几天,模拟了一个tcp发送与接收16进制的小程序.由于需求的改变现在需要接收二进制流式数据,下面记录一下客户端接收数据的实现的源码. package client; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; public class ClientSocket { static Socket socket = nul

使用C#向Sql Sever中存取网络图片和本地图片(二进制流的形式)

先是做普通的,存储我们本地的图片,将它转化为二进制流存储到数据库对应的表中. 代码如下: string path = "../../A.jpg"; FileStream fs = new FileStream(path, FileMode.Open); int streamLength = (int)fs.Length; //获取文件流的长度. byte[] image = new byte[streamLength]; //声明字节数组,用于保存图片文件 fs.Read(image,

python+ mysql存储二进制流的方式

很多时候我们为了管理方便会把依稀很小的图片存入数据库,有人可能会想这样会不会对数据库造成很大的压力,其实大家可以不用担心,因为我说过了,是存储一些很小的图片,几K的,没有问题的! 再者,在这里我们是想讲一种方法,python+ mysql存储二进制流的方式 这里用的是Mysqldb,python里面最常用的数据库模块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

[.net&#160;面向对象程序设计进阶] (9) 序列化(Serialization) (一) 二进制流序列化

[.net 面向对象程序设计进阶]  (9)  序列化(Serialization) (一) 二进制流序列化 本节导读: 在.NET编程中,经常面向对象处理完以后要转换成另一种格式传输或存储,这种将对象转向其他数据格式的过程,即序列化(Serialization). 与之相反的过程就是反序列化(Deserialization).掌握和利用好序列化和反序列化的方法,对提高面向编程技术很有益处. 读前必备: A.类和类的实例  [.net 面向对象编程基础]  (9) 类和类的实例  B.类的成员

转:php park、unpark、ord 函数使用方法(二进制流接口应用实例)

在工作中,我也逐渐了解到park,unpark,ord对于二进制字节处理的强大. 下面我逐一介绍它们. park,unpark,ord这3个函数,在我们工作中,用到它们的估计不多. 我在最近一个工作中,因为通讯需要用到二进制流,然后接口用php接收.当时在处理时候,查阅不少资料.因为它们使用确实比较少,也很少朋友工作中会用到它们. 在工作中,我也逐渐了解到park,unpark,ord对于二进制字节处理的强大. 下面我逐一介绍它们. park,unpark,ord函数使用介绍 park函数说明:

二进制流BinaryFormatter存储读取数据的细节测试

二进制流的使用很方便,为了更好的理解应用它,我创建简单对象开始测试它的增加特性和减少特性. [Serializable] class Data----------开始时候的存储对象 { public string name = "namex"; public string ceshia = "aa"; public string ceshib = "bb"; } [Serializable] class Data----------在代码中修改存

javamail发送二进制流附件的问题

最近做个邮件发送功能,要内嵌图片并有附件. 需求很奇怪,图片和附件文件是放在ftp服务器上的,查了下javamail的文档. 添加附件方法如下 MimeBodyPart messageBodyPart=new MimeBodyPart(); DataSource dataSource1=new FileDataSource("d:/xx.doc"); //DataSource dataSource1=new UrlDataSource("url"); 按照这个api