私はこのように動作する単純なクライアントサーバーアプリケーションを持っています:サーバーは常にクライアント接続を(別のスレッドで)リッスンしています(サーバーに強制終了させたいプロセスの名前を送信します)。
サーバーは次のとおりです。
private void btnStart_Click(object sender, EventArgs e)
{
_port = int.Parse(comboBoxPorts.SelectedItem.ToString());
_tcpListener = new TcpListener(_ipAddress, _port);
_keepRunning = true;
_listenerThread = new Thread(Listen);
HandleListenerThreadStartListenEvent += HandleListenerThreadStartedEventMethod;
ListenerThreadStartedEvent += HandleListenerThreadStartListenEvent;
_listenerThread.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (_tcpListener != null)
{
_keepRunning = false;
if (_tcpListener.Server.Connected)
{
_tcpListener.Server.Disconnect(true);
}
_tcpListener.Stop();
}
labelServerStatus.Text = "Server is stopped";
comboBoxPorts.Enabled = true;
btnStart.Enabled = true;
btnStop.Enabled = false;
}
private void Listen()
{
try
{
_tcpListener.Start();
OnListenerThreadStartListenEvent(); // just update the GUI
}
catch(Exception e)
{
MessageBox.Show("Port " + _port + " is NOT available." + Environment.NewLine +
"Please choose another one: " + e.Message);
return;
}
_keepRunning = true;
string ballonMessage = "Socket Server Running at " + _ipAddress + ", port: " + _port;
notifyIcon1.ShowBalloonTip(2000, "Simplex Listener", ballonMessage, ToolTipIcon.Info);
while (_keepRunning)
{
try
{
#region using AcceptSocket()
_clientSocket = _tcpListener.AcceptSocket();
string checkString = string.Empty;
IPAddress ipOfClient = ((IPEndPoint) _clientSocket.LocalEndPoint).Address;
notifyIcon1.ShowBalloonTip(2000, "Simplex Listener", "New client has connected from ip " + ipOfClient, ToolTipIcon.Info);
byte[] buffer = new byte[SIZE_OF_BUFFER];
int bytesReceived = _clientSocket.Receive(buffer);
// Concatenate chars as bytes to a received string.
for (int i = 0; i < bytesReceived; i++)
checkString += Convert.ToChar(buffer[i]);
//..... getting the name of process and kill it (and than open it...
RestartProcess(nameOfProcess, windowName, pathToExeFile);
// Client is waiting to know operation is complete- so send him some char...
ASCIIEncoding encoder = new ASCIIEncoding();
_clientSocket.Send(encoder.GetBytes("v"));
_clientSocket.Disconnect(true);
_clientSocket.Close();
#endregion
}
catch (Exception )
{
}
}
}
クライアント側:
public void RestartTheSoftwareInServerComputer(string ipOfServer, int portNumber)
{
TcpClient client = new TcpClient();
if (_serverEndPoint == null)
{
_serverEndPoint = new IPEndPoint(IPAddress.Parse(ipOfServer), portNumber);
}
client.Connect(_serverEndPoint);
// Send the command to the server:
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("....detailsOfProcess....");
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
// Now, wait for the server's response [which means the process had been restart].
NetworkStream stream = client.GetStream();
byte[] bytes = new byte[5];
stream.Read(bytes, 0, 5);
string response = Encoding.UTF8.GetString(bytes, 0, 1);
if (response.Equals("x"))
{
throw new Exception("Failed to restart X software.");
}
stream.Close();
client.Close();
}
サーバーを停止して再起動すると (クライアントが接続されていない場合)、すべて問題ありません。
問題は、サーバーがクライアントを接続して再起動したときに、クライアントが切断され、サーバーを再起動する必要がある場合です。「START SERVER」をもう一度押すと、例外が発生します。
通常、各ソケット アドレス (プロトコル/ネットワーク アドレス/ポート) の使用は 1 つだけ許可されます。
ポートを閉じるにはどうすればよいですか?