小超同学遇到一个问题:gen_tcp:send方法报错,Bad value on output port 'tcp_inet';按照字面意思是发往port的数据值是bad value;
打开erl5.9\lib\kernel-2.15\src\gen_tcp.erl看一下gen_tcp的源码:
%% %% Send %% -spec send(Socket, Packet) -> ok | {error, Reason} when Socket :: socket(), Packet :: iodata(), %%% <- 注意这里 Reason :: inet:posix(). send(S, Packet) when is_port(S) -> case inet_db:lookup_socket(S) of {ok, Mod} -> Mod:send(S, Packet); Error -> Error end.
从函数接口说明可以看出数据要求是iodata,估计出现'bad value'很有可能数据不是iodata,做个实验看看:
Eshell V5.9 (abort with ^G) 1> {ok,S0}=gen_tcp:listen(5678,[]). {ok,#Port<0.506>} 2> {ok,S1}=gen_tcp:connect("localhost",5678,[]). {ok,#Port<0.517>} 3> {ok,S2}=gen_tcp:accept(S0). {ok,#Port<0.518>} 4> gen_tcp:send(S1,"message text\0"). ok 5> gen_tcp:send(S1,["message text",0]). ok 6> gen_tcp:send(S1,["message text我们",0]). ok 7> flush(). Shell got {tcp,#Port<0.518>,[109,101,115,115,97,103,101,32,116,101,120,116,0]} Shell got {tcp,#Port<0.518>,[109,101,115,115,97,103,101,32,116,101,120,116,0]} Shell got {tcp,#Port<0.518>, [109,101,115,115,97,103,101,32,116,101,120,116,206,210,195,199, 0]} ok 8> gen_tcp:send(S1,["message text我们",msg,0]). {error,einval} =ERROR REPORT==== 23-Aug-2012::11:37:23 === Bad value on output port 'tcp_inet' 9> gen_tcp:send(S1,["message text我们",0]). ok 10> gen_tcp:send(S1,["message text我们",12,0]). ok 11> gen_tcp:send(S1,["message text我们",1222,0]). {error,einval} =ERROR REPORT==== 23-Aug-2012::11:57:24 === Bad value on output port 'tcp_inet' 12>
重现了小超遇到的问题,,只要发送的数据不是iodata就会报Bad value on output port 'tcp_inet'的错误,根据这个线索,小超同学跟了一下果然由于协议层代码问题导致发送的数据是error_protocol这样一个原子.
关于iodata和iolist这个我之前整理过一篇文章[链接],这里只把iodata的定义再贴一遍:
iodata() = iolist() | binary()
iolist() maybe_improper_list(char() | binary() | iolist(), binary() | [])
maybe_improper_list() maybe_improper_list(any(), any())
byte() 0..255
char() 0..16#10ffffmaybe_improper_list(T) maybe_improper_list(T, any())
或者:IoData = unicode:chardata()
chardata() = charlist() | unicode_binary()
charlist() = [unicode_char() | unicode_binary() | charlist()]
unicode_binary() = binary()A binary() with characters encoded in the UTF-8 coding standard.
下面资料遇到的情况是同样的原因:
[1] http://www.trapexit.org/forum/viewtopic.php?p=39602&sid=ba065c1a5b0c789b4383501784d416ec
[2] http://erlang.org/pipermail/erlang-questions/2009-September/046396.html
小图一张