Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 从光纤通过套接字发送和读取数据_Sockets_Crystal Lang_Fibers - Fatal编程技术网

Sockets 从光纤通过套接字发送和读取数据

Sockets 从光纤通过套接字发送和读取数据,sockets,crystal-lang,fibers,Sockets,Crystal Lang,Fibers,试图找出如何通过套接字发送/读取数据。在远程服务器上,我创建了新的netcat-l 4444,并从本地发送文本数据回显测试| netcat remote.host 4444。这总是很好用的 试图复制: require "socket" HOST = "remote.host" PORT = 4444 ch_request = Channel(String).new ch_response = Channel(String).new spawn do socket = TCPSocket

试图找出如何通过套接字发送/读取数据。在远程服务器上,我创建了新的netcat-l 4444,并从本地发送文本数据回显测试| netcat remote.host 4444。这总是很好用的

试图复制:

require "socket"

HOST = "remote.host"
PORT = 4444

ch_request = Channel(String).new
ch_response = Channel(String).new

spawn do
  socket = TCPSocket.new(HOST, PORT)
  loop do
    select
    when request = ch_request.receive
      socket << request
      socket.flush
    end

    if response = socket.gets
      ch_response.send response
    end
  end
end

sleep 0.1

ch_request.send "hello"

loop do
  select
  when response = ch_response.receive
    pp response
  end
end

在我的梦中,我将数据发送到通道,从第一个循环读取数据,然后发送到套接字。同样的方法,但从第二个循环读取它需要相反的顺序

在实践中,这种情况不会发生。在本地连接后,我得到了测试,无法发回任何东西。在远程,我可以发送到本地,但在本地,我只得到了一次空字符串,之后就什么也没有了


这种行为是什么意思?如何实现计划的?

您没有显示这一点,但我想您还有第二个实现,它使用了netcat-l等效的TCPServer

您需要使用单独的光纤来读取/写入插槽和通道。在看不到服务器的情况下,很难判断到底发生了什么,但我认为最终会陷入死锁,双方都在等待另一方或用户的输入,但无法继续实际发送或读取任何内容。换句话说,您联锁了发送/接收部分,要求另一方小心地作出反应和相互作用,以免锁定客户端。这显然是一种脆弱的方法

相反,您应该确保任何光纤在一个环路中不会执行多个操作。一个从插槽接收数据并将其转发到通道,第二个从通道接收数据并将其转发到插槽,第三个从读卡器侧通道接收数据并打印或执行您想执行的任何操作,最后一个填充发送器通道。这样,任何操作都无法阻止其他操作之一。当然,这些光纤中的一个应该是主程序光纤

在服务器中,您还需要一根光纤来接受客户端连接,并为每个连接生成发送方和接收方循环


最后请注意,如果select语句具有单个分支,则当分支无效时,可以直接进行调用。如果您需要在同一光纤中同时读取或写入多个通道,则select非常有用,因此,例如,如果您有多个通道提供要发送到套接字的数据,则可以使用select使消息不会因两个光纤同时写入同一套接字而损坏。select的另一个用例是发送或接收带有超时的频道。

正在寻找类似问题的答案。我想要的最终结果如下所示:

# Open socket for simulate remote server: `netcat -v -4 -l 4444`

require "socket"

HOST = "remote.host"
PORT = 4444

# JFYI: In real life this packed into class and I use class variable instead consts.
TUBE_REQUEST  = Channel(String).new
TUBE_RESPONSE = Channel(String).new

SOCKET = TCPSocket.new(HOST, PORT)

spawn do
  until SOCKET.closed?
    if request = TUBE_REQUEST.receive
      SOCKET << request
      SOCKET.flush
    end
  end
end

spawn do
  until SOCKET.closed?
    if response = SOCKET.gets
      TUBE_RESPONSE.send response
    end
  end
end

sleep 0.1

def receive_response
  TUBE_RESPONSE.receive
end

def send(message, wait_for_response = true)
  TUBE_REQUEST.send message
  receive_response if wait_for_response
end

send("command with response")
send("command with new line and response\n")
send("command without new line and response", false)


它将发送每个命令并等待应答,但最后一个命令来自远程,然后调用下一个命令。

>[…]第二次使用TCPServer实现。对于开发,我使用类似于上述的netcat。此命令用-l打开套接字,监听输入连接并打印数据。发送/读取数据不需要单独的服务器。对于像服务器这样的实现,我有Nsqd,它可以向我发送二进制流数据。您的回答非常有用,并扩展了我对光纤/通道的了解,我解决了这个问题。非常感谢您抽出时间!