在同一端口上重新打开 Tcp 套接字

Reopen Tcp socket on the same port

我有一个用于单一请求-响应目的的套接字。

我将它设置在端口 XXX 上让它等待连接、读取数据并回复一些数据。

我想在同一端口上打开一个新套接字。一旦发送响应。

这是外部处理的(有一个管理器正在检查线程的状态,如果它被使用,它会处理它并创建一个新的。

问题是它在

上被阻止
_socket = _socket.Accept();

并且当新客户端尝试连接时,它永远不会离开此行。 (客户没有得到回复)。

插座是运行在

new Thread(Run);

这是我的 运行 方法:

private void Run()
{
    var ipHostInfo = Dns.Resolve(Dns.GetHostName());
    var ipAddress = ipHostInfo.AddressList[0];
    var localEndPoint = new IPEndPoint(ipAddress, Port);
    _socket = new Socket(AddressFamily.InterNetwork,
        SocketType.Stream, ProtocolType.Tcp);
    try
    {
        _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        _socket.Bind(localEndPoint);
        _socket.Listen(100);
        _socket = _socket.Accept();
        var data = string.Empty;
        while (true)
        {
            var bytes = new byte[1024];
            var bytesRec = _socket.Receive(bytes);
            data += Encoding.UTF8.GetString(bytes, 0, bytesRec);
            if (data.IndexOf("<EOF>", StringComparison.Ordinal) <= -1) continue;
            var dataWithoutEof = data.Substring(0, data.IndexOf("<EOF>", StringComparison.Ordinal));
            //TODO: do smt with the data
            break;
        }
        var byteData = Encoding.UTF8.GetBytes("testResponse" + "<EOF>");
        _socket.Send(byteData);

        _socket.Shutdown(SocketShutdown.Both);
        _socket.Close();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
}

我想我没有正确关闭现有套接字。

你的代码是错误的,你不应该期望这个方法退出,因为你希望你的服务器在整个过程中 运行ning。我在这里假设您多次调用 运行 。不要那样做。 然后代码变成这样:

_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_socket.Bind(localEndPoint);
_socket.Listen(100);
while (true)
{
    var _servicingsocket = _socket.Accept();
    ....
    _servicingsocket.close();
}

accept 是一个阻塞调用。等待新的连接。 _socket 是一个侦听套接字,必须在服务器的生命周期内保留。

TCP 连接基于套接字对的概念。
服务器启动时,您有一个侦听端口 100 的套接字。 假设建立了一个连接,然后接受 returns 所谓的服务套接字,它基本上是侦听套接字的克隆。这意味着它也使用源端口 100,但因为它是服务套接字,所以它属于标识连接的套接字对。套接字对是 2 个套接字的组合,您自己的套接字和对等套接字。当有数据传入时,TCP 将遍历套接字对以找到正确的套接字。

这样做的另一个好处是,当您处理第一个请求时,您允许其他连接尝试在侦听套接字上排队。您的 _socket 被服务套接字覆盖,然后您假设侦听套接字将被垃圾收集。我不确定这是否会发生,因为我没有像您在代码中那样尝试过,因为这首先是个坏主意,因为它实现了 idisposable。 (https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)如果你真的想关闭服务器,你必须确保关闭服务套接字和监听套接字以使代码干净。