views:

823

answers:

2

Hello,

I edited my question when I set the bounty. I want to Invoke/DllImport WSAAsyncSelect() from WinAPI and use it much like I use it in Delphi/C++

For example - 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;

Thanks in advance!

A: 

(edit: relates mainly to the original question, before it was edited and a bounty added)

I've been looking at this problem recently - see Async without the pain. Note the comment at the end about using the delegate version - this simplifies the calling slightly.

As an update, the final code would look something like below, and as it transpires is very similar to what F# uses under the bonnet:

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);
}
Marc Gravell
+2  A: 

I made it! Finaly!!!

WSAAsyncSelect() structure

    [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();
    }
}

WndProc in the Form class.

    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);
        }
    }

Get Handle:

    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();
John