我将输入的信息保存在aaa 里面
现在需要保存一个文件的内容
因为是2进制文件 所以里面有\x00 字符
所以在输入的时候 会断掉
aaa += "\x0D\x0A\x0D\x0A\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xFF\xFF\xFF\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00"
在中途会断掉
我想这个问题 只要是网络传输都会遇到
比如人家传给你一个含有\x00 的字符串 那么缓存中就有\x00 字符了 但不是缓存结束的地方
这时候用strlen 取缓存长度 再取数据 显然不对
你怎么处理呢?
39 个解决方案
#1
不要用字符串处理
当作普通的整形数来处理
当作普通的整形数来处理
#2
拿我存取的时候怎么办? 一个个整数的往外取?
整数是4字节 有可能取不到4字节
普通的ftp 客户端怎么做呢?
取到了传来的数据放在 一个缓存块以后
因为有\x00 它如何确定缓存块的实际长度?
整数是4字节 有可能取不到4字节
普通的ftp 客户端怎么做呢?
取到了传来的数据放在 一个缓存块以后
因为有\x00 它如何确定缓存块的实际长度?
#3
memcpy
#4
对于缓冲区的实际大小问题,如果当中可能传递'\0',那么除非wchar_t *,或者数据整体本身并非单一个字符串,在这种情况下若是参数,通常需要带入数据长度。
#5
改写string类就行了吧,重新写个char_traits类,按你的要求进行操作,替换掉原来那个就行了~
#6
shellcode里面有一种解决方法~~~
把所有的code都 与 一个高的数 for example: \x99 then unencode
把所有的code都 与 一个高的数 for example: \x99 then unencode
#7
对于缓冲区的实际大小问题,如果当中可能传递'\0',那么除非wchar_t *,或者数据整体本身并非单一个字符串,在这种情况下若是参数,通常需要带入数据长度。
我并不知道要传来的数据的长度。我需要检测数据内容 才知道是否内容结束
我并不知道要传来的数据的长度。我需要检测数据内容 才知道是否内容结束
#8
对于这种情况,不要用strcpy,string这些东东,用memcpy函数。网络传输中包的长度是包含在包中的。
#9
你说得问题基本上无法解决的。
所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息。如果你使用的协议无法提供这个信息,或者是协议设计缺陷,或者你还没有完全理解这个协议。
另外,你的话实际上是个病语“传给你一个含有\x00 的字符串”:在C里面字符串是如何定义的呢?准确地讲,他传给你的是“字节流”,而不是字符串。
所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息。如果你使用的协议无法提供这个信息,或者是协议设计缺陷,或者你还没有完全理解这个协议。
另外,你的话实际上是个病语“传给你一个含有\x00 的字符串”:在C里面字符串是如何定义的呢?准确地讲,他传给你的是“字节流”,而不是字符串。
#10
boxban(冻酸梨) ( ) 说的不错。
“所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息”是对的,比如VB6里的winsock控件,在接收到数据的时候,有两个有用的属性值bytestotal(接收的总字节数)和bytesreceived(已经接收到的字节数),通过这两个值就可以判断数据是否已经接收完。
如果底层协议无法返回收到的字节数,那么就要在应用一层定义这个协议。比如定一个协议报文:
报文长度(4字节)+报文内容(变长)
使用报文长度这4字节表示报文内容的长度,这样,应用程序先接收4字节数据,就知道后续报文的长度了,然后再接收这么长的数据就OK了。
不管是字节流还是含有0x00的字符串,总之不能用strlen来取长度,用sizeof也不对(我见过很多初学者,一旦strlen的返回值不对了,就开始用sizeof,瞎蒙...),必须要根据实际情况正确地算法来取长度。一般来讲应用程序里出现含不可见字符(包括0x00)时,字符串的长度都应该是已知的,否则你怎么来对其进行操作啊,那就完全是程序设计者的问题了。
“所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息”是对的,比如VB6里的winsock控件,在接收到数据的时候,有两个有用的属性值bytestotal(接收的总字节数)和bytesreceived(已经接收到的字节数),通过这两个值就可以判断数据是否已经接收完。
如果底层协议无法返回收到的字节数,那么就要在应用一层定义这个协议。比如定一个协议报文:
报文长度(4字节)+报文内容(变长)
使用报文长度这4字节表示报文内容的长度,这样,应用程序先接收4字节数据,就知道后续报文的长度了,然后再接收这么长的数据就OK了。
不管是字节流还是含有0x00的字符串,总之不能用strlen来取长度,用sizeof也不对(我见过很多初学者,一旦strlen的返回值不对了,就开始用sizeof,瞎蒙...),必须要根据实际情况正确地算法来取长度。一般来讲应用程序里出现含不可见字符(包括0x00)时,字符串的长度都应该是已知的,否则你怎么来对其进行操作啊,那就完全是程序设计者的问题了。
#11
那么我获取的字节流 应该怎么保存起来 比较常用的方法是保存在什么对象里面呢?
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
#12
用二进制数组来进行处理。
#13
关注!
#14
网络传输或串口数据可以按照字节数组来处理
#15
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
#16
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
-----------------------------------------
什么叫“协议”?协议实际上就是发送方与接收方关于数据包格式,交换序列顺序等所有方面的共同约定。
如果你不知道该如何处理你收到的数据,对于定义良好的协议来讲(比如所有的标准协议),那是你还没有完全了解“协议/约定”的所有方方面面。如果你在处理http协议,建议你浏览一下http协议的内容。相信你在真正了解了这个协议之后,这个问题自然迎刃而解。
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
-----------------------------------------
什么叫“协议”?协议实际上就是发送方与接收方关于数据包格式,交换序列顺序等所有方面的共同约定。
如果你不知道该如何处理你收到的数据,对于定义良好的协议来讲(比如所有的标准协议),那是你还没有完全了解“协议/约定”的所有方方面面。如果你在处理http协议,建议你浏览一下http协议的内容。相信你在真正了解了这个协议之后,这个问题自然迎刃而解。
#17
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
这只是一个实际操作的问题了 和协议没有关系了
我已经知道对方要发多少字节给我 只是这个自己流中间可以有\x00
我应该如何处理? 当然我仍然可以建立一个字符串 不过外带长度参数的字符串
向外copy 的时候 按长度进行copy 但是如果想把这个想法移植到string 身上如何实现?
比如
string mm =("\xaa\xbb\x11\x00\xcc");
cout << mm.size();
长度应该是5 而不是现在的3
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
这只是一个实际操作的问题了 和协议没有关系了
我已经知道对方要发多少字节给我 只是这个自己流中间可以有\x00
我应该如何处理? 当然我仍然可以建立一个字符串 不过外带长度参数的字符串
向外copy 的时候 按长度进行copy 但是如果想把这个想法移植到string 身上如何实现?
比如
string mm =("\xaa\xbb\x11\x00\xcc");
cout << mm.size();
长度应该是5 而不是现在的3
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
#18
你用string只能保存256个字符。保存二进制流文件用char吧
#19
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"http 只能传合法的文本"的说法可能是有欠妥当,但这与“tcp/ip 没有对传输数据的内容有规定”又有什么关系呢?既然楼主已经仔细阅读过 tcp/ip 协议第一卷(楼主指的是《TCP/IP详解 第一卷:协议》吧),那么应该清楚HTTP、TCP、IP这3个协议之间的关系吧?也应该理解协议分层的概念吧?
楼主如此态度,让人颇感遗憾~~~~~~~
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"http 只能传合法的文本"的说法可能是有欠妥当,但这与“tcp/ip 没有对传输数据的内容有规定”又有什么关系呢?既然楼主已经仔细阅读过 tcp/ip 协议第一卷(楼主指的是《TCP/IP详解 第一卷:协议》吧),那么应该清楚HTTP、TCP、IP这3个协议之间的关系吧?也应该理解协议分层的概念吧?
楼主如此态度,让人颇感遗憾~~~~~~~
#20
http 只能传合法的文本, 这个说法本来就是错的。ip 包的内容包含的是什么没有规定
tcp 对传输的数据流内容也没有规定 http 对传输的内容也没有规定
我不明白我的态度 有什么不好。 我只是在请教 如何处理这个实际问题。就是数据流中含有\x00
因为这和字符串的结束符有冲突。我需要将他放入string 中,给别的函数操作。
楼上的一再强调协议,对实际问题的处理却没有实质性的指导。但是对我们这样的低手完全理解是有难度的。我们只能不断的遇见问题不断的解决问题。
没有理性的理解 合来感性的理解?
tcp 对传输的数据流内容也没有规定 http 对传输的内容也没有规定
我不明白我的态度 有什么不好。 我只是在请教 如何处理这个实际问题。就是数据流中含有\x00
因为这和字符串的结束符有冲突。我需要将他放入string 中,给别的函数操作。
楼上的一再强调协议,对实际问题的处理却没有实质性的指导。但是对我们这样的低手完全理解是有难度的。我们只能不断的遇见问题不断的解决问题。
没有理性的理解 合来感性的理解?
#21
不要用string, 定义一个字符数组(如char buf[4096])用于存放数据就可以了。
#22
用string 有很多好处啊 至少不用为长度犯愁 4096 肯定不够长的
#23
4096000够不够?呵呵,开个玩笑。大小可以根据实际情况定嘛。如果报文长度大小不确定,完全可以动态malloc嘛。
用char *的好处是,可以直接地址操作,如memcpy或使用&。string恐怕就没有这么方便了吧。
用char *的好处是,可以直接地址操作,如memcpy或使用&。string恐怕就没有这么方便了吧。
#24
楼主即然知道将要接收到的字节个数,可以在堆在分配一个已知大小的空间来存储,效率要比String的高.还是你想要String中提供的某些功能呢?
#25
刚问过一个朋友,用string也没有问题。
#26
>不要用string, 定义一个字符数组(如char buf[4096])用于存放数据就可以了。
unsighed char szBuff[LEN]
unsighed char szBuff[LEN]
#27
刚问过一个朋友,用string也没有问题。
how to ?
因为水平差 很多地方都是用string 要全部修改 量太大了
how to ?
因为水平差 很多地方都是用string 要全部修改 量太大了
#28
对着这样滴贴子,以及这样滴楼主,偶是见多了,更多还是学习不认真,既然楼上朋友都已经把问题说清楚了,而楼主去一味采用自己的所以然去理解,而不接受人家所讲述的“知识”那实在没有办法。偶对这样滴人也无能为力。
偶随便抓一贴给大家看看^_^
http://community.csdn.net/Expert/topic/4046/4046119.xml?temp=.739422
所以,偶对着如此滴楼主,只有两字“无语”!
偶随便抓一贴给大家看看^_^
http://community.csdn.net/Expert/topic/4046/4046119.xml?temp=.739422
所以,偶对着如此滴楼主,只有两字“无语”!
#29
因为很多地方都需要用string 所以我才要坚持用string
而且string 也并非不能插入 \x00 字符串 ( 我测试的结果)
例如 string aa ="aaaaaaaa";
cout << aa.size() << endl;
aa += "ddd";
cout << aa.size() << endl;
aa[5] = 0x00;
cout << aa.size() << endl;
for (int i =0 ; i < aa.size(); i++)
cout << (int) aa[i] << endl;
string 有很多字符数组所不具有的优点 在简洁 内存分配 效率上都强过你自己写的代码
至于态度问题 我感觉我没有过错 我感谢大家的帮助 但是对于你帮助中的错误
我仍然会指出 如果这就是所谓 态度不好 我真是无话可说
大家都是在讨论问题
而且string 也并非不能插入 \x00 字符串 ( 我测试的结果)
例如 string aa ="aaaaaaaa";
cout << aa.size() << endl;
aa += "ddd";
cout << aa.size() << endl;
aa[5] = 0x00;
cout << aa.size() << endl;
for (int i =0 ; i < aa.size(); i++)
cout << (int) aa[i] << endl;
string 有很多字符数组所不具有的优点 在简洁 内存分配 效率上都强过你自己写的代码
至于态度问题 我感觉我没有过错 我感谢大家的帮助 但是对于你帮助中的错误
我仍然会指出 如果这就是所谓 态度不好 我真是无话可说
大家都是在讨论问题
#30
mark
#31
接收->char[](把\x00转成\xcc, 呵呵)->string, 反之就反向操作, 不是都ok吗?
#32
\x00->\xcc \xcc 会和原来的\xcc 混在一起阿
当然 我想到 接受->base64 ->string那是可以的 但是代价好像太大了
当然 我想到 接受->base64 ->string那是可以的 但是代价好像太大了
#33
>刚问过一个朋友,用string也没有问题。
你所有解决问题的方案,都是基于这一基础之上吗?
你所有解决问题的方案,都是基于这一基础之上吗?
#34
如果真的想用,string可以容纳任何你需要的字符,只是这样子并不是string应该被使用的方法。
string的length并不是每次都遍历整个“字符串”得到的。
#include <string>
#include <iostream>
using std::string;
int main(int argc, char* argv[])
{
string str;
str = "heiheihei";
str = str + (char)0; // 在“字符串”插入0x00
str = str + "hohohoho";
std::cout << str.length() << std::endl; // length is 18
string str2(str.c_str(), str.length()); // 构造一个包含0x00的“字符串”
std::cout << str2.length() << std::endl; // length is 18
std::cin >> str;
return 0;
}
如果你真的需要,上面的两种方法可以满足你。
但是,如上面几个人(我看来都是好心)所说,你并不太懂得“协议”这个词的含义;而且这个地方实在不怎么适合用string。认真的补充一下这方面的知识,相信可以有更大的收获,而不仅仅是你现在的程序。多听多想多看才可以进步的比较快。
string的length并不是每次都遍历整个“字符串”得到的。
#include <string>
#include <iostream>
using std::string;
int main(int argc, char* argv[])
{
string str;
str = "heiheihei";
str = str + (char)0; // 在“字符串”插入0x00
str = str + "hohohoho";
std::cout << str.length() << std::endl; // length is 18
string str2(str.c_str(), str.length()); // 构造一个包含0x00的“字符串”
std::cout << str2.length() << std::endl; // length is 18
std::cin >> str;
return 0;
}
如果你真的需要,上面的两种方法可以满足你。
但是,如上面几个人(我看来都是好心)所说,你并不太懂得“协议”这个词的含义;而且这个地方实在不怎么适合用string。认真的补充一下这方面的知识,相信可以有更大的收获,而不仅仅是你现在的程序。多听多想多看才可以进步的比较快。
#35
btw: 最后的std::cin >> str仅仅是为了最后命令行在运行时不退出。习惯,呵呵。
#36
谢谢 黯然神伤)
你的代码基本能完成我的要求了
这里不用sting 的话 用什么比较好呢?
因为我从tcp 连接中读取字符流 然后从中分辨出命令 参数 或者是文件
我的想法是 tcp-> buff[] -> string
不同的函数对string 进行分析
因为string 带有find size 等参数 操作起来很方便
你的代码基本能完成我的要求了
这里不用sting 的话 用什么比较好呢?
因为我从tcp 连接中读取字符流 然后从中分辨出命令 参数 或者是文件
我的想法是 tcp-> buff[] -> string
不同的函数对string 进行分析
因为string 带有find size 等参数 操作起来很方便
#37
如果你的数据包不太大,在一个你的应用可以容忍大小的buffer里面能够放得下一个数据包,你可以直接在buffer上解析,得到其中任何你感兴趣的数据,比你用buffer的内容构造一个string,然后再用string解析要高效不少。
比如说:
class BufferReader
{
public:
BufferReader(unsigned char* buffer, unsigned int len);
int ReadInt(); // 从buffer中读取一个整数
short ReadShort();
string ReadString(int strlen); // 从buffer中读取固定长度的字符串
void SkipBytes(int len); // 跳过几个无用的字符
private:
unsigned char* pbuffer;
unsigned int currentPos;
unsigned int length;
}
当然这个仅仅是语法解析器,你还需要用它来构造自己的语义解析器。如果你的数据结构(字节流的结构)比较简单,也可以用几个函数代替,不用这个类。
如果一个buffer不能完全容纳一个数据包,需要别的方法。
等有空的时候把代码贴出来。
比如说:
class BufferReader
{
public:
BufferReader(unsigned char* buffer, unsigned int len);
int ReadInt(); // 从buffer中读取一个整数
short ReadShort();
string ReadString(int strlen); // 从buffer中读取固定长度的字符串
void SkipBytes(int len); // 跳过几个无用的字符
private:
unsigned char* pbuffer;
unsigned int currentPos;
unsigned int length;
}
当然这个仅仅是语法解析器,你还需要用它来构造自己的语义解析器。如果你的数据结构(字节流的结构)比较简单,也可以用几个函数代替,不用这个类。
如果一个buffer不能完全容纳一个数据包,需要别的方法。
等有空的时候把代码贴出来。
#38
谢谢
因为要支持http 协议 和 其他的2个协议 所以传来的文件大小未知 buff[] 无法保证一定能包含整个命令
所以才这么做的
因为要支持http 协议 和 其他的2个协议 所以传来的文件大小未知 buff[] 无法保证一定能包含整个命令
所以才这么做的
#39
一般来说,不能用字符串来处理二进制文件。只有一些很特殊的场合除外。
你应该按照这个二进制文件内容的特点,用字节、字节流、数值型等来处理。
你应该按照这个二进制文件内容的特点,用字节、字节流、数值型等来处理。
#1
不要用字符串处理
当作普通的整形数来处理
当作普通的整形数来处理
#2
拿我存取的时候怎么办? 一个个整数的往外取?
整数是4字节 有可能取不到4字节
普通的ftp 客户端怎么做呢?
取到了传来的数据放在 一个缓存块以后
因为有\x00 它如何确定缓存块的实际长度?
整数是4字节 有可能取不到4字节
普通的ftp 客户端怎么做呢?
取到了传来的数据放在 一个缓存块以后
因为有\x00 它如何确定缓存块的实际长度?
#3
memcpy
#4
对于缓冲区的实际大小问题,如果当中可能传递'\0',那么除非wchar_t *,或者数据整体本身并非单一个字符串,在这种情况下若是参数,通常需要带入数据长度。
#5
改写string类就行了吧,重新写个char_traits类,按你的要求进行操作,替换掉原来那个就行了~
#6
shellcode里面有一种解决方法~~~
把所有的code都 与 一个高的数 for example: \x99 then unencode
把所有的code都 与 一个高的数 for example: \x99 then unencode
#7
对于缓冲区的实际大小问题,如果当中可能传递'\0',那么除非wchar_t *,或者数据整体本身并非单一个字符串,在这种情况下若是参数,通常需要带入数据长度。
我并不知道要传来的数据的长度。我需要检测数据内容 才知道是否内容结束
我并不知道要传来的数据的长度。我需要检测数据内容 才知道是否内容结束
#8
对于这种情况,不要用strcpy,string这些东东,用memcpy函数。网络传输中包的长度是包含在包中的。
#9
你说得问题基本上无法解决的。
所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息。如果你使用的协议无法提供这个信息,或者是协议设计缺陷,或者你还没有完全理解这个协议。
另外,你的话实际上是个病语“传给你一个含有\x00 的字符串”:在C里面字符串是如何定义的呢?准确地讲,他传给你的是“字节流”,而不是字符串。
所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息。如果你使用的协议无法提供这个信息,或者是协议设计缺陷,或者你还没有完全理解这个协议。
另外,你的话实际上是个病语“传给你一个含有\x00 的字符串”:在C里面字符串是如何定义的呢?准确地讲,他传给你的是“字节流”,而不是字符串。
#10
boxban(冻酸梨) ( ) 说的不错。
“所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息”是对的,比如VB6里的winsock控件,在接收到数据的时候,有两个有用的属性值bytestotal(接收的总字节数)和bytesreceived(已经接收到的字节数),通过这两个值就可以判断数据是否已经接收完。
如果底层协议无法返回收到的字节数,那么就要在应用一层定义这个协议。比如定一个协议报文:
报文长度(4字节)+报文内容(变长)
使用报文长度这4字节表示报文内容的长度,这样,应用程序先接收4字节数据,就知道后续报文的长度了,然后再接收这么长的数据就OK了。
不管是字节流还是含有0x00的字符串,总之不能用strlen来取长度,用sizeof也不对(我见过很多初学者,一旦strlen的返回值不对了,就开始用sizeof,瞎蒙...),必须要根据实际情况正确地算法来取长度。一般来讲应用程序里出现含不可见字符(包括0x00)时,字符串的长度都应该是已知的,否则你怎么来对其进行操作啊,那就完全是程序设计者的问题了。
“所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息”是对的,比如VB6里的winsock控件,在接收到数据的时候,有两个有用的属性值bytestotal(接收的总字节数)和bytesreceived(已经接收到的字节数),通过这两个值就可以判断数据是否已经接收完。
如果底层协议无法返回收到的字节数,那么就要在应用一层定义这个协议。比如定一个协议报文:
报文长度(4字节)+报文内容(变长)
使用报文长度这4字节表示报文内容的长度,这样,应用程序先接收4字节数据,就知道后续报文的长度了,然后再接收这么长的数据就OK了。
不管是字节流还是含有0x00的字符串,总之不能用strlen来取长度,用sizeof也不对(我见过很多初学者,一旦strlen的返回值不对了,就开始用sizeof,瞎蒙...),必须要根据实际情况正确地算法来取长度。一般来讲应用程序里出现含不可见字符(包括0x00)时,字符串的长度都应该是已知的,否则你怎么来对其进行操作啊,那就完全是程序设计者的问题了。
#11
那么我获取的字节流 应该怎么保存起来 比较常用的方法是保存在什么对象里面呢?
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
#12
用二进制数组来进行处理。
#13
关注!
#14
网络传输或串口数据可以按照字节数组来处理
#15
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
#16
比如一个http 连接
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
-----------------------------------------
什么叫“协议”?协议实际上就是发送方与接收方关于数据包格式,交换序列顺序等所有方面的共同约定。
如果你不知道该如何处理你收到的数据,对于定义良好的协议来讲(比如所有的标准协议),那是你还没有完全了解“协议/约定”的所有方方面面。如果你在处理http协议,建议你浏览一下http协议的内容。相信你在真正了解了这个协议之后,这个问题自然迎刃而解。
我从http head 的context length 参数部分 取得长度
然后获取后面那么多字节 我应该存放在什么地方
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
-----------------------------------------
什么叫“协议”?协议实际上就是发送方与接收方关于数据包格式,交换序列顺序等所有方面的共同约定。
如果你不知道该如何处理你收到的数据,对于定义良好的协议来讲(比如所有的标准协议),那是你还没有完全了解“协议/约定”的所有方方面面。如果你在处理http协议,建议你浏览一下http协议的内容。相信你在真正了解了这个协议之后,这个问题自然迎刃而解。
#17
如果没有\x00 那么字符串是个很简单的应用
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
这只是一个实际操作的问题了 和协议没有关系了
我已经知道对方要发多少字节给我 只是这个自己流中间可以有\x00
我应该如何处理? 当然我仍然可以建立一个字符串 不过外带长度参数的字符串
向外copy 的时候 按长度进行copy 但是如果想把这个想法移植到string 身上如何实现?
比如
string mm =("\xaa\xbb\x11\x00\xcc");
cout << mm.size();
长度应该是5 而不是现在的3
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
这只是一个实际操作的问题了 和协议没有关系了
我已经知道对方要发多少字节给我 只是这个自己流中间可以有\x00
我应该如何处理? 当然我仍然可以建立一个字符串 不过外带长度参数的字符串
向外copy 的时候 按长度进行copy 但是如果想把这个想法移植到string 身上如何实现?
比如
string mm =("\xaa\xbb\x11\x00\xcc");
cout << mm.size();
长度应该是5 而不是现在的3
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
#18
你用string只能保存256个字符。保存二进制流文件用char吧
#19
http 只能传合法的文本。所谓合法就是其中不能出现'\0'还有其它的一些控制字符。那么二进制数据怎么办?其实很简单阿,把二进制数据转换成文本流再传输。这个有很多的方案。好像http 使用的是base.64
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"http 只能传合法的文本"的说法可能是有欠妥当,但这与“tcp/ip 没有对传输数据的内容有规定”又有什么关系呢?既然楼主已经仔细阅读过 tcp/ip 协议第一卷(楼主指的是《TCP/IP详解 第一卷:协议》吧),那么应该清楚HTTP、TCP、IP这3个协议之间的关系吧?也应该理解协议分层的概念吧?
楼主如此态度,让人颇感遗憾~~~~~~~
这种说法是错误的。 如果你打开一个抓包软件 使用flashget 下载一个网站上的gif 图片你就可以看见在字符流 中间的有\x00 的 因为gif 文件本身就有. 如果你仔细读 tcp/ip 协议第一卷 就会知道tcp/ip 没有对传输数据的内容有规定 。哪怕你全部传\x00 也可以
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"http 只能传合法的文本"的说法可能是有欠妥当,但这与“tcp/ip 没有对传输数据的内容有规定”又有什么关系呢?既然楼主已经仔细阅读过 tcp/ip 协议第一卷(楼主指的是《TCP/IP详解 第一卷:协议》吧),那么应该清楚HTTP、TCP、IP这3个协议之间的关系吧?也应该理解协议分层的概念吧?
楼主如此态度,让人颇感遗憾~~~~~~~
#20
http 只能传合法的文本, 这个说法本来就是错的。ip 包的内容包含的是什么没有规定
tcp 对传输的数据流内容也没有规定 http 对传输的内容也没有规定
我不明白我的态度 有什么不好。 我只是在请教 如何处理这个实际问题。就是数据流中含有\x00
因为这和字符串的结束符有冲突。我需要将他放入string 中,给别的函数操作。
楼上的一再强调协议,对实际问题的处理却没有实质性的指导。但是对我们这样的低手完全理解是有难度的。我们只能不断的遇见问题不断的解决问题。
没有理性的理解 合来感性的理解?
tcp 对传输的数据流内容也没有规定 http 对传输的内容也没有规定
我不明白我的态度 有什么不好。 我只是在请教 如何处理这个实际问题。就是数据流中含有\x00
因为这和字符串的结束符有冲突。我需要将他放入string 中,给别的函数操作。
楼上的一再强调协议,对实际问题的处理却没有实质性的指导。但是对我们这样的低手完全理解是有难度的。我们只能不断的遇见问题不断的解决问题。
没有理性的理解 合来感性的理解?
#21
不要用string, 定义一个字符数组(如char buf[4096])用于存放数据就可以了。
#22
用string 有很多好处啊 至少不用为长度犯愁 4096 肯定不够长的
#23
4096000够不够?呵呵,开个玩笑。大小可以根据实际情况定嘛。如果报文长度大小不确定,完全可以动态malloc嘛。
用char *的好处是,可以直接地址操作,如memcpy或使用&。string恐怕就没有这么方便了吧。
用char *的好处是,可以直接地址操作,如memcpy或使用&。string恐怕就没有这么方便了吧。
#24
楼主即然知道将要接收到的字节个数,可以在堆在分配一个已知大小的空间来存储,效率要比String的高.还是你想要String中提供的某些功能呢?
#25
刚问过一个朋友,用string也没有问题。
#26
>不要用string, 定义一个字符数组(如char buf[4096])用于存放数据就可以了。
unsighed char szBuff[LEN]
unsighed char szBuff[LEN]
#27
刚问过一个朋友,用string也没有问题。
how to ?
因为水平差 很多地方都是用string 要全部修改 量太大了
how to ?
因为水平差 很多地方都是用string 要全部修改 量太大了
#28
对着这样滴贴子,以及这样滴楼主,偶是见多了,更多还是学习不认真,既然楼上朋友都已经把问题说清楚了,而楼主去一味采用自己的所以然去理解,而不接受人家所讲述的“知识”那实在没有办法。偶对这样滴人也无能为力。
偶随便抓一贴给大家看看^_^
http://community.csdn.net/Expert/topic/4046/4046119.xml?temp=.739422
所以,偶对着如此滴楼主,只有两字“无语”!
偶随便抓一贴给大家看看^_^
http://community.csdn.net/Expert/topic/4046/4046119.xml?temp=.739422
所以,偶对着如此滴楼主,只有两字“无语”!
#29
因为很多地方都需要用string 所以我才要坚持用string
而且string 也并非不能插入 \x00 字符串 ( 我测试的结果)
例如 string aa ="aaaaaaaa";
cout << aa.size() << endl;
aa += "ddd";
cout << aa.size() << endl;
aa[5] = 0x00;
cout << aa.size() << endl;
for (int i =0 ; i < aa.size(); i++)
cout << (int) aa[i] << endl;
string 有很多字符数组所不具有的优点 在简洁 内存分配 效率上都强过你自己写的代码
至于态度问题 我感觉我没有过错 我感谢大家的帮助 但是对于你帮助中的错误
我仍然会指出 如果这就是所谓 态度不好 我真是无话可说
大家都是在讨论问题
而且string 也并非不能插入 \x00 字符串 ( 我测试的结果)
例如 string aa ="aaaaaaaa";
cout << aa.size() << endl;
aa += "ddd";
cout << aa.size() << endl;
aa[5] = 0x00;
cout << aa.size() << endl;
for (int i =0 ; i < aa.size(); i++)
cout << (int) aa[i] << endl;
string 有很多字符数组所不具有的优点 在简洁 内存分配 效率上都强过你自己写的代码
至于态度问题 我感觉我没有过错 我感谢大家的帮助 但是对于你帮助中的错误
我仍然会指出 如果这就是所谓 态度不好 我真是无话可说
大家都是在讨论问题
#30
mark
#31
接收->char[](把\x00转成\xcc, 呵呵)->string, 反之就反向操作, 不是都ok吗?
#32
\x00->\xcc \xcc 会和原来的\xcc 混在一起阿
当然 我想到 接受->base64 ->string那是可以的 但是代价好像太大了
当然 我想到 接受->base64 ->string那是可以的 但是代价好像太大了
#33
>刚问过一个朋友,用string也没有问题。
你所有解决问题的方案,都是基于这一基础之上吗?
你所有解决问题的方案,都是基于这一基础之上吗?
#34
如果真的想用,string可以容纳任何你需要的字符,只是这样子并不是string应该被使用的方法。
string的length并不是每次都遍历整个“字符串”得到的。
#include <string>
#include <iostream>
using std::string;
int main(int argc, char* argv[])
{
string str;
str = "heiheihei";
str = str + (char)0; // 在“字符串”插入0x00
str = str + "hohohoho";
std::cout << str.length() << std::endl; // length is 18
string str2(str.c_str(), str.length()); // 构造一个包含0x00的“字符串”
std::cout << str2.length() << std::endl; // length is 18
std::cin >> str;
return 0;
}
如果你真的需要,上面的两种方法可以满足你。
但是,如上面几个人(我看来都是好心)所说,你并不太懂得“协议”这个词的含义;而且这个地方实在不怎么适合用string。认真的补充一下这方面的知识,相信可以有更大的收获,而不仅仅是你现在的程序。多听多想多看才可以进步的比较快。
string的length并不是每次都遍历整个“字符串”得到的。
#include <string>
#include <iostream>
using std::string;
int main(int argc, char* argv[])
{
string str;
str = "heiheihei";
str = str + (char)0; // 在“字符串”插入0x00
str = str + "hohohoho";
std::cout << str.length() << std::endl; // length is 18
string str2(str.c_str(), str.length()); // 构造一个包含0x00的“字符串”
std::cout << str2.length() << std::endl; // length is 18
std::cin >> str;
return 0;
}
如果你真的需要,上面的两种方法可以满足你。
但是,如上面几个人(我看来都是好心)所说,你并不太懂得“协议”这个词的含义;而且这个地方实在不怎么适合用string。认真的补充一下这方面的知识,相信可以有更大的收获,而不仅仅是你现在的程序。多听多想多看才可以进步的比较快。
#35
btw: 最后的std::cin >> str仅仅是为了最后命令行在运行时不退出。习惯,呵呵。
#36
谢谢 黯然神伤)
你的代码基本能完成我的要求了
这里不用sting 的话 用什么比较好呢?
因为我从tcp 连接中读取字符流 然后从中分辨出命令 参数 或者是文件
我的想法是 tcp-> buff[] -> string
不同的函数对string 进行分析
因为string 带有find size 等参数 操作起来很方便
你的代码基本能完成我的要求了
这里不用sting 的话 用什么比较好呢?
因为我从tcp 连接中读取字符流 然后从中分辨出命令 参数 或者是文件
我的想法是 tcp-> buff[] -> string
不同的函数对string 进行分析
因为string 带有find size 等参数 操作起来很方便
#37
如果你的数据包不太大,在一个你的应用可以容忍大小的buffer里面能够放得下一个数据包,你可以直接在buffer上解析,得到其中任何你感兴趣的数据,比你用buffer的内容构造一个string,然后再用string解析要高效不少。
比如说:
class BufferReader
{
public:
BufferReader(unsigned char* buffer, unsigned int len);
int ReadInt(); // 从buffer中读取一个整数
short ReadShort();
string ReadString(int strlen); // 从buffer中读取固定长度的字符串
void SkipBytes(int len); // 跳过几个无用的字符
private:
unsigned char* pbuffer;
unsigned int currentPos;
unsigned int length;
}
当然这个仅仅是语法解析器,你还需要用它来构造自己的语义解析器。如果你的数据结构(字节流的结构)比较简单,也可以用几个函数代替,不用这个类。
如果一个buffer不能完全容纳一个数据包,需要别的方法。
等有空的时候把代码贴出来。
比如说:
class BufferReader
{
public:
BufferReader(unsigned char* buffer, unsigned int len);
int ReadInt(); // 从buffer中读取一个整数
short ReadShort();
string ReadString(int strlen); // 从buffer中读取固定长度的字符串
void SkipBytes(int len); // 跳过几个无用的字符
private:
unsigned char* pbuffer;
unsigned int currentPos;
unsigned int length;
}
当然这个仅仅是语法解析器,你还需要用它来构造自己的语义解析器。如果你的数据结构(字节流的结构)比较简单,也可以用几个函数代替,不用这个类。
如果一个buffer不能完全容纳一个数据包,需要别的方法。
等有空的时候把代码贴出来。
#38
谢谢
因为要支持http 协议 和 其他的2个协议 所以传来的文件大小未知 buff[] 无法保证一定能包含整个命令
所以才这么做的
因为要支持http 协议 和 其他的2个协议 所以传来的文件大小未知 buff[] 无法保证一定能包含整个命令
所以才这么做的
#39
一般来说,不能用字符串来处理二进制文件。只有一些很特殊的场合除外。
你应该按照这个二进制文件内容的特点,用字节、字节流、数值型等来处理。
你应该按照这个二进制文件内容的特点,用字节、字节流、数值型等来处理。