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

时间:2015-05-23 10:05:05

标签: c# sockets tcp tcpclient

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

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

我想在同一个端口上打开一个新套接字。一旦发送了回复。

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

问题是它在

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

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

套接字正在

中运行
new Thread(Run);

这是我的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());
    }
}

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

1 个答案:

答案 0 :(得分:1)

您的代码错误,您不应期望此方法退出,因为您希望服务器一直运行并运行。我在这里假设你多次打电话。不要那样做。 代码变成这样的东西:

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

接受是一个阻止通话。等待新的连接。 _socket是一个侦听套接字,必须在服务器的生命周期内保留。

TCP连接基于套接字对的概念 当服务器启动时,您有一个侦听端口100的插槽。 假设建立了连接,然后accept返回所谓的服务套接字,该套接字基本上是来自侦听套接字的克隆。这意味着它也使用源端口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)如果你真的想要关闭服务器,你必须确保关闭服务套接字和监听套接字以使代码干净。