【问题标题】:HTTP request, strange socket behaviourHTTP 请求,奇怪的套接字行为
【发布时间】:2011-02-02 08:45:24
【问题描述】:

我在通过套接字执行 HTTP 请求时遇到了奇怪的行为,这里是请求:

POST https://example.com:443/service/XMLSelect HTTP/1.1
Content-Length: 10926
Host: example.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)
Authorization: Basic XXX
SOAPAction: http://example.com/SubmitXml

稍后会出现我的请求正文,其中包含给定的内容长度。 之后我收到类似的东西:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Tue, 30 Mar 2010 06:13:52 GMT

所以这里似乎一切都很好。我从网络流中读取了所有内容并成功接收到响应。但是我正在对开关进行轮询的套接字是这样的模式:

write ( i write headers and request here )
read ( after headers sent i begin to receive response )
write ( STRANGE BEHAVIOUR HERE. WHY? here i send nothing really )
read ( here it switches to read back again )

最后两步可以重复多次。所以我想问一下socket的模式改变是什么导致的?在这种情况下,这不是一个大问题,但是当我在我的请求中使用 gzip 压缩(不知道它是如何相关的)并要求服务器像这样向我发送 gzip 响应时:

POST https://example.com:443/service/XMLSelect HTTP/1.1
Content-Length: 1076
Accept-Encoding: gzip
Content-Encoding: gzip
Host: example.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)
Authorization: Basic XXX
SOAPAction: http://example.com/SubmitXml

我收到这样的回复:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Encoding: gzip
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Tue, 30 Mar 2010 07:26:33 GMT

2000
�

我收到一个块大小和 GZIP 标头,一切正常。这就是我可怜的小插座同时发生的事情:

write ( i write headers and request here )
read ( after headers sent i begin to receive response )
write ( STRANGE BEHAVIOUR HERE. And it finally sits here forever waiting for me to send something! But if i refer to HTTP I don't have to send anything more! )

它与什么有关?它要我发送什么?是远程 Web 服务器的问题还是我遗漏了什么?

PS 所有实际的服务参考和登录名/密码都替换为假的:)

【问题讨论】:

  • 小点,但示例 URL 应使用 RFC2606 保留域之一 [rfc-editor.org/rfc/rfc2606.txt] 例如 example.com - 如果有人复制/粘贴示例,保证永远不会指向活动域在任何可以做任何事情的地方编写代码
  • Ops,对不起,替换为正确的 :) 我的问题呢?

标签: http sockets gzip


【解决方案1】:

只要套接字发送缓冲区中有空间,套接字就变为可写。操作系统无法真正知道您的应用程序是否有更多数据要发送,但知道其内部结构,例如套接字缓冲区。您必须显式添加/删除套接字以写入fd_set for select(2)(启用/禁用EPOLLOUT 事件epoll(4))。这通常由 状态机 处理,例如 libevent。轮询也最适合 非阻塞 套接字。

希望这会有所帮助。

【讨论】:

  • 谢谢你! =) 我实际上想出了关于缓冲的事情,但很高兴在这里见到专家!
  • 如果我有什么问题可以联系你吗? :)
  • 我正在 c# 上编写我的解决方案并使用阻塞套接字,但从缓冲区循环读取循环中的套接字。我想这不是最好的解决方案,但如果与使用线程的异步调用相比,它仍然显示出出色的性能。我可以在一个线程中处理 500 个套接字,而在循环时间上没有宝贵的开销。而且我的处理器平均只有 10% 的负载感觉很好:) 我很想直接从套接字发送/接收,但我不想自己实现 SSL 东西,我使用 SSLStream。如果您有任何建议,我很乐意听到!
  • 嘿,这是一个非常好的开始!在多套接字设置中,线程经常被高估,并产生更多它们应该解决的问题。如果您有任何问题 - 请发布!每天都有更多的专家在这里。我通常关注c/c++/sockets/etc。标签。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多