У меня вопрос по следующему коду:
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-соединения на сервере (это может быть тот же порт или новый).
Сценарий:
1. Пользователь запускает сервер (открывает сокет TCP на локальном IP-адресе и порту 5000.
2. Пользователь останавливает сервер (сервер закрывает TCP-соединение клиентов и сокет сервера)
3. Пользователь снова запускает сервер (тот же порт - 5000 или новый порт, если пользователь изменил порт в настройках приложения).
Когда пользователь снова запускает сервер с тем же портом (5000), я получаю сообщение об ошибке: Невозможно получить доступ к удаленному объекту! Когда пользователь снова запускает сервер с новым портом (5001), я получаю сообщение об ошибке: недопустимый аргумент (поскольку сокет сервера был привязан к другому порту).
Если я удалю код serverSocket.Close();
он будет работать, потому что только без изменения порта из-за того, что сокет сервера никогда не был закрыт. Посмотрите netstat в этом случае:
![enter image description here](https://i.stack.imgur.com/4EgwK.png)
Но это плохо, потому что это не позволяет изменить порт, пока конфигурация не будет сохранена и пользователь не перезапустит приложение.