2013-03-31 76 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