TcpClient套接字 - 每个套接字地址异常只有一种用法

时间:2015-12-06 14:44:22

标签: c# .net sockets tcpclient

使用TcpClient和TcpListener时抛出此异常,我有点失落。它第一次工作,然后我再次运行它,我得到以下异常:

通常只允许使用每个套接字地址(协议/网络地址/端口)127.0.0.1:8086

我已经检查过以确保关闭所有打开的连接。我试过在TcpClient上手动调用close以及使用IDisposable使用模式但仍然有同样的问题。

这是代码,如果您在Visual Studio中复制粘贴它应该运行(前提是您已添加以下使用语句)

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

internal class Program
{
    private static void tcpClientConnection()
    {
        Console.WriteLine("Ready");
        Console.ReadKey();

        IPAddress address = IPAddress.Parse("127.0.0.1");

        using (TcpClient client = new TcpClient(new IPEndPoint(address, 8087)))
        {
            client.Connect(new IPEndPoint(address, 8086));

            using (NetworkStream ns = client.GetStream())
            {
                ns.Write(System.Text.Encoding.ASCII.GetBytes("Hello"), 0, "Hello".Length);
                ns.Flush();
            }

            Console.WriteLine("Closing client");
        }
    }

    internal static void Main(string[] args)
    {
        IPAddress address = IPAddress.Parse("127.0.0.1");

        TcpListener server = new TcpListener(new IPEndPoint(address, 8086));
        server.Start();

        using (Task task2 = new Task(tcpClientConnection))
        {
            task2.Start();

            using (TcpClient client = server.AcceptTcpClient())
            {
                using (NetworkStream ns = client.GetStream())
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        ns.CopyTo(ms);
                        byte[] data = ms.ToArray();

                        Console.WriteLine(System.Text.Encoding.ASCII.GetString(data));
                    }
                }
            }

            Console.WriteLine("Server stop");
            Console.ReadKey();

            server.Stop();
        }

        Console.WriteLine("END");
        Console.ReadKey();

    }
}

请注意,我已经查看了类似问题中提供的解决方案,但未能看到问题所在......

2 个答案:

答案 0 :(得分:1)

对于TcpClient,请不要指定本地端点。我认为这解决了问题,你不应该这样做,因为它什么也没做。  指定传出连接的本地端点使操作系统选择适当的值和可用值。通常,99.9%的程序都是这样做的。

  

如果所有连接都已关闭,是否可以继续使用相同的地址和端口?

TCP有一些不直观的行为导致连接在关闭后暂停一段时间。通过让操作系统为您选择一个可以减轻问题的新端口。

您还可以查看Task的使用情况并选择一些最佳做法:使用Task.Run并且不要处置。这毫无意义。

答案 1 :(得分:0)

我发现一些设置在重用指定了本地端点的套接字时似乎可以大大减少(但不能完全消除)此错误:

tcpClient.Client.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true );
tcpClient.LingerState = new LingerOption( true, 0 );

我可能还应该提到在关闭tcpClient之前,我先关闭客户端的流并执行以下操作:

if ( tcpClient.Client.Connected )
    tcpClient.Client.Shutdown( SocketShutdown.Both );

这可能会有所帮助,但是如果有人发现完全可以防止出现此错误的内容,请分享。