0

UNIXソケットを使用してC++で単純なサーバー/クライアントチャットアプリを開発していますが、気になることが1つあります。

ターミナルでチャットクライアントを実行し(Macを使用しています)、CTRL + Cでクライアントを閉じると、4方向ハンドシェイクが実行され、接続が正しく閉じられます。

代わりに、クライアントが実行されているターミナルウィンドウを閉じることを選択した場合、クライアントは大量のパケットをサーバーに送信します。

CTRL+Cでクライアントを閉じます。

ここに画像の説明を入力してください

ターミナルウィンドウを閉じてクライアントを閉じます。

ここに画像の説明を入力してください

誰かが私に何が起こっているのか説明できたら素晴らしいと思います。

クライアントコード:

 void writeString(int FD, const char* data, size_t n){
   size_t bytesLeft = n;
   ssize_t bytesWritten = 0;
   const char *cBuffer = (char*) data;
   while ((bytesWritten = write(FD, cBuffer, bytesLeft)) > 0) {
    bytesLeft -= bytesWritten;
    cBuffer += bytesWritten;
   }
 }

 bool writeInt(int FD, int intToWrite){
   intToWrite = htonl(intToWrite);
   write(FD, &intToWrite, sizeof(intToWrite));
 }  

void writeMessage(int FD, int type, int ID, string message){
  if(type == 1){
    int messageSize = (int) message.length();
    writeInt(FD, type);
    writeInt(FD, ID);
    writeInt(FD, messageSize);
    writeString(FD, message.c_str(), messageSize);
  }
}

while (!connectionClosed) {
FD_SET(socketFD, &rset);
FD_SET(0, &rset);
int maxfd = max(0, socketFD) + 1;

select(maxfd, &rset, NULL, NULL, NULL);

if(FD_ISSET(0, &rset)){
  getline(cin, input);
  writeMessage(socketFD, 1, ID, input);
}else if(FD_ISSET(socketFD, &rset)){
  int type = 0;
  if(readInt(socketFD, type) == 0)
    connectionClosed = true;
  readMessage(socketFD, type, ID);
}
}

close(socketFD);
4

1 に答える 1

0

私の推測では、閉じるボタンでターミナルを閉じると、PTYへのセッションを終了するための標準的なターミナルコマンドが送信されます。チャットアプリが実行されているため、コマンドは代わりにチャットアプリによってインターセプトされ、サーバーに転送されます。

たとえば、telnetプロトコルには、実行中のプロセスの中断や中止など、さまざまな制御コードが含まれています。

送信されている実際のパケットの内容を確認しましたか?

PSH(プッシュ)については、ここでかなりよく説明されています。たとえば、http:
//packetlife.net/blog/2011/mar/2/tcp-flags-psh-and-urg/

クライアントアプリのディスクにログを追加して、後でターミナルウィンドウを閉じているときに何が起こっていたかを調べることができるようにすることもできます。

または、別のターミナルウィンドウから実行中のクライアントにデバッグセッションをアタッチすることもできます。

于 2012-12-13T19:12:46.390 に答える