【问题标题】:C# Client/Server socket will not connect again after it has been disconnectedC#客户端/服务器套接字断开后将不再连接
【发布时间】:2017-09-26 21:57:29
【问题描述】:

我正在构建一个基于服务器和客户端的应用程序,它通过套接字(典型的东西)进行通信。

预期的功能是客户端连接,它们来回发送一些数据,然后客户端关闭连接。一段时间后,客户端重新连接,他们来回发送更多信息,然后再次断开连接。

该过程的第一步工作正常。客户端连接,BeginAccept 根据需要触发,然后他们聊了一会儿。连接似乎关闭得很好(Disconnect()),逻辑运行并再次调用 BeginAccept。但是,如果客户端再次尝试连接,AcceptCallback 将不会触发。

网上其他问题/答案提示socket需要恢复,但我这里是这样做的。

在实际版本中(在此处进行了修剪)我有大量的异常处理和日志记录,但没有异常或错误可以使用。

如果我重新启动服务,它会再次运行(但只有一次),这让我相信这是我的服务器代码而不是我的客户端。 似乎 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
    }

}

【问题讨论】:

    标签: c# sockets


    【解决方案1】:

    问题是你再也不会打电话给BeginAccept()。实际上,一旦获得第一个连接,您就会丢弃原来的侦听套接字。

    关于如何编写基于套接字的网络代码的正确示例有很多,因此我不会过多介绍。特别是,因为这里没有一个好的Minimal, Complete, and Verifiable code example 可以使用。但是,在您发布的代码中,似乎需要的主要更改是替换:

       this.listener = handler;
    

    与:

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

    没有足够的上下文来了解您的第一个 sn-p 中的其他代码在做什么,但您可能也应该删除它:

    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。

    【讨论】:

    • 感谢您提供有关 BeginAccept() 的信息。我给出的第一个代码 sn-p 在循环中运行。所以我再次调用 BeginAccept()。但是,我应用了您的第一个建议并停止了循环并且它起作用了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多