gpt4 book ai didi

c# - 套接字关闭 : when should I use SocketShutdown. 两者

转载 作者:行者123 更新时间:2023-12-03 11:49:23 24 4
gpt4 key购买 nike

我相信关闭顺序如下(如 here 所述):

Socket Shutdown sequence

MSDN documentation (备注部分)内容如下:

When using a connection-oriented Socket, always call the Shutdown method before closing the Socket. This ensures that all data is sent and received on the connected socket before it is closed.



这似乎暗示如果我使用 Shutdown(SocketShutdown.Both) ,任何尚未收到的数据,可能仍会被消费。要测试这个:
  • 我不断地向客户端发送数据(通过 Send 在一个单独的线程中)。
  • 客户端执行 Shutdown(SocketShutdown.Both) .
  • BeginReceive服务器上的回调执行,然而,EndReceive抛出异常:现有连接被远程主机强行关闭。这意味着我无法收到 0返回值,然后调用 Shutdown .

  • 根据要求,我在下面发布了服务器端代码(它被封装在一个 Windows 窗体中,它只是作为一个实验而创建的)。在我的测试场景中,我没有看到 CLOSE_WAIT 状态在 TCPView就像我通常没有发送连续数据一样。所以可能我做错了什么,我错误地中断了后果。在另一个实验中:
  • 客户端连接到服务器。
  • 客户端执行 Shutdown(SocketShutdown.Both) .
  • 服务器收到关闭确认并发送一些数据作为响应。服务器也执行 Shutdown .
  • 客户端从服务器接收数据但下一个 BeginReceive不允许:发送或接收数据的请求被禁止,因为套接字已经在之前的关闭调用中在该方向关闭

  • 在这种情况下,我仍然期待 0来自 EndReceive 的返回值至 Close socket 。这是否意味着我应该使用 Shutdown(SocketShutdown.Send)反而?如果是这样,应该什么时候使用 Shutdown(SocketShutdown.Both) ?

    第一个实验的代码:
    private TcpListener SocketListener { get; set; }
    private Socket ConnectedClient { get; set; }
    private bool serverShutdownRequested;
    private object shutdownLock = new object();

    private struct SocketState
    {
    public Socket socket;
    public byte[] bytes;
    }

    private void ProcessIncoming(IAsyncResult ar)
    {
    var state = (SocketState)ar.AsyncState;
    // Exception thrown here when client executes Shutdown:
    var dataRead = state.socket.EndReceive(ar);
    if (dataRead > 0)
    {
    state.socket.BeginReceive(state.bytes, 0, state.bytes.Length, SocketFlags.None, ProcessIncoming, state);
    }
    else
    {
    lock (shutdownLock)
    {
    serverShutdownRequested = true;
    state.socket.Shutdown(SocketShutdown.Both);
    state.socket.Close();
    state.socket.Dispose();
    }
    }
    }

    private void Spam()
    {
    int i = 0;
    while (true)
    {
    lock (shutdownLock)
    {
    if (!serverShutdownRequested)
    {
    try { ConnectedClient.Send(Encoding.Default.GetBytes(i.ToString())); }
    catch { break; }
    ++i;
    }
    else { break; }
    }
    }
    }

    private void Listen()
    {
    while (true)
    {
    ConnectedClient = SocketListener.AcceptSocket();
    var data = new SocketState();
    data.bytes = new byte[1024];
    data.socket = ConnectedClient;
    ConnectedClient.BeginReceive(data.bytes, 0, data.bytes.Length, SocketFlags.None, ProcessIncoming, data);
    serverShutdownRequested = false;
    new Thread(Spam).Start();
    }
    }

    public ServerForm()
    {
    InitializeComponent();
    var hostEntry = Dns.GetHostEntry("localhost");
    var endPoint = new IPEndPoint(hostEntry.AddressList[0], 11000);
    SocketListener = new TcpListener(endPoint);
    SocketListener.Start();
    new Thread(Listen).Start();
    }

    最佳答案

    Shutdown(SocketShutdown.Both) 禁用当前套接字上的发送和接收操作。调用 Shutdown(SocketShutdown.Both) 是实际的 断线 来自服务器的客户端。您可以通过检查服务器端 SocketState 对象中的 socket Connected 属性来看到这一点:它将是假的。
    发生这种情况是因为 Shutdown 操作是不可逆的,因此在套接字上停止发送和接收之后,由于它是隔离的,因此没有必要保持连接。
    “一旦调用关闭函数来禁用发送、接收或两者,就无法重新启用现有套接字连接的发送或接收。”
    ( https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-shutdown )
    至于你的问题:

  • 我不断地向客户端发送数据(通过在单独的线程中发送)。
  • 客户端执行了 Shutdown(SocketShutdown.Both)。 --> 这会断开客户端
  • 服务器上的 BeginReceive 回调执行,但是,EndReceive 抛出一个
    异常:现有连接被远程主机强行关闭。这意味着
    我无法接收 0 返回值,然后调用 Shutdown。

  • EndReceive 抛出异常,因为客户端套接字不再连接。
    优雅地终止套接字:
  • 客户端套接字调用 Shutdown(SocketShutdown.Send)) 但应该继续接收
  • 在服务器上,EndReceive 返回读取的 0 字节(客户端表示没有更多数据来自其端)
  • 服务器
    A) 发送最后的数据
    B) 调用 Shutdown(SocketShutdown.Send))
    C) 在套接字上调用 Close,可选择超时以允许从客户端读取数据
  • 客户端
    A) 从服务器读取剩余数据,然后接收 0 字节(服务器表示没有更多数据来自其端)
    B) 在套接字上调用 Close

  • ( https://docs.microsoft.com/it-it/windows/win32/winsock/graceful-shutdown-linger-options-and-socket-closure-2?redirectedfrom=MSDN )

    关于c# - 套接字关闭 : when should I use SocketShutdown. 两者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32397370/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com