2011-09-08 190 views
0

我想編寫一個簡單的客戶端,它向服務器發送消息並接收響應。我有一臺服務器,當我用telnet測試它時,它會向所有連接的客戶端廣播相同的消息,並將其工作。當我嘗試使用Erlang shell進行操作時,gen_tcp:send將不會發送任何消息,直到關閉套接字爲止。使用gen_tcp的消息:直到套接字關閉才發送發送消息

這就是我想要做的事:

{ok, S} = gen_tcp:connect(IP, Port, []). 
gen_tcp:send(S, "Test"). 
flush(). 

我可以看到,當我通過看我的telnet客戶端關閉套接字的消息被髮送。

二郎版本:R14B01(專家評審組-5.8.2)

更新

hdima評論說,這可能是錯誤的服務器如何從流中提取的消息。這似乎是我嘗試編寫自己的服務器時客戶端似乎按預期工作的原因。我將嘗試獲取服務器的源代碼。服務器是用Java編寫的。

+0

貌似服務器不知道如何從流中提取消息。你能發佈服務器源代碼嗎? – hdima

+0

@hdima:沒有抱歉,我沒有服務器代碼。 – softarn

回答

1

主要問題是有沒有通用信息格式。所以你的第一步是找到服務器使用的消息格式。你不能用另一種語言與服務器通話。

一些消息格式可以是:

  • 整個流是一個消息。
  • 固定大小的消息。
  • 由標記分隔的郵件。例如SMTPPOP,HTTP和許多其他協議使用這種類型的消息。
  • 帶大小字段的消息。例如TLV (Type-Length-Value)消息格式。 IPUDPErlang和許多其他協議使用這種類型的消息。

例如,如果服務器瞭解由換行字符,你可以用下面的代碼發送兩個不同的消息分隔消息:

1> {ok, S} = gen_tcp:connect(IP, Port, []). 
2> gen_tcp:send(S, "Test\n"). 
3> gen_tcp:send(S, "Test2\n"). 
+0

用行結束作品發送消息。 java服務器可能使用readLine()或類似的。謝謝! – softarn

+0

我不認爲這是正確的。這與服務器期望的消息類型無關。這是由於Erlang方面的套接字設置。使用{packet,PacketType}設置來配置它。 –

+0

@ NateC-K使用{packet,PacketType}選項,Erlang只需透明地發送/接收每條消息作爲Length-Value。如果您打算連接使用其他語言編寫的服務器/客戶端(如問題中的Java),則必須瞭解消息格式。 – hdima

0

你可以試試Erlang服務器,看看它是否有問題的服務器或客戶端。

在外殼答:

1> {ok, L} = gen_tcp:listen(12345, [{active, false}]). 
{ok,#Port<0.601>} 
2> {ok, S} = gen_tcp:accept(L), {ok, P} = gen_tcp:recv(S, 0), gen_tcp:send(S, P). 
... % Server will block here until a message comes 
ok 

在外殼B:

1> {ok, S} = gen_tcp:connect(localhost, 12345, []), gen_tcp:send(S, "hello"). 
ok 
2> flush(). 
Shell got {tcp,#Port<0.607>,"hello"} 

如果一切正常,這是最有可能在Java方面的問題。

+0

我很喜歡在Erlang使用套接字是多麼容易! –

+0

如果您閱讀更新部分,我已經說過它似乎是服務器。但是謝謝你花時間回答! – softarn

+0

啊,沒有發現。 :-)您也可以回答自己的問題,並將該答案標記爲已接受。 –

3

當發送數據的小塊插座緩存起來試試填充TCP數據包的最大有效負載。

有可能這是發生了什麼事,因爲當你關閉套接字時,它在被釋放前被刷新。

嘗試設置您的插座上的

{nodelay, true} 

選項。

此處瞭解詳情: http://www.erlang.org/doc/man/inet.html#setopts-2

+1

這是最好的答案。客戶端正在緩衝數據。它與服務器無關。關鍵設置是{packet,PacketType},在您鏈接的部分對此進行了說明。 –