小超同学遇到一个问题: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

 

小图一张