Erlang 中的 TCP 端口
我正在使用 Erlang 编写 BitTorrent 客户端代码。我已经被同样的问题困扰了 4 天。
我将握手发送给所有对等点,每个对等点都有自己的 ip:port。
我使用 gen_tcp:connect 进行连接。
问题是我无法得到他们的回复。我做了很多研究并使用了一些程序来监视我的入站/出站连接。
对等方获取数据并将回复发送回我用来向他们发送握手的端口。
代码方面: get_tcp:connect 选择一个端口并使用该端口将数据发送到对等点。对等方在该端口上回复。然而,正如您所知,在 Erlang 中您需要使用 gen_tcp:listen 来获取回复连接,并且需要指定一个端口。就我而言,我应该侦听的端口是 gen_tcp:connect 返回的端口。
我可以使用 inet:port 获取此端口号,但错误始终相同:端口正在使用。 我明白为什么会收到错误,这只是因为我尝试侦听的端口已被 gen_tcp:connect 使用。我尝试关闭套接字以释放端口,但没有任何结果。
所以我的问题是:在 Erlang 中是否有可能以某种方式连接到对等点并向其发送数据到端口,然后在同一端口上侦听答复。如果没有,那么我必须能够以某种方式告诉对等方将数据发送回我选择的端口。
欢迎所有 Erlang 大师提出任何想法。 谢谢,
//弗兰克。
I'm using Erlang to code a bittorrent client. I have been stuck for 4 days now on the same problem.
I'm sending the handshake to all the peers with each peer having its own ip:port.
I use gen_tcp:connect to connect.
The problem is that I can't get their reply. I have done a lot of research and used some programs to monitor my inbound/outbound connections.
The peers get the data and send the reply back to the port that I used to send them the handshake.
Code wise: get_tcp:connect picks a port and uses that port to send the data to a peer. The peer replies back on that port. However, as you know in Erlang you need to use gen_tcp:listen to pick up the reply connection and you need to specify a port. In my case the port that I should be listening on is the port that gen_tcp:connect returned.
I can get this port number using inet:port but the error is always the same: port in use.
I understand why I get the error, it's simply because the port I'm trying to listen on is already being used by gen_tcp:connect. I tried to close the Socket to free the port but nothing.
So my question is: is it possible in Erlang to somehow connect to a peer and send data to it to port then listen on that same port for a reply. If not then I must somehow be able to tell the peer to send me the data back on a port I choose.
Any ideas from all the Erlang gurus are welcome.
Thanks,
//Frank.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里听起来有些不对劲,让我总结一下您正在尝试执行的操作:
您使用的是 TCP 连接而不是 UDP
TCP 连接如下所示:
IP2:Port2 是您传递给 gen_tcp:connect 的端口,IP1 只是本地计算机上接口的 IP,而 Port1 可能是临时端口由您计算机上的 TCP 堆栈选择。
如果对等方在同一连接上回复,您将仅获得如下数据
作为端口所有者的消息(可能是调用连接的进程)。除非您使用被动模式:那么您必须调用 gen_tcp:recv 来获取数据。
如果您正在调用 gen_tcp:listen,那么您会尝试打开另一个返回的连接。有一些协议可以执行此类操作,例如 FTP,但您必须使用另一个端口号(通常调用侦听,然后获取端口号并通过现有连接将它们发送到可以连接到现有端口的客户端)。但几乎所有较新的协议都不再这样做,因为它有点混乱并且需要状态防火墙。如今,甚至 FTP 也在回避它。所以我强烈怀疑你不想这样做。
Something sounds wrong here, let me summarize what you are trying to do:
You are using TCP connections not UDP
A TCP connection looks like this:
IP2:Port2 is the port you pass to gen_tcp:connect, IP1 is just the IP of the interface on your local machine and Port1 is probably a ephemeral port chosen by the TCP Stack on your machine.
If the peer replies back on the same connection you will just get the data as
messages as the port owner (process who calle connect probably). Except when you are using passive mode: then you have to call gen_tcp:recv og get the data.
If you are calling gen_tcp:listen instead you try to open another connection going back. There are protocols that do this kind of stuff e.g. FTP but you have to use another port number (usually call listen, then get the port number and send these over the existing connection to the client who can the connect to the existing port). But almost all newer protocols don't do this anymore since its kind of messy and needs stateful firewalls. Even FTP is avoiding it nowadays. So I strongly suspect you don't want to do this.
Bittorrent 有两种对等点相互连接的方式:
您的客户端发起与对等点的连接,这是
gen_tcp:connect
。连接一旦建立,就是双向的,并且这个唯一的连接就是您用于所有通信的连接。对等方连接回您的客户端。这是
gen_tcp:listen
路径,后跟gen_tcp:accept
。再次建立双向连接,然后您可以使用该连接。您看到正在使用的端口可能是因为您试图在已有连接的“顶部”创建连接。阅读一些有关 TCP 连接的内容可能是值得的。
一个可行的解决方案路径是首先假设您只连接到其他人并忽略入站连接。针对接受入站连接的测试客户端运行,一切都会正常工作。然后,当一种方法有效时,您可以将入站连接添加到代码中。请注意,握手是相似的,但有一些细微的差别。例如,连接器首先将 info_hash 发送到连接者(以便连接者可以在其当前提供的 torrent 中查找 infohash)。
Bittorrent has two ways peers can connect to each other:
Your client initiates the connect to the peer, this is
gen_tcp:connect
. The connection once established is bi-directional and this sole connection is what you use for all communication.The peer connects back to your client. This is the
gen_tcp:listen
path followed bygen_tcp:accept
. Again, a bi-directional connection is established which you then use.You see the port-in-use probably because you are trying to create a connection "on top" of the connection you already have. It might be worthwhile to read up a bit on TCP connections.
A viable solution path is to begin by assuming you only connect to others and ignore inbound connections. Run against a test client which does accept connections inbound and everything will work. You can then add inbound connections to your code when one way works. Note that the handshake is similar, but there are some slight differences. The connector sends the info_hash to the connectee first for instance (so the connectee can look up the infohash among the torrents it is currently serving).