我是靠谱客的博主 迅速奇异果,最近开发中收集的这篇文章主要介绍gen_tcp容易误用的一点解释,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前天有同学在玩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容易误用的一点解释所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部