问题标签 [gen-tcp]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
67 浏览

c++ - 接收使用 gen_tcp:send/2 发送的数据

我有一个 erlang 客户端,它使用 gen_tcp:send/2 向我发送数据

具体来说,它是这样发送给我的,

我有一个基于 c++ 的 tcp 服务器,它接收消息。如果客户端可以使用 term_to_binary/1 发送给我,我可以使用 ei_decode_X 并解码。不确定如何接收此特定消息并能够解析它。即,我应该知道消息,A,B的值。

我收到这些数据使用

我可以看到当我这样发送时根本没有收到数据。但是,如果我在 term_to_binary/1 转换后发送它,我就可以接收数据。

这是发送数据的正确方式吗?

谢谢

0 投票
1 回答
330 浏览

c++ - 在 gen_tcp 中使用 {packet, N} 以及如何在 C++ 程序中接收数据

当通信的两端都基于 erlang 并且文档清楚地表明使用 {packet, N} 附加一个带有消息大小的标头并且 gen_tcp:recv/2 在接收时删除标头时,我已经工作过。这很简单。但是,如果接收程序不是基于 erlang,而是基于 c++,我如何只解析标头并知道消息的大小,以便我可以分配该内存量。一直用到现在

但不确定如何获取该标头,然后使用 ei_module 获取真正的解码值。

这就是我解码消息的方式。

此处的代码 这是客户端使用选项 {packet,0} 连接时,因此没有带有大小的标头。为了允许动态内存分配,我开始使用 {packet, N} 但不确定如何读取该标头?先感谢您。

0 投票
1 回答
351 浏览

sockets - 与 gen_tcp 并行建立大量连接时出现 CLOSED 错误(错误?)

在尝试并行建立大量 TCP 连接时,我观察到一些奇怪的行为,我认为这是gen_tcp.

该场景是一个服务器在具有多个并发接受器的端口上侦听。从客户端我通过调用建立连接gen_tcp:connect/3,然后我向服务器发送“Ping”消息并在被动模式下等待“Pong”响应。当按顺序执行“get_tcp:connect/3”调用时,一切正常,包括大量连接(我测试了高达 ~ 28000)。

尝试并行建立大量连接时会出现问题(取决于大约 75 到数百之间的机器)。虽然大多数连接仍然建立,但一些连接失败并closed出现gen_tcp:recv/3. 奇怪的是,这些连接之前没有失败,调用gen_tcp:connect/3gen_tcp:send/2都成功(即返回ok)。在服务器端,我没有看到这些“奇怪”连接的匹配连接,即没有返回gen_tcp:accept/1。我的理解是,成功的“get_tcp:connect/3”应该会导致服务器端匹配接受的连接。

我已经提交了一个错误报告,在那里你可以找到更详细的描述和一个最小的代码示例来演示这个问题。我能够在 Linux 和 Mac OS X 以及不同的 Erlang 版本上重现该问题。

我的问题是:

  1. 是否有人能够重现该问题并可以确认这是错误行为?
  2. 任何解决方法的想法?如何处理这个问题,其他顺序启动所有连接(这需要永远)?
0 投票
1 回答
1419 浏览

sockets - 半建立的 TCP 连接

半建立连接

对于半建立的连接,我的意思是客户端调用connect()成功返回的连接,但服务器调用accept()没有成功。这可以通过以下方式发生:客户端调用connect(),从而将SYN数据包发送到服务器。服务器进入状态并向客户端SYN-RECEIVED发送SYN-ACK数据包。这会导致客户端回复ACK,进入状态ESTABLISHED并从connect()调用中返回。如果 finalACK丢失(或由于服务器上的完整接受队列而被忽略,这可能是更可能的情况),服务器仍处于状态SYN-RECEIVED并且accept()不会返回。由于与SYN-RECEIVED状态相关的超时SYN-ACK将被重新发送,允许客户端重新发送ACK. 如果服务器最终能够处理ACK,它也会进入状态ESTABLISHED。否则它将最终重置连接(即向RST客户端发送一个)。

您可以通过在单个侦听套接字上启动大量连接来创建此场景(如果您不调整 backlog 和tcp_max_syn_backlog)。有关更多详细信息,请参阅此问题本文

实验

我进行了几次实验(使用此代码的变体)并观察到一些我无法解释的行为。所有实验都是使用 Erlanggen_tcp和当前的 Linux 进行的,但我强烈怀疑答案并不特定于这个设置,所以我试图在这里保持更通用。

connect()-> 等待 -> send()->receive()

我的出发点是从客户端建立连接,等待 1 到 5 秒,向服务器发送“Ping”消息并等待回复。使用此设置,我观察到当我有一个半建立的连接时receive()失败并出现错误。在半建立连接closed期间从未出现错误。您可以在此处send()找到有关此设置的更详细说明。

connect()-> 漫长的等待 ->send()

要查看,如果在半建立的连接上发送数据时出现错误,我在发送数据前等待了 4 分钟。这 4 分钟应涵盖与半建立连接相关的所有超时和重试。仍然可以发送数据,即send()返回没有错误。

connect()->receive()

接下来我测试了如果我只receive()用很长的超时时间(5 分钟)调用会发生什么。我的期望是closed在半建立的连接中出现错误,就像在原始实验中一样。唉,什么也没发生,没有抛出错误,接收最终超时。

