Как конвертировать IntPtr / Int в Socket? - PullRequest
5 голосов
/ 19 апреля 2009

Я хочу преобразовать сообщение. Парам в сокет.

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == Values.MESSAGE_ASYNC)
        {

            switch (m.LParam.ToInt32())
            {
                case Values.FD_READ:
                    WS2.Receive(m.WParam);
                case Values.FD_WRITE: break;
                default: break;
            }

        }
        else
        {
            base.WndProc(ref m);
        }
    }

public class WS2
{
    public static void Receive(IntPtr sock)
    {
        Socket socket = sock;
    }
}

Как преобразовать IntrPtr (sock) в Socket, чтобы я мог вызывать Receive ()?

Ответы [ 2 ]

6 голосов
/ 19 апреля 2009

Вы не можете сделать это, потому что класс Socket создает и управляет своим собственным дескриптором сокета. Теоретически, вы можете использовать какое-то злое отражение, чтобы заколоть свой дескриптор сокета в закрытое поле сокета, но это полный взлом, и я бы этого не делал.

При наличии правильного дескриптора сокета вы можете получать данные, вызывая функцию Win32 recv через P / Invoke, например:

[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);
    }
  }
}
1 голос
/ 19 апреля 2009

В классе Socket нет ничего для этого - хотя он использует базовый дескриптор, для управления им нет API, а свойство Handle доступно только для чтения.

Возможно, вам лучше всего просто P / Invoking recv и вызвать его напрямую с помощью вашего дескриптора IntPtr.

A быстрый просмотр кода ротора выглядит так, как будто вы можете сойти с рук при создании Socket, закрыв его дескриптор , а затем установив в поле m_handle значение твой собственный. Но для этого требуется Reflection, и если ваш сокет уже подключен (что звучит так, как будто - поскольку вы только что спросили о вызове recv), вам также придется манипулировать закрытым состоянием Socket - что делает эту идею еще менее приятной и более хрупкий.

...