有多种进程共享一个侦听套接字的方法吗? [英] Is there a way for multiple processes to share a listening socket?

查看:210
本文介绍了有多种进程共享一个侦听套接字的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在套接字编程中,您创建一个侦听套接字,然后为每个连接的客户端,您将获得一个普通的流套接字,您可以使用它来处理客户端的请求。操作系统管理后台进入连接的队列。



两个进程不能同时绑定到同一个端口 - 默认情况下,无论如何。



我想知道是否有一种方法(在任何知名的操作系统,特别是Windows上)启动进程的多个实例,使它们都绑定到套接字,因此它们有效共享队列。然后每个进程实例可以是单线程的;它只会在接受新连接时阻止。当客户端连接时,其中一个空闲进程实例将接受该客户端。



这将允许每个进程有一个非常简单的单线程实现,通过显式共享内存,用户将能够通过启动更多实例来调整处理带宽。



这样的功能是否存在?



编辑:对于那些问为什么不使用线程?显然,线程是一个选项。但是在单个进程中具有多个线程,所有对象都是可共享的,并且必须非常小心,以确保对象不是共享的,或者一次只能对一个线程可见,或者绝对不可变的,以及最流行的语言运行时缺乏管理这种复杂性的内置支持。



通过启动一些相同的工作进程,你会得到一个并发系统,其中 default


解决方案

你可以在两个之间共享一个套接字(或更多)进程。



在Linux(或POSIX类型操作系统)下,使用 fork()将使得分叉的孩子拥有所有父的文件描述符的副本。任何没有关闭的任何东西都会继续被共享,并且(例如使用TCP侦听套接字)可以用于客户端的 accept()新套接字。这是多少服务器,包括Apache在大多数情况下工作。



在Windows上,同样的事情基本上是真的,除了没有系统调用,因此父进程需要使用 CreateProcess 或某事来创建子进程(当然可以使用相同的可执行文件)需要传递它一个可继承的句柄。



使侦听套接字成为一个可继承的句柄不是一个简单的活动,但也不是太棘手。 需要使用DuplicateHandle()创建一个重复的句柄(仍然在父进程中),它将设置可继承标志。然后,您可以将 STARTUPINFO 结构中的句柄作为 STDIN OUT ERR 句柄(假设您不想将其用于其他任何操作)。



EDIT:



读取MDSN库,看起来 WSADuplicateSocket 这样做的正确机制;它仍然是不平凡的,因为父/子进程需要解决哪些句柄需要被一些IPC机制复制(尽管这可能像文件系统中的文件一样简单)



澄清:



在回答OP的原始问题时,多个进程不能 bind();只是原来的父进程会调用 bind() listen()等,子进程只处理请求 accept() send() recv()等等。


In socket programming, you create a listening socket and then for each client that connects, you get a normal stream socket that you can use to handle the client's request. The OS manages the queue of incoming connections behind the scenes.

Two processes cannot bind to the same port at the same time - by default, anyway.

I'm wondering if there's a way (on any well-known OS, especially Windows) to launch multiple instances of a process, such that they all bind to the socket, and so they effectively share the queue. Each process instance could then be single threaded; it would just block when accepting a new connection. When a client connected, one of the idle process instances would accept that client.

This would allow each process to have a very simple, single-threaded implementation, sharing nothing unless through explicit shared memory, and the user would be able to adjust the processing bandwidth by starting more instances.

Does such a feature exist?

Edit: For those asking "Why not use threads?" Obviously threads are an option. But with multiple threads in a single process, all objects are shareable and great care has to be taken to ensure that objects are either not shared, or are only visible to one thread at a time, or are absolutely immutable, and most popular languages and runtimes lack built-in support for managing this complexity.

By starting a handful of identical worker processes, you would get a concurrent system in which the default is no sharing, making it much easier to build a correct and scalable implementation.

解决方案

You can share a socket between two (or more) processes in Linux and even Windows.

Under Linux (Or POSIX type OS), using fork() will cause the forked child to have copies of all the parent's file descriptors. Any that it does not close will continue to be shared, and (for example with a TCP listening socket) can be used to accept() new sockets for clients. This is how many servers, including Apache in most cases, work.

On Windows the same thing is basically true, except there is no fork() system call so the parent process will need to use CreateProcess or something to create a child process (which can of course use the same executable) and needs to pass it an inheritable handle.

Making a listening socket an inheritable handle is not a completely trivial activity but not too tricky either. DuplicateHandle() needs to be used to create a duplicate handle (still in the parent process however), which will have the inheritable flag set on it. Then you can give that handle in the STARTUPINFO structure to the child process in CreateProcess as a STDIN, OUT or ERR handle (assuming you didn't want to use it for anything else).

EDIT:

Reading the MDSN library , it appears that WSADuplicateSocket is a more robust or correct mechanism of doing this; it is still nontrivial because the parent/child processes need to work out which handle needs to be duplicated by some IPC mechanism (although this could be as simple as a file in the filesystem)

CLARIFICATION:

In answer to the OP's original question, no, multiple processes cannot bind(); just the original parent process would call bind(), listen() etc, the child processes would just process requests by accept(), send(), recv() etc.

这篇关于有多种进程共享一个侦听套接字的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