2009-03-26 2 views
2

현상금을 설정할 때 제 질문을 편집했습니다. 내가 호출 할 /WinAPI를에서 같이 DllImport WSAAsyncSelect 함수()와 델파이에서 사용 많은처럼 사용/C++C#에서 WSAAsyncSelect()를 호출하고 사용하는 방법은 무엇입니까?

예를 들어

-

미리 감사드립니다 델파이

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

+0

그것은 ++ 닷넷에서 낮은 수준의 API와 상호 작용하기 쉽지 않다. 그것에 대해 아무런 논쟁 거리가 없습니다. 아마 당신의 문제에 잘못된 해결책을 적용하려고합니다. 귀하의 질문에 대한 답변이 아니지만 프레임 워크를 보면 기능이 상위 레벨에있을 수 있습니다. –

+0

어쩌면 당신이 원하는 것을 ** ** 수행하고 싶은 ** (즉, 원하는 행동이 무엇인지) ** (** WSAAsyncSelect) - 당신은 무엇을하고 싶습니까? –

+0

BeginRecv 대신 그 API를 사용하는 것이 훨씬 간단합니다. 문제는 현재의 작업을 끝내기 전에 다음 패킷을 받는다는 것입니다. 의미 현재받은 패킷 (어느 정도 시간이 걸립니다)을 다음 패킷 분실되었다. –

답변

4

내가 그것을했다! Finaly !!!

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

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

가져 오기 핸들 : 관리되지 않는 C에서와 같이

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(); 
+0

아주 좋습니다. 이렇게하면 C# .NET Framwork의 큰 문제를 해결할 수 있습니다. UI 스레드에서 완료를 위해 비동기 소켓 읽기를 대기열에 넣을 방법이 없습니다. –

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); 
} 
관련 문제