Winsock Programmer’s FAQ Articles: Passing Sockets Between Processes |
by Warren Young and Frank Schmied
If you want to pass a socket from one process to another, the
only offically sanctioned way to do this is with Winsock 2’s
new WSADuplicateSocket()
function. The FAQ originally covered
this issue this way:
Winsock 2 provides support for this through the
WSADuplicateSocket()
facility. The spec describes this
method in detail in section 2.10, and MSDN has a step-by-step
procedure in its documentation for this function. You should
also read article KB150523 in the Microsoft Knowledge
Base. It describes how socket inheritance differs between the
various flavors of Windows.
Another fun feature of the Win32 API is that it allows you
to give a new process different "standard handles" (stdin,
stdout and stderr) when you create it. Microsoft knowledge base
article KB190351 addresses this. Note that this feature
only allows you to do this with a child process; you can’t
redirect your own standard I/O handles to a socket. Also, the
item notes that some processes may behave stangely when you do
this to them. Clearly, this functionality is not as powerful as
the Unix world’s dup2()
system call.
The original FAQ item then said that you can’t do this with Winsock 1.1. As it turns out, Frank Schmied showed how you can do this under Microsoft’s Winsock 1.1 stack on Win32, with a bit of trickery. Frank wrote:
Winsock 1.1 lets you pass sockets from one process to another,
using the Win32 call DuplicateHandle()
. The handling of this
call can be quite complicated. In fact, generating the "real"
process handles is not as easy as its seems. Windows uses two
kinds of window handles: pseudo-handles and real handles. Handles
in Windows are usually memory addresses, and the instance handle is
none other than the offset pointer of the code start in the current
address range. So, an HINSTANCE handle of a process (the pseudo- or
local handle) is usually 0x4000000. Porting with this handle
from one process to another doesn’t work. To get the "real"
handle of the current process, you can use OpenProcess()
:
OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
Duplicating a handle looks like this:
SOCKET ConvertProcessSocket(SOCKET oldsocket, DWORD source_pid) { HANDLE source_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, source_pid); HANDLE newhandle; DuplicateHandle(source_handle, (HANDLE)oldsocket, GetCurrentProcess(), &newhandle, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); CloseHandle(source_handle); return (SOCKET)newhandle; }
This works fine on my multiprocesss webserver. This function
duplicates the socket into the new process and closes the handle
in the old process. The handle has the same access options as
the old handle but can’t be inherited to child processes.
To change this behaviour, alter the FALSE to a TRUE in the
DuplicateHandle()
call. As you see, the hosts' process handle
can be a pseudo handle, the remote processes' handle must
be a real handle.
As I understand it, the source process converts its local SOCKET
handle to a real handle with OpenProcess()
, then passes that
value and its process ID to the destination process. The destination
process then calls Frank’s ConvertProcessSocket()
function
to convert the real handle to a local handle which you can use with
Winsock. Notice that the DuplicateHandle()
call closes the
source process’s handle, and then the CloseHandle()
call closes the real handle you passed to the destination process.
Caveats: Frank’s technique probably only works with Microsoft stacks. It does not work on Win16, and may not work on WinCE. It may or may not work in the presence of Layered Service Providers, except on Windows NT 4.0 SP 4+, which patches the Installable FileSystems (IFS) layer to make this sort of thing work. It may not work on the second Tuesday of the month, when the moon is in its third quarter, unless you chant "oompa hoozah" four times slowly before running the program. In short, this is trickery: you have been warned. :)
Copyright © 2000 by Warren Young and Frank Schmied. All rights reserved.
<< CSocket Considered Harmful |
Dealing with Firewalls >> |
Updated Fri Dec 16 2022 12:23 MST | Go to my home page |