我想制作一个多客户端-单服务器测验应用程序。在此,首先,客户端将连接到服务器并注册自己。然后,服务器将向每个已向服务器注册的客户端多播一个问题。然后,客户端将给出答案,该答案将仅发送到服务器。然后服务器会将每个客户端的分数发送给各自的客户端。
这就是我在上面的应用程序中尝试做的事情-
1. 因为我也有
multicast
,这就是为什么我将我的服务器套接字设置为SOCK_DGRAM
(即UDP)。然后我使用 CLASS-D
IP 地址来创建一个组(服务器将向哪个组进行多播)。然后是使用setsockopt
,我将客户添加到这个组中,以便他们可以收到问题。select
。它使用套接字描述符在各个客户端之间进行选择,以了解哪个客户端已准备好读取。listen
和 accept
功能。因此,我不会获得套接字描述符(由 accept
返回)。这就是为什么,我将无法使用select
(因为它仅使用文件描述符)。即使使用 UDP 和未连接的套接字,您仍然可以使用
select
等功能。只需将服务器套接字绑定到一个地址,然后使用该套接字即可 select
。当套接字可读时,客户端已发送一些内容,例如sendto
你可以这样做recvfrom
。
但是,我真的建议您使用 TCP 套接字,它会让很多事情变得更简单,尤其是在通信协议方面(请记住,UDP 包可能会丢失或出现故障,您必须自己处理)。
正如您所说,
select
在这里没有用,因为服务器端只有一个套接字。
该套接字用于发送带有 sendto
的数据报
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
在
dest_addr
中指定数据报的目标地址。
在 UDP 套接字上使用
recvfrom(2)
类似:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
src_addr
是发送者地址,因此您可以识别发送响应的客户端。
recvfrom
调用会阻塞,直到数据可供读取为止(除非您将套接字设置为解除阻塞)。
您可以循环接收所有回复。
你走在正确的轨道上,但你不需要listen()或accept()。只需选择可读性即可。当套接字变得可读时,读取它。你可能根本不需要 select() ,实际上,只是一个阻塞读取,如果你愿意的话可以超时。