user-0 提问: 自定义的http协议，怎样读取body? 

回复:
user: user-0
content: 引用 20 楼 zhuyf87 的回复:[quote=引用 19 楼 baidu_24733621 的回复:] [quote=引用 17 楼 zhuyf87 的回复:] [quote=引用 14 楼 baidu_24733621 的回复:] [quote=引用 13 楼 zhuyf87 的回复:] [quote=引用 11 楼 baidu_24733621 的回复:] [quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗[/quote]  既然不固定，。那么只有一个办法读取头， 一个个字节recv。  但是这样效率很低。 [/quote]  呃，为什么要一个一个字节的recv呢？一个线程负责将协议数据读取到一个缓冲队列中，另一个线程将缓冲队列中的数据copy出来，遍历解析，正确解析一包之后，就从缓冲队列中删除一包数据。[/quote]  以前说了， 头的大小不固定，你怎么知道， 几个字节是一个完整的头呢？   请认真看问题。  我不知道其他开源库是怎么处理的？   标准http 的头，确实是不固定的， [/quote]  不是头有多大，就必须一次recv多大。而是只要有数据就读到buffer里，然后处理线程从buffer中取数据解析。 读到特殊标记，比如\r\n\r\n时，则读完了一个完整的Head。 我认真看问题了，其实我和7楼的想法是一样的，我觉得你认为的： “既然不固定。那么只有一个办法读取头， 一个个字节recv。” 是不对的。 [/quote]  赞同  接受线程，每次接受几k大小的包，然后放到buffer中，接受线程只管接受，不关协议内容。  处理线程去处理包里的东西。 谢谢

user: user-1
content: 引用 17 楼 zhuyf87 的回复:[quote=引用 14 楼 baidu_24733621 的回复:] [quote=引用 13 楼 zhuyf87 的回复:] [quote=引用 11 楼 baidu_24733621 的回复:] [quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗[/quote]  既然不固定，。那么只有一个办法读取头， 一个个字节recv。  但是这样效率很低。 [/quote]  呃，为什么要一个一个字节的recv呢？一个线程负责将协议数据读取到一个缓冲队列中，另一个线程将缓冲队列中的数据copy出来，遍历解析，正确解析一包之后，就从缓冲队列中删除一包数据。[/quote]  以前说了， 头的大小不固定，你怎么知道， 几个字节是一个完整的头呢？   请认真看问题。  我不知道其他开源库是怎么处理的？   标准http 的头，确实是不固定的，

user: user-2
content: 根据自己项目需求，采用相应的方法，没有那种方法绝对的适合所有应用

user: user-3
content: 引用 14 楼 baidu_24733621 的回复:[quote=引用 13 楼 zhuyf87 的回复:] [quote=引用 11 楼 baidu_24733621 的回复:] [quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗[/quote]  既然不固定，。那么只有一个办法读取头， 一个个字节recv。  但是这样效率很低。 [/quote]  呃，为什么要一个一个字节的recv呢？一个线程负责将协议数据读取到一个缓冲队列中，另一个线程将缓冲队列中的数据copy出来，遍历解析，正确解析一包之后，就从缓冲队列中删除一包数据。

user: user-3
content: 引用 19 楼 baidu_24733621 的回复:[quote=引用 17 楼 zhuyf87 的回复:] [quote=引用 14 楼 baidu_24733621 的回复:] [quote=引用 13 楼 zhuyf87 的回复:] [quote=引用 11 楼 baidu_24733621 的回复:] [quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗[/quote]  既然不固定，。那么只有一个办法读取头， 一个个字节recv。  但是这样效率很低。 [/quote]  呃，为什么要一个一个字节的recv呢？一个线程负责将协议数据读取到一个缓冲队列中，另一个线程将缓冲队列中的数据copy出来，遍历解析，正确解析一包之后，就从缓冲队列中删除一包数据。[/quote]  以前说了， 头的大小不固定，你怎么知道， 几个字节是一个完整的头呢？   请认真看问题。  我不知道其他开源库是怎么处理的？   标准http 的头，确实是不固定的， [/quote]  不是头有多大，就必须一次recv多大。而是只要有数据就读到buffer里，然后处理线程从buffer中取数据解析。 读到特殊标记，比如\r\n\r\n时，则读完了一个完整的Head。 我认真看问题了，其实我和7楼的想法是一样的，我觉得你认为的： “既然不固定。那么只有一个办法读取头， 一个个字节recv。” 是不对的。

user: user-4
content: 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

user: user-4
content: 无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

user: user-1
content: 引用 13 楼 zhuyf87 的回复:[quote=引用 11 楼 baidu_24733621 的回复:] [quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗[/quote]  既然不固定，。那么只有一个办法读取头， 一个个字节recv。  但是这样效率很低。

user: user-3
content: 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。

user: user-5
content: 引用 2 楼 u012879787 的回复:[quote=引用 1 楼 starytx 的回复:] 固定长度不行吗？或者说协议设置成前四个字节保存head的长度，先读取到这个信息，然后根据这个读取对应长度的信息  开源库是如何处理的？  自定义http协议，感觉头+体里的东西都是按照标准http协议走的，  标准 http的头里没有头大小这个东西。  你的方法不对吧 [/quote]我没研究过http协议，只是针对lz说的“自定义”来说可以这样，如果要和标准依附那就要遵循标准，而不是自定义了

user: user-3
content: 要么加len字段，要么加标记。

user: user-6
content: 引用 6 楼 bsnry 的回复:[quote=引用 5 楼 luciferisnotsatan 的回复:] [quote=引用 2 楼 u012879787 的回复:] [quote=引用 1 楼 starytx 的回复:] 固定长度不行吗？或者说协议设置成前四个字节保存head的长度，先读取到这个信息，然后根据这个读取对应长度的信息  开源库是如何处理的？  自定义http协议，感觉头+体里的东西都是按照标准http协议走的，  标准 http的头里没有头大小这个东西。  你的方法不对吧 [/quote] 标准http头是以两个连续的“\r\n”结尾的。 如果你不按标准，要自己定义一套，那么就要你自己想怎么算结束了[/quote]  两个\r\n， 那么如何读取head, 每次读取一个字符来判断头是否结束，不觉得效率太低了吗  [/quote] 你不会socket一次接收一大段数据到内存buffer里，然后再去判断这段buffer里有没有连续的\r\n。干嘛要一个字节一个字节recv  同时，CPU解析这么段http文本的所需时间相对于网络传输的时间来说可以忽略不计的。

user: user-0
content: 引用 5 楼 luciferisnotsatan 的回复:[quote=引用 2 楼 u012879787 的回复:] [quote=引用 1 楼 starytx 的回复:] 固定长度不行吗？或者说协议设置成前四个字节保存head的长度，先读取到这个信息，然后根据这个读取对应长度的信息  开源库是如何处理的？  自定义http协议，感觉头+体里的东西都是按照标准http协议走的，  标准 http的头里没有头大小这个东西。  你的方法不对吧 [/quote] 标准http头是以两个连续的“\r\n”结尾的。 如果你不按标准，要自己定义一套，那么就要你自己想怎么算结束了[/quote]  两个\r\n， 那么如何读取head, 每次读取一个字符来判断头是否结束，不觉得效率太低了吗

user: user-6
content: 引用 2 楼 u012879787 的回复:[quote=引用 1 楼 starytx 的回复:] 固定长度不行吗？或者说协议设置成前四个字节保存head的长度，先读取到这个信息，然后根据这个读取对应长度的信息  开源库是如何处理的？  自定义http协议，感觉头+体里的东西都是按照标准http协议走的，  标准 http的头里没有头大小这个东西。  你的方法不对吧 [/quote] 标准http头是以两个连续的“\r\n”结尾的。 如果你不按标准，要自己定义一套，那么就要你自己想怎么算结束了

user: user-3
content: 引用 11 楼 baidu_24733621 的回复:[quote=引用 10 楼 zhuyf87 的回复:] 加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。 [/quote]  当然是不固定的，这有什么关系吗

user: user-7
content: 协议栈一般是这么实现（大概思路）： 1. 查找两个 "\r\n" 以确定头结束 2. 因为是 TCP，没找到则需要缓存数据等待后续数据到达（新数据到达开始 1） 3. 找到了就知道 Header 在哪里结束，对 Header 部分查找 "\r\n"（处理每一行） 4. 对每一行数据查找 ":" 分割，前面的部分匹配头域关键字，按照不同的头来处理 ":"  之后的内容 5. 获得 Content-Length 头，检查 Body 的数据是否已收全（Header 结束的位置至数据的尾部） 6. 如果没有收全，需要等待 Body 的后续数据，因此缓存已处理内容（新数据到达开始 5） 7. 按照 Body 的类型，解析 Body 8. 仍有剩余数据（已收取数据减去 Header 和 Body 的长度）需要开始下一个报文的解析（因为是 TCP），继续 1

user: user-1
content: 引用 10 楼 zhuyf87 的回复:加标记不会降低效率，本来http头里面的各个字段也需要遍历一遍才能解析出来。  标准http的头的大小不固定。

user: user-8
content: 请参考nginx的HTTP协议解码部分。

user: user-9
content: 加一个 字段标注   head多大

user: user-10
content: 引用 1 楼 starytx 的回复:固定长度不行吗？或者说协议设置成前四个字节保存head的长度，先读取到这个信息，然后根据这个读取对应长度的信息  开源库是如何处理的？  自定义http协议，感觉头+体里的东西都是按照标准http协议走的，  标准 http的头里没有头大小这个东西。  你的方法不对吧