前天有同学在玩erlang gen_tcp的时候碰到了点小麻烦,描述如下:
比如说连接到baidu.com,发个http请求,然后马上接收数据,发现接收出错,wireshark抓包发现数据都有往返发送,比较郁闷。
我把问题演示下:
Erlang R14B03 (erts-5.8.4) 1 [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll: false ] |
Eshell V5.8.4 (abort with ^G) |
1> {ok,Sock} = gen_tcp:connect( "baidu.com" , 80, []). |
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n" ). |
这个问题的根源在于gen_tcp默认的{active,true},也就是说当gen_tcp收到网络包的时候,默认是把报文发送给它的宿主进程。而gen_tcp:recv是用户主动去拉数据,这二个模式是互斥的。
我们来看下代码otp/erts/emulator/drivers/common/inet_drv.c:7462
if (desc->inet.active || (len != 8)) |
return ctl_error(EINVAL, rbuf, rsize); |
那就解释为什么 gen_tcp:recv(Sock,0)返回错误码{error,einval}。
同时我们来验证下,报文是以消息的方式发送的。
"HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 03:51:25 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>400 Bad Request</TITLE>\n</HEAD><BODY>\n<H1>Bad Request</H1>\nYour browser sent a request that this server could not understand.<P>\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>\n</BODY></HTML>\n\r\n0\r\n\r\n" } |
搞清楚了问题,那解决方案很简单,connect的时候把active模式设成{active,false}.
再来演示下:
Erlang R14B03 (erts-5.8.4) 1 [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll: false ] |
Eshell V5.8.4 (abort with ^G) |
1> {ok,Sock} = gen_tcp:connect( "baidu.com" , 80, [{active, false }]). |
2> gen_tcp:send(Sock, "GET / HTTP/1.1\r\n\r\n" ). |
{ok, "HTTP/1.1 400 Bad Request\r\nDate: Fri, 01 Jul 2011 05:25:15 GMT\r\nServer: Apache\r\nConnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n127\r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>400 Bad Request</TITLE>\n</HEAD><BODY>\n<H1>Bad Request</H1>\nYour browser sent a request that this server could not understand.<P>\nclient sent HTTP/1.1 request without hostname (see RFC2616 section 14.23): /<P>\n</BODY></HTML>\n\r\n0\r\n\r\n" } |
搞定!
玩得开心!
建议继续学习:
- gen_tcp发送进程被挂起起因分析及对策 (阅读:36971)
- gen_tcp发送缓冲区以及水位线问题分析 (阅读:5220)
- whatsapp深度使用Erlang有感 (阅读:4568)
- Erlang match_spec引擎介绍和应用 (阅读:4527)
- php-erlang (阅读:4308)
- gen_tcp调用进程收到{empty_out_q, Port}消息奇怪行为分析 (阅读:3541)
- hibernate使用注意事项 (阅读:3218)
- Erlang linkin driver用port_control方式时的一些经验分享 (阅读:2965)
- Erlang如何限制节点对集群的访问之net_kernel:allow (阅读:2971)
- ERLANG OTP源码分析 – gen_server (阅读:2856)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习