如何在C#中调用和使用WSAAsyncSelect()?

时间:2009-03-26 15:49:26

标签: c# asynchronous callback

我在设置赏金时编辑了我的问题。 我想从WinAPI调用/ DllImport WSAAsyncSelect()并使用它,就像我在Delphi / C ++中使用它一样

例如 - Delphi

//Async CallBack handler Declaration
procedure MessageHandler(var Msg:Tmessage);Message WM_WINSOCK_ASYNC_MSG;

//Where i setup the Async
dwError := WSAAsyncSelect(Sock, form1.handle, WM_WINSOCK_ASYNC_MSG, FD_CLOSE or FD_READ);

//Async Callback Handler
procedure Tform1.MessageHandler(var Msg:Tmessage);
begin
  case WSAGetSelectEvent(MSG.LParam) of //LParam is FD_READ/FR_CLOSE/FD_WRITE
    FD_READ: OnSocketRead(MSG.WParam); //WPARAM is the Socket itself.
    FD_CLOSE: OnSocketClose(MSG.WParam);
  end;
end;

提前致谢!

2 个答案:

答案 0 :(得分:4)

我做到了! Finaly !!!

WSAAsyncSelect()结构

    [DllImport("wsock32.dll")]
    public static extern int WSAAsyncSelect(
    int socket,
    int hWnd,
    int wMsg,
    int lEvent
    );

WS2 Class

public class WS2
{
    public static Socket sock;
    public static byte[] data = new byte[8096];
    public static int server = 0;
    public static bool forced = true;

    public static void Close()
    {
        //Extern.closesocket(sock.Handle.ToInt32());
        //Extern.WSACleanup();

        sock.Shutdown(SocketShutdown.Both);
        sock.Close();

        if (forced)
        {
            Connect();
        }
    }
    public static void ConnectTo(string ip,int port)
    {
        sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sock.Connect(ip, port);

        int handle = 0;
        var form1 = Form.ActiveForm as FormMain;
        if (form1 != null)
            handle = form1.GetHandle;
        if (handle == 0)
        {
            FormMain.PerformActionOnMainForm(form => form.memo.Text += "An error occured: Error code WS_01_ASYNC_HANDLE");
            return;
        }
        Extern.WSAAsyncSelect(sock.Handle.ToInt32(), handle, Values.MESSAGE_ASYNC, Values.FD_READ | Values.FD_CLOSE);
    }

    public static void Connect()
    {
        //Get IP && port
        string ip = GetIPFromHost("gwgt1.joymax.com");
        if (ip == "")
        {
            ip = GetIPFromHost("gwgt2.joymax.com");
            if (ip == "")
            {
            }
            server +=2;
        }
        else
            server +=1;

        int port = 15779;

        //
        ConnectTo(ip, port);
    }

    public static void Receive()
    {
        int size = sock.Receive(data);
        if (size == 0)
        {
            FormMain.PerformActionOnMainForm(form => form.memo.Text += "An error occured: Error Code WS_02_RECV_BEGN");
        }

        Main.Handle(data, size);
    }

    public static string GetIPFromHost(string HostName)
    {
        IPHostEntry ip;
        try
        {
            ip = Dns.GetHostEntry(HostName);
        }
        catch (Exception)
        {
            return "";
        }
        return ip.AddressList[0].ToString();
    }
}

Form类中的WndProc。

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

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

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

获取句柄:

    public int GetHandle
    {
        get
        {
            if (this.InvokeRequired)
            {
                return (int)this.Invoke((GetHandleDelegate)delegate
                {
                    return this.Handle.ToInt32();
                });
            }
            return this.Handle.ToInt32();
        }
    }
    private delegate int GetHandleDelegate();

答案 1 :(得分:0)

(编辑:主要与原始问题有关,在编辑之前加上赏金)

我最近一直在关注这个问题 - 请参阅Async without the pain。请注意最后关于使用委托版本的注释 - 这会略微简化调用。

作为更新,最终的代码看起来如下所示,因为它发现与F#在引擎盖下使用的内容非常相似:

public static void RunAsync<T>(
    Func<AsyncCallback, object, IAsyncResult> begin,
    Func<IAsyncResult, T> end,
    Action<Func<T>> callback) {
    begin(ar => {
        T result;
        try {
            result = end(ar); // ensure end called
            callback(() => result);
        } catch (Exception ex) {
            callback(() => { throw ex; });
        }
    }, null);
}