2

我想设计一个监听 x 客户端的 TCP 服务器。X 很小,比如大约 10 并且它是固定的。客户可以随时连接。一旦建立连接(accept()成功),我为每个客户端生成一个线程并处理它们。

在这个handle()函数中,我想向客户端发送命令并相应地接收数据。

问题: 一旦从服务器发送命令,客户端就会通过连续发送数据来响应。如何将命令发送回客户端以停止它?与当前代码一样,我正在循环接收来自客户端的数据。

  1. 我不知道如何在接收过程中从服务器线程发送命令,比如一旦建立连接,我是否需要另一个线程(发送 cmds)?
  2. 如何不断地从客户端接收数据并同时发送命令?根据用户输入向每个客户端发送命令。(假设用户希望 client1 开始发送数据,那么我必须向 client1 发送 START。并且用户希望停止 client1 发送,所以我需要向 client1 发送 STOP 如果用户希望将 data3 cmd 发送到客户端 4 然后发送命令 DATA3 到 client4 等,这种情况下如何识别客户端?基本上形成一个小协议**

下面的代码在我可以监听套接字和客户端连接并发送数据的地方工作。我不确定如何将用户输入的命令发送到正确的客户端(比如 client4)并同时接收。

4

4 回答 4

1

如果您想要真正连续地流式传输数据并同时想要交换命令,您将无法绕过额外的连接来建立命令通道。替代方案将是某种多路复用。流式传输一大块数据,检查命令,流式传输下一个块,再次检查命令... - 由于流不断中断,因此复杂且容易出错...

古老的 ftp 协议做了类似的事情:http ://en.wikipedia.org/wiki/Ftp和https://www.rfc-editor.org/rfc/rfc959(参见第 2.3 章中的 ascii 艺术)

于 2013-02-25T17:50:30.533 回答
0

过去,我为无法同时通信的低级设备设计了自己的双向协议,这让我很开心。您可以使用的一种方法是相互让步:建立一种在客户端和服务器之间传递消息的机制。流式传输您需要发送的任何命令或消息,然后将流传输到另一端。然后另一方将流式传输任何消息或命令,然后将流传递给原始侧。这种机制的唯一问题是它对于高 ping 连接非常滞后,例如国际互联网连接。

这已经提到过,但我不妨重新讨论一下。计算机已经在其网络硬件中内置了多路复用,因此您可以进行“并发”发送/接收调用。只需为每个连接运行一对线程:一个接收线程和一个发送线程。这应该是最稳健的解决方案。

于 2013-02-25T19:42:54.497 回答
0

假设您想让另一个线程发起发送命令的请求,您可以使用标准异步 i/o 完成您想要的操作,添加另一个通道 - 管道 - 以接​​收来自另一个线程的命令。伪代码:

Master thread:
while(1) {
    newsocket = accept(listen socket)
    pipefds = pipe()
    new thread(Receiver, newsocket, pipefds.read)
}

Receiver thread:
while(1) {
    readfds = [ pipefds.read, newsocket ]
    poll( readfds )  // wait for there to be data on one of the fds
    if (data ready on newsocket) {
           read (newsocket)
           process data
    }
    if (data ready on pipefds.read) {
           read (pipefds.read)
           send command
    }
}

Commander thread:
write (pipefds.write, command)

select只要套接字上有要读取的数据,或者另一个线程发送了需要发送到远程连接的命令,主接收器循环就会唤醒。

查找信息的关键系统调用是poll(或select),和pipe

于 2013-02-26T17:18:46.747 回答
0

呜呼!我的朋友,你决定深入研究一个非常棘手的主题。

让我首先重新表述您的问题:您的程序一次只能等待一件事。如果它正在等待receive,它就不能等待send。所以你不能同时发送和接收。

这是通过多路复用解决的:等待多个事物。

  1. 谷歌搜索关键字:io, multiplexing, select, poll.
  2. SO相关问题:使用select读写同一个套接字(TCP)

另一种方法是进入一个nonblocking-read -> nonblocking-write -> sleep循环。这显然不是最佳的,但对于您的情况可能就足够了。

于 2013-02-25T17:45:30.297 回答