2017-09-26 88 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

相关问题