2013-03-31 113 views
1
Socket SocketSrv; 
public static ManualResetEvent Done = new ManualResetEvent(false); 
IPEndPoint IPP = new IPEndPoint(IPAddress.Any, 1234); 

void Listening() 
{ 
    SocketSrv = new Socket(AddressFamily.InterNetwork, 
          SocketType.Stream, ProtocolType.Tcp); 
    try 
    { 
     SocketSrv.Bind(IPP); 
     SocketSrv.Listen(5); 

     while (true) 
     { 
      Done.Reset(); 
      info.Text = "Waiting for connections...."; 
      SocketSrv.BeginAccept(new AsyncCallback(Connection), 
            SocketSrv); 
      Done.WaitOne(); 
     } 
    } 
    catch(Exception error) 
    { 
     MessageBox.Show(error.Message); 
    } 
} 

void Connection(IAsyncResult ar) 
{ 
    Done.Set(); 
    Socket con= (Socket)ar.AsyncState; 
    Socket handler = con.EndAccept(ar); 
} 

我想了解在此異步操作中的ManualResetEvent,因爲我從來沒有使用它。瞭解異步服務器套接字中的ManualResetEvent

  • Step1。 SocketSrv被創建爲接受TCP連接,並且發送和接收「命令」的類型是流。

  • Step2。套接字與ip,port綁定,然後我們開始監聽連接。

  • Step3。在while循環:

    • ManualResetEvent復位(據我所知,ManualResetEvent是一類爲布爾類型,並指出當線程正忙或沒有)。在這種情況下,事件總是被複位,因爲如果有連接並且另一個連接正在進行,我需要重置它並再次啓動「操作」。

    • BeingAccept我正在啓動異步操作,執行的回調函數和IAsyncResult參數將成爲「套接字」。

  • Step4。 ResetEvent現在正在等待阻止當前線程並等待連接方法中的處理程序結束,以便它可以完成初始化當前連接。

  • Step5。在連接線程中,ResetEvent將信號設置爲真,這意味着...以及我不知道它是什麼意思。我認爲它告訴ResetEvent解鎖主線程。

在'con'插座中,我得到了AsyncState。我不知道這是什麼意思。

在處理程序套接字中,我告訴ResetEvent已建立連接。

有人說,有人可以告訴我,如果我說的是真/錯,爲什麼?

+0

這是毫無意義的。只需使用非異步版本SocketSrv.Accept()即可在沒有事件的情況下獲得完全相同的結果。 –

+0

不是真的..因爲我會繼續添加讀取,使用異步操作進行寫入,以便在執行其他操作時可以接受多個連接。 – Leo

+0

在Done.WaitOne()調用中阻止代碼時,沒有任何內容處於「繼續」狀態。也許你打算使這個異步,它只是不是在它的當前版本。 –

回答

1

該事件用於在發生連接時BeginAccept在調用Connect方法之前不會被再次調用。例如WaitOne停止線程,直到調用Set。調用Reset將事件的狀態重新設置爲發信號,以便WaitOne將再次暫停該線程,以便它將等待Connect再次被調用。

就我個人而言,我不使用這種特殊模式。我從來沒有看到過這種模式的解釋。如果在BeginAccept循環和Connect方法之間存在某種共享狀態,則可能有意義。但是,正如所寫的,任何國家都不會因使用該事件而受到保護。當我使用BeginAccept時,我只是不使用事件,而且我已經使用這樣的代碼來處理多次連接。使用事件將不會做任何事情以防止一次連接太多的錯誤。坦率地說,使用異步方法並強制它有效地同步就會失敗。

BeginAccept的角度來看,AysncState僅僅是不透明的數據。這是用於特定異步操作的「狀態」。這個「狀態」是特定於應用程序的。當你想異步處理連接時,你可以使用任何你需要的東西。在BeginAccept回調的情況下,您通常希望對服務器套接字執行某些操作,並將其傳入該狀態,以便您可以訪問該套接字以致電EndAccept。由於SocketSrv是一個成員字段,你真的不需要要做到這一點,你可以這樣做,而不是:

SocketSrv.BeginAccept(new AsyncCallback(Connection), null); 
//... 
void Connection(IAsyncResult ar) 
{ 
    Socket handler = SocketSrv.EndAccept(ar); 
    //... 
} 

您的評論似乎表明你的代碼特定位把握好。您的「Step4」有點關閉,它不等待Connection方法結束,僅僅爲了開始(因爲Set被稱爲第一行)。並且是的,「Step5」,Set表示它將取消阻止WaitOne,因此主線程調用Reset,然後BeginAccept