我的问题

  1. 我所说的半建立连接有一个通用名称吗?
  2. 为什么send()半建立连接成功?
  3. receive()如果我先发送数据,为什么 a only 会失败?

欢迎任何帮助,尤其是详细解释的链接。

0 投票
1 回答
958 浏览

erlang - 如何使用 gen_tcp 在 Elixir 中的活动套接字上检测 TCP 超时?

我有一个GenServer通过gen_tcp.

opts = [:binary, active: true, packet: :line] {:ok, socket} = :gen_tcp.connect('remote-url', 8000, opts}

我正在处理以下消息:

def handle_info({:tcp, socket, msg}, stage) do IO.inspect msg {:noreply, state} end

效果很好。但是,TCP 服务器很容易超时。如果我使用gen_tcp.recv,我可以指定超时。但是,我习惯用active: true接收消息handle_info,而不必循环调用recv. 因此,GenServer即使服务器超时,它也会愉快地等待下一条消息。

GenServer当 X 秒后没有收到来自 TCP 连接的消息时,如何触发函数?我被卡住了recv吗?

0 投票
1 回答
121 浏览

tcp - 有什么方法可以通过 gen_tcp 获取 ether/ip 标头?

有什么办法不仅可以获得传入消息的正文。还要ether/IP标头吗?现在我正在gen_tcp通过主动控制过程使用和接收消息。

现在套接字是通过“of_driver”以这种方式打开的:

0 投票
1 回答
1656 浏览

sockets - 在打开的连接中从 Elixir 中的 tcp 服务器向 tcp 客户端发送消息

我使用 Erlang :gen_tcp模块的实现在Phoenixframwork中开发了一个 TCP 服务器。

我可以通过调用它来启动服务器:gen_tcp.listen(port),然后侦听此端口上的新连接。

一个客户是药房的自动拣货系统(基本上是自动配药机器人)。

因此,作为 tcp 客户端,机器人能够打开与我的 tcp 服务器的连接。服务器通过 -callback 方法侦听机器人的新消息,handle_info并且还能够在此请求中响应客户端 ( :gen_tcp.send)。

我面临的问题是我不知道如何在没有客户端请求的情况下使用此连接并将数据发送回机器人。

由于机器人是 tcp 客户端(机器人背后的公司表示目前无法让机器人充当服务器),因此我没有可以向其发送消息的开放端口/机器人服务器地址。所以我必须使用客户端初始化的已经建立的连接。

设置

pharmacy_ui > pharmacy_api(凤凰)> 机器人(供应商软件)

工作流程

  1. 机器人通过 tcp 初始化与 api 的连接
  2. 机器人向api发送状态信息并获得响应
  3. 在某些时候(参见更新 1),api 必须向机器人发送分配请求(通过使用 #1 中初始化的连接)

第 1 步和第 2 步有效,第 3 部分无效。

这看起来是关于 Elixir/Phoenix 中 tcp 连接的一个相当简单的问题,但任何正确方向的提示都非常感谢:)

到目前为止,我想出了这个实现(基于this blog post):

更新 1

在某个时刻 = 用户(例如药剂师)在 ui 前端下订单。Frontend 触发一个 post 到 api 并且 api 处理 OrderController 中的 post。OrderController 必须转换订单(以便机器人理解它)并将其传递给持有与机器人连接的 TcpServer。这个工作流程每天会发生很多次。

0 投票
1 回答
1861 浏览

erlang - Erlang client-server example using gen_tcp is not receiving anything

I am trying to receive data at client side, but nothing is received.

Server code that sends message

Client that should receive and print out

0 投票
0 回答
472 浏览

erlang - 在 localhost 上测试具有多个客户端的并发服务器:错误,econnrefused

我无法让多个客户端与我的并发回显服务器进行通信。这是我的结果:

服务器终端窗口:

客户端窗口:

在shell中,如果我启动我的服务器,然后连接一个客户端,我的客户端和服务器可以来回通信而不会出错:

服务器终端窗口:

客户端窗口:

在我失败的并发测试中,我这样做:

这是我的回声服务器:

这是我的客户:

我的理解是 aTCP socket只不过是一个包含四个数字的元组:

我认为我的每个客户端都必须具有相同的senderPortand senderAddress,因此它们都在尝试使用相同的 TCP 套接字。但我认为我的一个客户端将能够成功建立 TCP 连接,而其余客户端则出现连接被拒绝错误,但我的所有并发客户端都出现连接被拒绝错误。

在我看来,gen_tcp:connect()以某种方式选择了一个 senderPort 并检索了 senderAddress,它与 ServerAddress 和 ServerPort 参数一起定义了套接字。如何让我的每个客户端使用不同的 senderPort,以便每个客户端创建一个唯一的套接字?

有没有办法在本地主机上以编程方式测试具有多个客户端的并发服务器?

0 投票
1 回答
192 浏览

erlang - 无法连接到特定的网络接口

我已经阅读了'inet''gen_tcp' 的文档,但无法理解错误在哪里。

connect_option() = {ip, inet:socket_address()}

socket_address() = ip_address()

ip_address() = ip4_address() | ip6_address()

ip6_address() = {0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535}

所以它必须是 {ip, {0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535, 0..65535}}

或者

{错误,无效}