【发布时间】:2018-07-17 18:24:22
【问题描述】:
多次运行我的程序时,我不断收到SocketException: Address already in use。
小例子:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace test
{
class Program
{
static TcpListener listener;
static void Main(string[] args)
{
listener = new TcpListener(new IPEndPoint(IPAddress.Any, 3349));
listener.Start();
listener.BeginAcceptSocket(Accept, null);
Console.WriteLine("Started!");
// Simulate a random other client connecting, nc localhost 3349 does the same thing
var client = new TcpClient();
client.Connect("localhost", 3349);
Thread.Sleep(2000);
listener.Stop();
Console.WriteLine("Done!");
}
static void Accept(IAsyncResult result)
{
using(var socket = listener.EndAcceptSocket(result))
{
Console.WriteLine("Accepted socket");
Thread.Sleep(500);
socket.Shutdown(SocketShutdown.Both);
}
Console.WriteLine("Socket fully closed");
}
}
}
运行程序两次 (dotnet run):第一次会正常完成,但第二次会失败,提示“地址已在使用”。
请注意,client 的丢失处置不是这里的问题——我可以使用 nc localhost 3349 手动复制相同的错误。
如何清理监听器以免遇到错误?
操作系统和 .NET 信息:
dotnet --version
2.1.103
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.4 LTS
Release: 16.04
Codename: xenial
此问题在 Windows 上不存在。使用mono时也不会出现这种情况,所以这似乎是特定于微软的linux实现。
【问题讨论】:
-
解决方法可能是使用SetSocketOption() 将ReuseAddress 设置为
true。 -
@itsme86 谢谢!我还没有想到。您是否会碰巧知道该选项是否有任何副作用? (只要同时运行的程序实例不超过一个)
-
我自己过去用过,没有任何副作用。如果有的话,我不知道。
-
在服务器中使用
SO_REUSEADDR是相当标准的。使用它出现问题的可能性实际上很小。首先解释问题的原因在这里:stackoverflow.com/a/3233022/1076479