2

賞金を設定するときに質問を編集しました。WinAPI から Invoke/DllImport WSAAsyncSelect() を使用し、Delphi/C++ で使用するのと同じように使用したい

例 - デルファイ

//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;

前もって感謝します!

4

2 に答える 2

4

やった!最後に!!!

WSAAsyncSelect() 構造体

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

WS2クラス

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();
于 2009-04-19T15:42:36.620 に答える
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);
}
于 2009-03-26T16:00:50.477 に答える