编写推送到客户端的服务器应用程序 (TCP)
我正在编写一个客户端-服务器应用程序,要求之一是服务器在收到来自其中一个客户端的更新后,能够将新数据推送到所有其他客户端。这是一个 C++ (Qt) 应用程序,旨在在 Linux(客户端和服务器)上运行,但我更多地寻找它应该如何工作的高级概念想法(尽管低级想法也很好)。
服务器:
它需要(除其他职责外)保持套接字打开,监听来自可能n个不同客户端的传入数据包,大概是在后台线程上(我在套接字代码方面没有写太多其他内容)比学校里的一些小例子)。从客户端获取这些数据后,它会对其进行处理,然后将其发送给所有客户端,对吧?
当然,我不确定它实际上是如何做到这一点的。我猜这意味着它必须与每个客户端(至少是活动客户端)保持持久连接,但我什至从概念上不理解如何维护此连接(或这些连接的列表)。
那么,我应该如何处理这个问题呢?
I'm writing a client-server application and one of the requirements is the Server, upon receiving an update from one of the clients, be able to Push out new data to all the other clients. This is a C++ (Qt) application meant to run on Linux (both client and server), but I'm more looking for high-level conceptual ideas of how this should work (though low-level thoughts are good, too).
Server:
It needs to (among its other duties) keep a socket open listening for incoming packets from potentially n different clients, presumably on a background thread (I haven't written much in terms of socket code other than some rinky-dink examples in school). Upon getting this data from a client, it processes it and then spits it out to all its clients, right?
Of course, I'm not sure how it actually does this. I'm guessing this means it has to keep persistent connections with every single client (at least the active clients), but I don't understand even conceptually how to maintain this connection (or the list of these connections).
So, how should I approach this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一般来说,当您有多个客户端时,有几种方法可以处理这个问题。
首先,在 TCP 中,当客户端连接到您时,它们会被放入队列中,直到可以为其提供服务。这是给定的,除了调用
accept
系统调用来接收新客户端之外,您不需要执行任何操作。收到客户端后,您将获得一个用于读写的套接字。谁先读/写完全取决于您的协议,但双方都需要知道协议(由您定义)。获得套接字后,您可以做一些事情。在一个简单的情况下,您只需读取一些数据,处理它,写回套接字,关闭套接字,然后为下一个客户端提供服务。不幸的是,这意味着您一次只能为一个客户端提供服务,因此不可能进行“推送”更新。另一种策略是保留所有打开的套接字的列表。任何“更新”都只需迭代列表并写入每个套接字。但这可能会带来问题,因为它仅允许推送更新(如果客户端发送请求,谁会监视它?)
更高级的方法是为每个套接字分配一个线程。在这种情况下,每次创建套接字时,都会启动一个新线程,其全部目的是为一个客户端提供服务。这可以减少延迟并利用多个内核(如果可用),但编程难度要大得多。另外,如果有 10,000 个客户端连接,那么 10,000 个线程就太多了。将更新推送到单个客户端(在这种情况下)非常简单(线程只需写入其各自的套接字)。一次推送到所有这些有点棘手(需要一个线程事件或一个生产者/消费者队列,这两者实现起来都不是很有趣)
当然,还有一百万种其他方法来处理这个问题(一个<每个客户端都有一个进程,一个线程池,一个负载平衡代理,凡是你能想到的)。我只想说,没有办法在一个答案中涵盖所有这些内容。我希望这能回答您的基本问题,如果您需要我澄清任何事情,请告诉我。这是一个非常大的主题。然而,如果我可以提出一个建议,处理多个客户端是一个已经被重新发明了一百万次的轮子。有一些非常好的库,它们比原始套接字 IO 更高效且对程序员更友好。我建议 libevent,它将网络请求转变为事件驱动的范例(更像 GUI 编程,这可能对你),并且非常高效。
In general when you have multiple clients, there are a few ways to handle this.
First of all, in TCP, when a client connects to you they're placed into a queue until they can be serviced. This is a given, you don't need to do anything except call the
accept
system call to receive a new client. Once the client is recieved, you'll be given a socket which you use to read and write. Who reads / writes first is entirely dependent on your protocol, but both sides need to know the protocol (which is up to you to define).Once you've got the socket, you can do a few things. In a simple case, you just read some data, process it, write back to the socket, close the socket, and serve the next client. Unfortunately this means you can only serve one client at a time, thus no "push" updates are possible. Another strategy is to keep a list of all the open sockets. Any "updates" simply iterate over the list and write to each socket. This may present a problem though because it only allows push updates (if a client sent a request, who would be watching for it?)
The more advanced approach is to assign one thread to each socket. In this scenario, each time a socket is created, you spin up a new thread whose whole purpose is to serve exactly one client. This cuts down on latency and utilizes multiple cores (if available), but is far more difficult to program. Also if you have 10,000 clients connecting, that's 10,000 threads which gets to be too much. Pushing an update to a single client (in this scenario) is very simple (a thread just writes to its respective socket). Pushing to all of them at once is a little more tricky (requires either a thread event or a producer / consumer queue, neither of which are very fun to implement)
There are, of course, a million other ways to handle this (one process per client, a thread pool, a load-balancing proxy, you name it). Suffice it to say there's no way to cover all of these in one answer. I hope this answers your basic questions, let me know if you need me to clarify anything. It's a very large subject. However if I might make a suggestion, handling multiple clients is a wheel that has been re-invented a million times. There are very good libraries out there that are far more efficient and programmer-friendly than raw socket IO. I suggest libevent, which turns network requests into an event-driven paradigm (much more like GUI programming, which might be nice for you), and is incredibly efficient.
据我了解,我认为您需要保持无限循环(至少直到程序终止)来回答来自客户端的连接请求。最好将它们添加到某种数组中。使用事件来查看何时将新客户端添加到该数组中,并等待其中之一提供数据。然后,您对这些数据执行您必须执行的操作并将其返回。
From what I understand, I think you need to keep an infinite loop going, (at least until the program terminates) that answers a connection request from your clients. It would be best to add them to a array of some sort. Use an event to see when a new client is added to that array, and wait for one of them to give data. Then you do what you have to do with that data and spit it back.