1

私はこのように動作する単純なクライアントサーバーアプリケーションを持っています:サーバーは常にクライアント接続を(別のスレッドで)リッスンしています(サーバーに強制終了させたいプロセスの名前を送信します)。

サーバーは次のとおりです。

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 つだけ許可されます。

ポートを閉じるにはどうすればよいですか?

4

1 に答える 1