2009-04-19 4 views
4

Я хочу преобразовать message.WParam в Socket.Как преобразовать IntPtr/Int в Socket?

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 (носок) в Socket, чтобы я мог позвонить Receive()?

ответ

6

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

Учитывая корректный дескриптор сокета, вы можете получить данные, вызвав функцию ПРИЕМ Win32 с помощью 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

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

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

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

+0

На других языках (C++/Delphi) Сокет declarated как целое число. Я думал, WParam.ToUint32() будет работать, но Socket не int в C#. Почему? –

+0

Поскольку Socket - это класс, который управляет собственным состоянием - он инкапсулирует дескриптор (int). –

Смежные вопросы