-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
EDIT: Revised proposal by @stephentoub on 4/3/2020:
public Socket(SafeSocketHandle handle);System.Net.Sockets.Socket currently does not expose any mechanism to instantiate a socket from an existing file descriptor/handle. This proposal aims to expose this functionality to improve interop with external applications that manage socket connections.
Rationale and Usage
Currently, a socket must be both created and managed by the user application. While this is desired behaviour in most cases, there is no mechanism to take an existing socket handle/file descriptor and make use of it within the user application. If one wanted to use a socket that was created by an external application, the only option (outside of reflection hacks) is to reimplement the calls to the underlying platform sockets with P/Invoke - largely removing the benefits that the managed socket classes provide.
More specifically, this improves interop with existing applications that manage socket connections, such as systemd and the socket activation feature. In this scenario, systemd creates an unmanaged socket to listen for connections. Once a connection is established, a .NET application is launched and a file descriptor that references the unmanaged socked is passed to it through environment variables. Without the ability to create a managed socket from a file descriptor, the connection will need to be reset and then reestablished using the managed APIs - rather than cleanly being passed through and maintained.
Proposed API
namespace System.Net.Sockets
{
// Previously implemented socket class
public partial class Socket : System.IDisposable
{
// Existing constructors
public Socket(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType) { }
public Socket(System.Net.Sockets.SocketInformation socketInformation) { }
public Socket(System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType) { }
private Socket(SafeCloseSocket fd) { }
// Additional existing members omitted
// Proposed member
public Socket(IntPtr fileDescriptor, AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) { }
}
}Details
- Adding this rather than exposing the existing Socket(SafeCloseSocket fd) constructor will keep the rest of the socket PAL internal, as there's currently public no way (as far as I can tell) to create an instance of SafeCloseSocket from a IntPtr.
- This will align with user expectations coming from other languages, such as Python, which has a similar method to create a socket from a file descriptor (see socket.fromfd(fd, family, type[, proto])).
- Platforms that don't support wrapping unmanaged sockets (or that don't expose them, such as UWP?) will throw PlatformNotSupportedException.