我对以下代码有疑问:
private static readonly Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private static readonly List<Socket> clientSockets = new List<Socket>();
private const int BUFFER_SIZE = 1024*2;
private static readonly byte[] buffer = new byte[BUFFER_SIZE];
public static Manager Manager { get; set; }
private static bool firstInit = true;
/// <summary>
/// Config and start the server
/// </summary>
public static void SetupServer()
{
try
{
Manager.PCForm.ConnectionButtonStatus(false);
var PORT = int.Parse(Properties.Settings.Default.LocalPort);
var listenToAny = Properties.Settings.Default.ListenToAny;
var IP = GetSocketIP(listenToAny);
Logger.LogInfo("Setting up server...");
if(Properties.Settings.Default.UseLocalWifiNetwork)
{
Logger.LogInfo("PC Local IP: " + LocalIPAddress);
}
else
{
Logger.LogInfo("PC External IP: " + ExternalIPAddress);
}
if(firstInit)
{
firstInit = false;
Logger.LogDebug("Binding new port:" + PORT);
serverSocket.Bind(new IPEndPoint(IP, PORT));
}
else
{
Logger.LogDebug("Using port that was already binded");
}
serverSocket.Listen(0);
Logger.LogDebug("Listening To: " + IP + ":" + PORT);
serverSocket.BeginAccept(AcceptCallback, null);
Manager.PCForm.ConnectionButtonStatus(true);
Logger.LogInfo("Server setup complete");
}
catch(Exception ex)
{
FormsHelpers.ShowErrorMessage(ex.Message);
Logger.LogError("Fail to setup server. Please restart the app.");
}
}
public static void CloseAllSockets()
{
try
{
Logger.LogDebug("Closing All Sockets...");
Manager.PCForm.ConnectionButtonStatus(false);
foreach(Socket socket in clientSockets.ToArray())
{
CloseSocket(socket);
}
serverSocket.Close();
Logger.LogInfo("Server was shutdown");
Manager.PCForm.ConnectionButtonStatus(true);
}
catch(Exception ex)
{
Console.WriteLine("Fail to close sockets.\r\nExpection: " + ex.Message);
}
}
当我想重用绑定的套接字时,我的问题开始了。我的应用程序支持关闭并重新打开服务器中的TCP连接(可以是同一端口,也可以是新端口)。
场景:
[当用户使用相同的端口(5000)再次启动服务器时,出现错误:无法访问已处置的对象!当用户使用新端口(5001)再次启动服务器时,出现错误:无效参数(因为服务器套接字已绑定到其他端口)。
如果删除代码serverSocket.Close();
,它将起作用,因为服务器套接字从未关闭,因此无需更改端口即可。在这种情况下,请查看netstat:
但是这不好,因为除非保存了配置并且用户重新启动了应用程序,否则不允许更改端口。
我更新了代码。当我关闭服务器时,我仅断开客户端连接。当我启动服务器时,我会重用最后一个套接字,但是如果更改端口,我将关闭它并分配一个新的socketServer实例并使用它。
if(portInUse.Equals(PORT))
{
Logger.LogDebug("Using port that was already binded");
}
else
{
Logger.LogDebug("Binding new port:" + PORT);
if(serverSocket != null)
{
//close previous socket because it was using old port
serverSocket.Close();
}
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IP, PORT));
portInUse = PORT;
}