概述
前天有同学在玩erlang gen_tcp的时候碰到了点小麻烦,描述如下:
比如说连接到baidu.com,发个http请求,然后马上接收数据,发现接收出错,wireshark抓包发现数据都有往返发送,比较郁闷。
我把问题演示下:
$ erl 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, []). {ok,#Port<0.582>} 2> gen_tcp:send(Sock, "GET / HTTP/1.1rnrn"). ok 3> gen_tcp:recv(Sock,0). {error,einval}
这个问题的根源在于gen_tcp默认的{active,true},也就是说当gen_tcp收到网络包的时候,默认是把报文发送给它的宿主进程。而gen_tcp:recv是用户主动去拉数据,这二个模式是互斥的。
我们来看下代码otp/erts/emulator/drivers/common/inet_drv.c:7462
case TCP_REQ_RECV: {
..
if (desc->inet.active || (len != 8))
return ctl_error(EINVAL, rbuf, rsize);
..
那就解释为什么 gen_tcp:recv(Sock,0)返回错误码{error,einval}。
同时我们来验证下,报文是以消息的方式发送的。
4> flush(). Shell got {tcp,#Port<0.582>, "HTTP/1.1 400 Bad RequestrnDate: Fri, 01 Jul 2011 03:51:25 GMTrnServer: ApachernConnection: Keep-AlivernTransfer-Encoding: chunkedrnContent-Type: text/html; charset=iso-8859-1rnrn127rn<!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>nrn0rnrn"} ok 5>
搞清楚了问题,那解决方案很简单,connect的时候把active模式设成{active,false}.
再来演示下:
$ erl 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}]). {ok,#Port<0.582>} 2> gen_tcp:send(Sock, "GET / HTTP/1.1rnrn"). ok 3> gen_tcp:recv(Sock,0). {ok,"HTTP/1.1 400 Bad RequestrnDate: Fri, 01 Jul 2011 05:25:15 GMTrnServer: ApachernConnection: Keep-AlivernTransfer-Encoding: chunkedrnContent-Type: text/html; charset=iso-8859-1rnrn127rn<!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>nrn0rnrn"} 4>
搞定!
玩得开心!
最后
以上就是迅速奇异果为你收集整理的gen_tcp容易误用的一点解释的全部内容,希望文章能够帮你解决gen_tcp容易误用的一点解释所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复