-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider exposing Socket(SafeSocketHandle fd) constructor #862
Comments
Please take a look at: for API change process and submit API proposal. |
I agree, this would be a good feature to have. |
Next step: We need formal API proposal (linked above) |
@karelz Here's the proposal. This is my first contribution here, so please let me know if I need to add more details/adjustments. Proposal: Add a new constructor to System.Net.Sockets.Socket that allows instantiating a socket from a file descriptor. I imagine this would also need to be added to the next netstandard version, but this shouldn't introduce any extra dependencies/other breaking API changes.
Adding this rather than exposing the existing Use cases: support features where external programs manage socket connections (such as systemd socket activation), improved interop with native code and existing unix tools |
Can you please use the API template in API process? It's much, much easier to read ;) Thanks! |
@stephentoub Thoughts on this? |
@karelz I've updated the top post based on the example from that document. |
Great, thank you! Does the fileDescriptor always match OS bitness on all OSs - Windows, Linux and Mac OS APIs? @davidsh @geoffkizer @CIPop @Priya91 please comment or give thumbs up, thanks! |
file descriptors on Unix are <= 32K. Since handles in Windows are represented as pointers, we've been using IntPtr everywhere in corefx to represent both, which allows us to use SafeHandle for them.
Seems like an ok API to expose. One modification though: Related to this, I also wonder if there are implicit assumptions in Socket's implementation related to lifetime. I expect some vetting of the implementation will need to be done and it won't be quite as simple as just adding a ctor, though it may turn out to be all the actual code that's needed. |
Perhaps also consider a On Linux, the address family, socket type and protocol can be retrieved as |
👍 to this. I've been looking for a way to restart an application without losing open TCP connections, and while |
I've got my DBus client and get a file descriptor from BlueZ representing the RFCOMM socket when a smart phone connects to a registered Bluetooth profile. I would love to work with this using all the socket goodness instead of wrapping it in a Stream and providing the bare minimum read and write pinvokes by myself. |
cc: @wfurt |
We should do this as well: dotnet/corefx#26193 |
Are we waiting for an implementation or there is more to be discussed here? If I'm not mistaken, the windows story here is already complete I believe, due to SocketInformation, but a cross-plat story is missing. This would then be useful to implement a http.sys like port sharing behavior cross platform in Kestrel (albeit a user-mode multi-process one). |
@krwq @stephentoub I tried the new enums from commit (dotnet/corefx#37315) in .Net Core 3 preview 7 with various combinations but it look's like CAN (Controller-Area-Network) is not properly implemented (At least i couldn't get it to work). I implemented a own solution as temporary workaround to get the canbus interface to work in .Net Core. Maybe you guys could expose the interface for creating a raw socket or implement this properly al the way down (this is the preffered way). You could find my full functional example/demo for sending and receive CAN message out-of-the-box in the following repo: https://github.com/jormenjanssen/netcore-can-example |
cc: @wfurt |
Far CAN, only RAW type is supported at the moment. |
As far is the main thread: It seems like we are either looking for It seems like we don't really need socketType and protocolType after constructor. One can always use ProtocolType.Unknown and SocketType.Unknown if that is not applicable. For the |
@jormenjanssen also for CAN you must also enable it on the device before usage externally (i.e. you must set speed etc) - you can use https://github.com/dotnet/iot/blob/master/src/devices/SocketCan/README.md to see what is exactly needed. |
Triage: we think the API is fine but don't want to go review it until we understand if it's worth the complexity to implement it. @wfurt can you please take a look at this, there are some interesting hurdles re: managing state for socket options, address family for udp, etc. |
We have two internal partners asking for this. CC @samsp-msft |
That leaves macOS. When socket is bound or connected we can get AddressFamily from the address. Also I did also some testing with using unsupported socket type on Linux e.g. |
Thanks for the notes! Mostly. I actually have this implemented locally and wired up with #34158 (which was what I actually wanted to solve). However, we can't fully reconstruct everything you listed. Blocking, for example. I don't know of any way to query that on Windows. And on Unix, we can query it, but that tells us the actual state of the file descriptor's nonblocking setting, whereas in the managed layer we maintain some shadow state to keep Socket.Blocking behaving the way the developer set it but be able to use non-blocking under the covers as part of the async implementation. Even with some minor hiccups / inconsistencies, I think this is still worthwhile. The majority use case for this is taking a file descriptor / handle that didn't come from a managed Socket, and without this ctor, there's no good way to achieve it, and with the ctor, the cited inconsistencies should be at worst minor annoyances. |
For the Blocking, the special handling would apply only with async, right? So for the newly created socket it should be OK to reflect OS Blocking IMHO since no Async was done so far. This could possibly create issue if somebody used Handle from existing socket thinking it is Blocking but it is not under the cover e.g. the issue is with sending, not creating Socket from handle. For Windows, I'm wondering if we could always set it as blocking and document that or if it would be better to live with possible inconsistency. In some way caller should know and structure the code accordingly. The easy way to fix if somebody hits is to set it explicitly after creation, right? If we see use case for creating In either case, since access exist outside if the |
Correct.
That's what I currently do. I don't see a better alternative.
Yes |
@wfurt, here's my branch, btw: |
Looks good as proposed: namespace System.Net.Sockets
{
public partial class Socket
{
public Socket(SafeSocketHandle handle);
}
} |
EDIT: Revised proposal by @stephentoub on 4/3/2020:
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
Details
The text was updated successfully, but these errors were encountered: