我一直在用C编写复杂的服务器 - 客户端系统,我不知道如何实现套接字通信。
简而言之,系统是一个服务器应用程序,它与数据库通信并使用UNIX套接字与使用fork()
创建的一个或多个子进程进行通信。孩子们的目的是运行游戏服务器。启动游戏服务器的过程如下:
execlp()
以开始运行实际的游戏服务器可执行文件。我对套接字的体验相当小。我之前在服务器应用程序上使用select()
来“复用”众多客户端,如GNU C文档here中的简单示例所示。
我现在面临一个新的挑战,因为系统必须能够做得更多:管理员需要能够任意向游戏控制器子项发送命令(它会通过定期检查数据库找到)并获得回复,但是还期望从它们传入任意命令/错误并发回回复。
所以,我需要一种“上下文”系统,其中套接字只在它们之间有意义。换句话说,当一个命令从管理器发送到游戏控制器时,每一方都需要知道谁在询问并知道答复是什么(因此,哪个命令是答复)。
因为select()
仅用于知道何时有传入数据,并且线程应该阻塞它,我是否需要另一个发送数据并获得回复的线程?这是否需要每个游戏控制器(尽管技术上是“客户端”)使用监听套接字并使用select()
?
我希望我已经简明扼要地解释了系统和问题;如果需要,我会添加更多细节。谢谢!
答案 0 :(得分:1)
好吧,我仍然不确定我到底知道你的问题究竟在哪里,所以我只会说出一些关于编写客户端/服务器应用的事情。如果我偏离轨道,请告诉我。
服务器知道哪些客户端对应哪个套接字的方式是客户端告诉服务器的方式。基本上,您需要具有登录协议。当游戏控制器连接到服务器时,它将发送一条消息,上面写着“嗨,我在主机xyz上注册为控制器foo1,端口abc ......”以及服务器需要知道的有关其客户端的任何其他信息。服务器将保留一个数据结构,将套接字映射到客户端元数据,状态等。每当它获得新消息时,它就可以轻松地从传入的主机/端口映射到其元数据。或者您的协议可以要求在每个传入消息上,将客户端将其注册的名称作为字段发送。
处理请求/响应可以通过多种方式完成。首先让我们在服务器端处理它的网络部分。正如您所提到的,管理此方法的一种方法是使用select(或poll或epoll)来复用套接字。实际上,这通常被认为是更复杂的做事方式。另一种方法是为每个传入的客户端生成一个线程(或fork一个过程,这些日常不常见)。每个衍生线程都可以读取自己分配的套接字,一次响应一条消息,而不必担心除了它自己正在处理的其他客户端之外还有其他客户端。如果有许多客户端,这种简单的一对一线程到套接字模型会崩溃,但如果不是这样,那么值得考虑。
第2部分实际上只涵盖了向服务器发送消息的客户端,以及服务器的回复。当服务器想要发起通信时会发生什么?它是如何做到的以及客户如何处理它?另外,如何在应用程序级别对通信模型进行建模,这意味着假设我们将读/写部分放下,我们如何知道要发送什么?您可能希望根据状态机对事物进行建模。还有很多事情需要处理,比如当客户端崩溃时会发生什么?服务器什么时候崩溃了?另外,如果你真的有使用select的心脏,也许是因为你期望很多客户呢?我明天会尝试为这个答案添加更多内容。