2010-11-11 107 views
3

我使用Erlang來編寫一個bittorrent客戶端。對於同樣的問題,我被困了4天。Erlang的TCP端口

我發送握手給所有對等體,每個對等體都有自己的ip:port。

我使用gen_tcp:連接來連接。

問題是我無法得到他們的答覆。我做了大量的研究,並使用一些程序來監視我的入站/出站連接。

對等體獲取數據並將回覆發送回我用來發送握手的端口。

明智的代碼:get_tcp:connect選擇一個端口並使用該端口將數據發送到對等端。對端回覆該端口。但是,正如您在Erlang中所瞭解的那樣,您需要使用gen_tcp:listen來獲取回覆連接,並且您需要指定一個端口。在我的情況下,我應該監聽的端口是gen_tcp:connect返回的端口。

我可以使用inet:port得到這個端口號,但是錯誤總是一樣的:使用中的端口。 我明白爲什麼我會得到這個錯誤,這只是因爲我試圖監聽的端口已被gen_tcp:connect使用。我試圖關閉Socket來釋放端口但沒有任何東西。

所以我的問題是:是否有可能在Erlang中以某種方式連接到對等端並將數據發送到端口,然後在該端口上偵聽回覆。如果沒有,那麼我必須以某種方式告訴同行將我的數據發回給我選擇的端口。

歡迎來自所有愛爾蘭大師的任何想法。 謝謝,

//弗蘭克。

+0

順便說一句爲什麼最近每個人都想寫BitTrent的同齡人fpr erlang ??? – 2010-11-11 15:19:14

+0

這是作爲一個大學的任務,同行! – 2010-11-11 16:46:26

回答

6

東西聽起來錯在這裏,讓我來總結一下你正在嘗試做的:

  • 您使用的是TCP連接,不是UDP

  • 一個TCP連接是這樣的:

    Erlang side: IP1:Port1 <----> Peer side IP2:Port2 
    
  • IP2:Port2是您傳遞給gen_tcp:connect的端口,IP1只是本地計算機上接口的IP,而Port1可能是一個短暫端口由您的機器上的TCP堆棧選擇。

  • 如果對方來回復相同的連接上,你只會得到的數據作爲

    {tcp, Socket, Data} 
    

    消息作爲端口所有者(誰大概大道連接過程)。除非您使用被動模式:那麼您必須調用gen_tcp:recv og獲取數據。

  • 如果您正在調用gen_tcp:listen,則嘗試打開另一個連接返回。有一些協議可以處理這類信息,例如FTP,但您必須使用另一個端口號(通常調用listen,然後獲取端口號並通過現有連接將這些端口號發送給可連接到現有端口的客戶端)。但幾乎所有較新的協議都不再這樣做了,因爲它的混亂和需要有狀態的防火牆。即使FTP現在也避免它。所以我強烈懷疑你不想這樣做。

+0

BitTorrent *不需要'gen_tcp:listen',因爲每個客戶端也都像服務器一樣。端口號通常被定義爲特定的端口號,因此您可以在防火牆中插入漏洞。 – 2010-11-11 16:54:40

1

BT軟件有兩種方式可以同行相互連接:

  • 你的客戶端發起連接到同級,這是gen_tcp:connect。建立的連接是雙向的,並且這是您用於所有通信的唯一連接。

  • 對等體連接回您的客戶端。這是gen_tcp:listen路徑,然後是gen_tcp:accept。再次建立一個雙向連接,然後使用。

您會看到使用端口,可能是因爲您正嘗試在已有連接的「頂部」創建連接。在TCP連接上讀取一些信息可能是值得的。

一個可行的解決方案路徑是從假設你只連接到其他人並忽略入站連接開始的。針對接受入站連接的測試客戶端運行,並且一切都將工作。然後,您可以在一種方式下將入站連接添加到您的代碼中。請注意握手是相似的,但有一些細微的差異。例如,連接器首先將info_hash發送給connectee(因此連接器可以查找它當前正在服務的種子中的infohash)。

+0

感謝您的回覆,如果我沒有錯,我意識到您是etorrent的作者。我知道無論是監聽還是連接都是Bottorrent協議所必需的。但是現在,我所要做的就是發送握手並回復。所以我忽略了其他所有東西。我也有一個程序,顯示所有的TCP連接,它告訴我,我的消息是握手類型。同行們實際上正在向我發送他們的握手。但是我正在使用gen_tcp:聽取他們的回覆,我認爲現在是錯誤的。我應該使用gen_tcp:recv嗎? – Frank 2010-11-11 19:02:51

+0

編輯,看起來像我已經解決了這個問題。我會盡快回復您。我必須清理代碼。 – Frank 2010-11-11 19:19:13

+0

閱讀對等消息並研究Erlang中主動和被動套接字之間的區別。運行'erl -man gen_tcp'。 – 2010-11-11 19:36:04