How to convert IntPtr/Int to Socket?

江枫思渺然 提交于 2019-12-04 07:43:27

You can't do it because the Socket class creates and manages its own private socket handle. In theory you could use some evil reflection to jamb your socket handle into a private field of a Socket but that's a total hack and I wouldn't do it.

Given a valid socket handle, you can receive data by calling the Win32 recv function via P/Invoke, like this:

[DllImport("ws2_32.dll")]
extern static int recv([In] IntPtr socketHandle, [In] IntPtr buffer,
  [In] int count, [In] SocketFlags socketFlags);

/// <summary>
/// Receives data from a socket.
/// </summary>
/// <param name="socketHandle">The socket handle.</param>
/// <param name="buffer">The buffer to receive.</param>
/// <param name="offset">The offset within the buffer.</param>
/// <param name="size">The number of bytes to receive.</param>
/// <param name="socketFlags">The socket flags.</param>
/// <exception cref="ArgumentException">If <paramref name="socketHandle"/>
/// is zero.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="buffer"/>
/// is null.</exception>
/// <exception cref="ArgumentOutOfRangeException">If the 
/// <paramref name="offset"/> and <paramref name="size"/> specify a range
/// outside the given buffer.</exception>
public static int Receive(IntPtr socketHandle, byte[] buffer, int offset,
  int size, SocketFlags socketFlags)
{
  if (socketHandle == IntPtr.Zero)
    throw new ArgumentException("socket");
  if (buffer == null)
    throw new ArgumentNullException("buffer");
  if (offset < 0 || offset >= buffer.Length)
    throw new ArgumentOutOfRangeException("offset");
  if (size < 0 || offset + size > buffer.Length)
    throw new ArgumentOutOfRangeException("size");

  unsafe
  {
    fixed (byte* pData = buffer)
    {
      return Recv(socketHandle, new IntPtr(pData + offset),
        size, socketFlags);
    }
  }
}

There's nothing in the Socket class to do this - though it uses an underlying handle, there's no API to manipulate it and the Handle property is read-only.

You would probably be best off by just P/Invoking recv and calling it directly with your IntPtr handle.

A quick browse of the Rotor code looks like you could get away with creating a Socket, closing it's handle, and then setting it's m_handle field to your own. But that requires Reflection, and if your socket is already connected (which it sounds like it is - since you just asked about calling recv) then you'd also have to manipulate the private state of Socket - which makes this idea even less palatable and more fragile.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!