编辑:我的应用是多线程的
假设我有一台服务器
int main()
{
resolveAddrandPort(hostname, port); // Custom function
SOCKET listening_socket = socket(/* args... */); // Creates a socket.
bind(listening_socket, /* args... */); // Binds the socket to the address and port provided above.
listen(listening_socket, default_backlog); // Places the socket in a mode where it can accept any requests.
add_handlers(10); // Custom function that adds 10 handlers which each run on different threads and can handle requests concurrently (using the same socket[=listening_socket]).
while(is_recieving_requests)
{
SOCKET client_socket = accept(listening_socket, /* args... */);
handle_request( // Custom function
find_available_handler(), // Custom function that finds among the 10 handlers which of them is currently free and not handling any requests to handle this request.
client_socket
);
clean_up(); // Custom function that cleans up after finishing with the request.
}
server_clean_up(); // Cleans up after the server.
}
我用winsock创建服务器
在有关listen
的文档中,您可以提供一个backlog来确定有多少请求可以挂起。
现在这可能是愚蠢的,但我假设一个socket不能并发处理多个请求。如果是这样,我认为我必须创建多个listening_socket
才能并发处理它。
如果我错了,请纠正我,谢谢你的耐心。
3条答案
按热度按时间x6yk4ghg1#
你的问题有点模糊,但我会试着总结一下。你可以有一个单独的侦听套接字来接受来自传入连接或消息(关于UDP)的请求。
一个套接字不能同时处理多个请求
concurrently是让我感到困惑的地方。backlog意味着你可以有x个最大数量的请求挂起,直到你接受或放弃它们,然后新的请求将被允许。
在TCP中,一个监听套接字将用于接受来自连接的请求。然后您可以用自己的套接字来区分每个连接。
在UDP中,一个单独的监听套接字可以用来接受由其远程地址定义的请求。你也可以使用一个单独的套接字向许多不同的连接发送远程地址。
我认为你的问题的模糊性在于你是否可以在一个线程中同时从多个套接字读取请求。在典型的阻塞I/O中,你一次只能从一个套接字读取。这就是为什么非阻塞套接字存在。这可以让你循环通过每个套接字并检查是否有挂起的数据。在这种情况下,数据可以被检索。
如果您正在考虑为每个套接字运行一个线程,以便可以从每个套接字读取一个请求(许多网络初学者都是这样做的,因为他们是从哪里学来的)。从你的代码来看,这似乎就是你正在做的事情。这是一个可怕的想法!这可能是一个“OK”的临时套接字解决方案(单HTTP请求),但不用于长期连接。但我甚至不会为单个请求使用每个套接字的线程。这可能会导致漏洞。
xuo3flqw2#
你不需要多个监听套接字,一个就可以了。
当一个连接请求到来时,一个新的连接被创建,
accept
返回一个专门为该连接创建的新套接字,并且您继续从该套接字为该连接提供服务。同时,侦听套接字准备好接受新连接。您不能同时收到许多连接请求,因为单个物理连接(以太网或其他)一次传输一个数据包。积压的事情是当请求来的比你可以
accept
他们快(仍然是一次一个)。在多线程服务器中,这基本上不是问题。你把得到的套接字发送给一个工作线程来服务,然后监听线程准备好再次执行accept
。这都是关于TCP的。UDP的工作方式有点不同,没有连接,只有消息。
xzv2uavs3#
你不需要多个侦听套接字,事实上你不能有多个TCP侦听套接字。
你有一个监听套接字,这个套接字用于接受连接,每个连接都被分配了自己的套接字。
你可以有一个线程监听新的连接,然后当它得到一个时,它可以将接受的套接字传递给一个新线程或池中的现有线程。这样,你有一个线程只监听新的连接,还有许多其他线程,每个线程都处理一个活动连接。这将有限制,例如,如果你有比CPU内核更多的线程,那么一些线程将等待其他线程,但它将工作。