Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:System.Net.Sockets.TcpListener有时无法正确关闭套接字_C#_Sockets_Tcp_Tcplistener - Fatal编程技术网

C#:System.Net.Sockets.TcpListener有时无法正确关闭套接字

C#:System.Net.Sockets.TcpListener有时无法正确关闭套接字,c#,sockets,tcp,tcplistener,C#,Sockets,Tcp,Tcplistener,在我的一个项目中,我实现了一个小型HTTP服务器,用于流式传输连接的网络摄像头的视频数据。对于此任务,我将使用.Net Framework 4.5中的System.Net.Sockets.TcpListener,它侦听预配置的端点,并使用AcceptSocketAsync()mtehod等待输入请求。您可以在下面看到相关的代码部分: this.server = new TcpListener(endpoint); this.server.Server.SetSocketOption(Socket

在我的一个项目中,我实现了一个小型HTTP服务器,用于流式传输连接的网络摄像头的视频数据。对于此任务,我将使用.Net Framework 4.5中的System.Net.Sockets.TcpListener,它侦听预配置的端点,并使用AcceptSocketAsync()mtehod等待输入请求。您可以在下面看到相关的代码部分:

this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);

...

private async void Listen()
{
    try
    {
        while (this.server.Server.IsBound)
        {
            Socket socket = await this.server.AcceptSocketAsync();
            if (socket == null)
            {
                break;
            }

            Task.Factory.StartNew(() => this.ClientThread(socket));
        }
    }
    catch (ObjectDisposedException)
    {
        Log.Debug("Media HttpServer closed.");
    }
}
当我启动应用程序并且HTTP服务器第一次启动时,这一切都很好。但是,当我停止HTTP服务器(通过应用程序设置中的复选框完成)时,未传送的侦听套接字有时不会关闭。当我通过控制台(netstat-ano)检查套接字的状态时,我可以看到套接字仍然处于监听状态。由此产生的问题是,当我再次重新启动HTTP服务器时,我得到一个System.Net.Sockets.SocketException,其中包含消息“每个套接字地址通常只允许使用一次”,这并不奇怪

停止HTTP服务器的相关代码部分如下所示:

...
if (this.server != null)
{
    if (this.server.Server != null)
    {
        if (this.server.Server.Connected)
        {
            this.server.Server.Shutdown(SocketShutdown.Both);
            this.server.Server.Disconnect(true);
        }

        this.server.Server.Close();
    }

    this.server.Stop();
}
...
我还跟踪打开的连接,并在完成数据传输和停止服务器时关闭它们。没有一个连接插座保持打开状态,因此我认为只有侦听插座应该与此问题相关

在停止服务器时,我已经尝试了Shutdown()、Disconnect()、Close()和Stop()方法的各种组合/顺序,以及在启动服务器时设置/取消设置几个选项,如Linger和ReuseAddress,这在一开始似乎可以解决问题,但几天后问题再次出现

我还尝试在使用iphlapi.dll中的GetTcpTable(…)和SetTcpEntry(…)停止服务器时“强制”侦听套接字关闭,如本问题所述: 不幸的是,这种方法对我不起作用(它根本改变了侦听套接字的状态)

由于我有点不知道我还能做些什么,我在这里问,是否有人知道什么可能导致所描述的问题,或者如何解决它。任何帮助都将不胜感激

亲切问候,,
克里斯

一旦你关闭了你的套接字连接,我会处理掉它们。文档中说它们应该在关闭后处理,但我个人想说什么时候处理使用IDisposable接口的任何东西。

如果您没有任何特殊要求,建议仅使用
TcpListener
类及其方法,或者如果您有此类要求,不要使用
TcpListener
并从原始套接字开始

TcpListener
类是自给自足的,可以提供类似

Start()、acceptcpclient()
Stop()

TcpListener
实例上调用
Stop()
后,您可以创建一个
列表
并循环遍历每个客户端并调用
client.close()

MSDN上有一个很好的客户机-服务器通信示例:


关于

您几乎应该总是让
TcpListener.Server
一个人呆着。它就在那里,所以你可以在它上面设置套接字选项,而不是将它用于控制目的

因此,您的
收听应该是:

private async void Listen()
{
    try
    {
        while (true)
        {
            Socket socket = await this.server.AcceptSocketAsync();
            if (socket == null)
            {
                break;
            }

            Task.Run(() => this.ClientThread(socket));
        }
    }
    catch (ObjectDisposedException)
    {
        Log.Debug("Media HttpServer closed.");
    }
}
(假设您确实希望每个客户端有一个线程,我一般不推荐这种架构)

当您准备停止时,只需停止:

if (this.server != null)
{
    this.server.Stop();
}

在服务器套接字上,侦听套接字不需要关闭和断开连接。只有已连接的套接字才需要这些调用。用以下代码更换插座止动块:

if (this.server != null)
{
    if (this.server.Server != null)
    {
        this.server.Server.Close();
        this.server.Server = NULL;
    }

}

你成了迷信模式的牺牲品。您可以通过多种方式进行处理,并检查各种情况<代码>服务器.Dispose()就足够了,不会产生这个问题。