2017-09-26 67 views
1

我正在構建一個基於服務器和基於客戶端的應用程序,它通過套接字(典型的東西)進行通信。C#客戶端/服務器套接字在斷開連接後將不會再次連接

預期的功能是客戶端連接,它們來回發送一些數據,然後客戶端關閉連接。一段時間後,客戶端重新連接,他們來回發送更多信息,並再次斷開連接。

該過程的第一步正常工作。客戶端連接,BeginAccept根據需要熄滅,並且他們聊了一會兒。連接似乎關閉就好(Disconnect()),邏輯運行並再次調用BeginAccept。但是,如果客戶端嘗試再次連接,AcceptCallback將不會觸發。

在線其他問題/答案建議套接字需要恢復,但我這樣做。

在真實版本(這裏修剪)我有廣泛的異常處理和日誌記錄,但沒有任何例外或錯誤的工作。

如果我重新啓動服務,它將再次運行(但只有一次),這導致我相信這是我的服務器代碼,而不是我的客戶端。 看來AsyncCallback根本不會再被觸發。

我做錯了什麼,所以我不能連接多次? 謝謝!

在服務器上,在一個線程我有以下(這被稱爲在一開始,以及當切斷信號從客戶端發送):

try 
{ 
    //check connected, and if not connected, then close socket and reopen 
    if (mDisconnectFlag == true) 
    { 
     mDisconnectFlag = false; 
     this.Disconnect(); 
    } 

    if (listener == null || listener.Connected == false) 
    { 
     // Create a TCP/IP socket. 
     this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     this.listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); 

     // Bind the socket to the local endpoint and listen for incoming connections. 
     this.listener.Bind(localEndPoint); 
     this.listener.Listen(10); 
     // Start an asynchronous socket to listen for connections. 
     this.listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
    } 
    else if (listener.Connected == false || mAcceptCallBackFlag == true) 
    { 
     // Start an asynchronous socket to listen for connections. 
     this.listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

    } 
    // Wait until a connection is made before continuing. 
    _retevent = ProcessSocketEvent.WaitOne(mSocketProcessTimeInterval, false); 
} 
catch (Exception ex) 
{ 
    //logging - don't worry about this 
} 

斷線如下:

public void Disconnect() 
{ 
    try 
    { 
     this.listener.Shutdown(SocketShutdown.Both); 
     this.listener.Disconnect(false); 
     this.listener.Dispose(); 
     listener = null; 
    } 
    catch (Exception ex) 
    { 
     //logging 
    } 

} 

最後,回電:

public void AcceptCallback(IAsyncResult ar) 
{ 
    try 
    { 
     // Get the socket that handles the client request. 
     Socket listener = (Socket)ar.AsyncState; 
     Socket handler = listener.EndAccept(ar); 
     this.listener = handler; 

     // Create the state object. 
     StateObject state = new StateObject(); 

     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
      new AsyncCallback(ReadCallback), state); 
     mAcceptCallBackFlag = true; 
    } 
    catch (Exception ex) 
    { 
     //logging 
    } 

} 

回答

0

的問題是,你永遠不打電話再次,。事實上,只要你第一次連接,你就會丟棄原來的監聽套接字。

有很多關於如何編寫基於套接字的網絡代碼的正確示例,所以我不會詳細討論。尤其是,因爲這裏沒有合適的Minimal, Complete, and Verifiable code example。但是,在您發佈的代碼,這似乎是所需要的主要變化是更換:

this.listener = handler; 

有:

this.listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

有沒有足夠的上下文知道在你的第一個片段的其他代碼是這樣做的,但很可能你也應該刪除此:

else if (listener.Connected == false || mAcceptCallBackFlag == true) 
{ 
    // Start an asynchronous socket to listen for connections. 
    this.listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 

} 

並沒有什麼會設置ProcessSocketEvent您等待就在這裏:

_retevent = ProcessSocketEvent.WaitOne(mSocketProcessTimeInterval, false); 

如果這不在你省略的代碼部分,你應該擺脫WaitOne()調用,或者確保你設置了事件句柄。同樣,目前還不清楚該代碼的目的是什麼。如果你處在一個你期望再次撥打BeginAccept()的循環中,你就混合了你的範例(一個不幸的後果,有時人們會按照MSDN套接字示例發生,這很可怕)。如果要在循環中阻止並接受,則只需使用同步方法Accept()。如果你想使用BeginAccept(),那麼你不需要循環;在完成回調方法中調用EndAccept()後,請撥打BeginAccept()

如果您需要更多的幫助,請改善問題並確保有一個好的MCVE。

+0

感謝您提供有關BeginAccept()的信息。我給出的第一個代碼片段是循環運行的。所以我再次調用BeginAccept()。但是,我應用了您的第一個建議並停止了循環,並且它可以正常工作。 – Jonathan

相關問題