1

Linux環境用のC言語でアプリを作りました。このアプリは動作しますが、しばらくすると (5 時間前後)、パフォーマンスが不安定になります。これが背景です。5分ごとにソケット(私のアプリ)を介してデータを送信するリモートコンピューター(400台程度)があります。すべてのプロセスはループであり、一日中機能する必要があります。アプリは最初にデータを送信し (存在する場合)、次にデータを受信します (存在する場合)。私のアプリは、いくつかの引数を持つサーバー側のように動作するか、他の引数を持つクライアント側のように動作します。サーバー モードとして動作するアプリは、リッスン状態の後、クライアント接続のみを待機します。クライアントが接続されると、クライアントモードのアプリは、データが送信されることを示すメッセージを送信し、サイズと名前が連結された新しいメッセージをサーバー側に送信します (常に 64 バイトを送信し、私のアプリは64バイトを書き込み、反対側では64バイトを読み取ります)、データ(ファイル)を送信します。サーバーは、受信するファイルのサイズと名前のメッセージ (64 バイト) を読み取り、メッセージを分割して、サイズを変数に、ファイル名を other に格納し、ファイル データを受信した後に受け取ります。変数に保存されているサイズと読み取ったデータのサイズを比較し、すべて問題がなければ、サーバーはメッセージを送信し、データを受信前の名前で新しいファイルに保存します。このようにして、最後のファイルが送信されるまで続けます。次に、サーバーはメッセージを送信し、データを受信前の名前で新しいファイルに保存します。このようにして、最後のファイルが送信されるまで続けます。次に、サーバーはメッセージを送信し、データを受信前の名前で新しいファイルに保存します。このようにして、最後のファイルが送信されるまで続けます。

私のアプリが開発段階にあったとき、数時間後にメッセージが破損していることに気付きました。つまり、メッセージが不完全であるか、より多くのデータ (おそらく次のデータ) があることを意味します。だからファイルデータも。では、どうすれば同じソケットを介してファイル データを送信できますか?? 注: メッセージを送受信するためのバッファーと、ファイル データを送受信するためのバッファーがあります。

その他の質問: 元のコード:

int copydata(int readfd, int writefd, int offset, int bytes) {
  char buffer[4096];
  int crbytes = 0, cwbytes = 0, trbytes = 0, twbytes = 0;
  if (offset) {
    if (lseek(readfd, offset, SEEK_CUR) < 0) {
      return -1;
    }
  }
  while ((crbytes = read(readfd, buffer, bytes)) > 0) {
    if (crbytes < 0) {
      return -1;
    }
    trbytes += crbytes;
    //printf("dbgmsg::Readed data <%dB> | Total readed data <%dB>\n", crbytes, trbytes);
    while (crbytes > 0) {
      cwbytes = write(writefd, buffer, crbytes);
      if (cwbytes < 0) {
        return -1;
      }
      twbytes += cwbytes;
      crbytes -= cwbytes;
      //printf("dbgmsg::Written data <%dB> | Total written data <%dB>\n", cwbytes, twbytes);
    }
  }
  return twbytes;
}

このコードは、ファイル データの送受信に使用されます。データを送信する側は、送信したいファイルのファイル記述子を使用して (読み取り) <readfd>、ソケットのファイル記述子に書き込みます (書き込み) <writefd>。データを受信する側は<readfd>、ソケット ファイル記述子から読み取るために使用し、<writefd>データを書き込みたいファイルからファイル記述子に書き込みます。この関数を使用する前に他のメッセージが送信された場合、クライアントとサーバーの両方が内部の「while ループ」の最後でスタックします。つまり、クライアントはすべてのファイル データを送信し、サーバーはすべてのファイル データを受信します (このポイント、受信したデータが完了したことをどのように知ることができますか? 受信したファイルを開くことができるため)。エラーはなく、「目的のタイプのメッセージがありません」という 1 つだけです。この関数の前にメッセージを送信しなかった場合、すべて正常に機能します。この小さな問題をスキップするために、コードを変更し、ファイル サイズも引数として渡し、2 つの while と if 構造の間に書き込みます。

int copydata(int readfd, int filesz, int writefd, int offset, int bytes) {
  char buffer[4096];
  int crbytes = 0, cwbytes = 0, trbytes = 0, twbytes = 0;
  if (offset) {
    if (lseek(readfd, offset, SEEK_CUR) < 0) {
      return -1;
    }
  }
  while ((crbytes = read(readfd, buffer, bytes)) > 0) {
    if (crbytes < 0) {
      return -1;
    }
    trbytes += crbytes;
    //printf("dbgmsg::Readed data <%dB> | Total readed data <%dB>\n", crbytes, trbytes);
    while (crbytes > 0) {
      cwbytes = write(writefd, buffer, crbytes);
      if (cwbytes < 0) {
        return -1;
      }
      twbytes += cwbytes;
      crbytes -= cwbytes;
      //printf("dbgmsg::Written data <%dB> | Total written data <%dB>\n", cwbytes, twbytes);
    }
    if (twbytes == filesz) { break; }
  }
  return twbytes;
}

前もってありがとう、そして私の英語でごめんなさい!!

4

1 に答える 1

0

プログラムが「不完全な」write() に遭遇した場合、内部ループはバッファの先頭を再送信します。

while (crbytes > 0) {
      cwbytes = write(writefd, buffer, crbytes);
      if (cwbytes < 0) {
        return -1;
      }
      twbytes += cwbytes;
      crbytes -= cwbytes;
      //printf("dbgmsg::Written data <%dB> | Total written data <%dB>\n", cwbytes, twbytes);
    }

次のように変更できます。

for ( sentbytes=0; sentbytes < crbytes; sentbytes += cwbytes ) {
      cwbytes = write(writefd, buffer+sentbytes, crbytes - sentbytes);
      if (cwbytes < 0) { return -1; }
      twbytes += cwbytes;
    }
于 2012-05-16T21:03:23.080 に答える