3

cのクライアントからサーバーにファイルを1行ずつ送信するプログラムをcで作成しました。ファイルが完全に送信された後、ファイルが終了しendoffile、次のファイルが次に送信されていることを識別するために、サーバーで文字列比較するための行をtxtファイルに指定しました。次のファイルは、サーバー内の別のファイルに書き込む必要があります。しかし、問題は、strcmpがendoffileコード内でを検出せずendoffile、クライアントのファイルから等しい文字列として受信されることです。amdは、クライアントからサーバーの同じファイルに次のファイルを書き込み続けます。

char enof[]="endoffile";
...
do
{
   rewind(appcrt);
   bytes_recieved = recv(pass_arg.connected, recv_data_c, strlen(recv_data_c), 0);
   recv_data_c[bytes_recieved-1] = '\0';
   fputs(recv_data_c, appcrt);
   if(strcmp(enof,recv_data_c) == 0){break;}
}while(check<count);

テキストファイル:

Necessary data
that is
being transmitted
to be written to the file
endoffile

txtファイルからの読み取りとサーバーへの送信に使用されるコード:

while (fgets(line, sizeof(line), crt) != NULL)
{
    send(sock, line, sizeof(line), 0);
}

do....while();問題が解決され、コードがループから抜け出すために、条件にどのような変更を加える必要がありますか。前もって感謝します。オペレーティングプラットフォーム:Linux

編集1:do....while()次のように編集しました:

do
    {
       rewind(appcrt);
       bytes_recieved = recv(pass_arg.connected, recv_data_c, 100, 0);
       recv_data_c[bytes_recieved] = '\0';
       fputs(recv_data_c, appcrt);
       printf("%s-%s",enof,recv_data_c);
       //if(strcmp(enof,recv_data_c) == 0){break;}
    }while(check<count);

ターミナルで次の出力を取得しました。

endoffile-file1line1
endoffile-file1line2
endoffile-file1line3
endoffile-file1line4
endoffile-file1line5
endoffile-file1line6
endoffile-endoffile
endoffile-file2line1
endoffile-file2line2
endoffile-file2line3
endoffile-file2line4
endoffile-file2line5
endoffile-file2line6
.
.
.

まだ希望はありません。

4

2 に答える 2

2

クライアントは一度に 1 行ずつソケットに書き込みますが、ソケットを介して転送されるデータは単なるバイト ストリームであるため、これはサーバーがそれを消費する方法ではありません。サーバーは、次の改行文字まで読み取ってから比較する必要があります。簡単なアルゴリズムでは、一度に 1 バイトを読み取り、それが改行文字かどうかを確認し、そうでない場合は、改行文字が読み取られるまで文字列に追加します。

/* Read next line. */
memset(line, 0, sizeof(line));
size_t line_len = 0;
while (line_len < sizeof(line) - 1 &&
       1 == recv(pass_arg.connected, &line[line_len], 1, 0))
{
    if ('\n' == line[line_len]) break;
    line_len++;
}

それとは別に、コードにはいくつかの問題があります。

  • よりも小さい可能性があるため、ファイルから読み取ったものを送信する必要がありますsizeof(line)。変化する:

    send(sock, line, sizeof(line), 0);
    

    に:

    send(sock, line, strlen(line), 0);
    

    また、 の戻り値をチェックして、send()成功したかどうかを判断します。

  • 以下は、以前に読み取られたものを最大で読み取るだけであるため、正しくありません (または、空の文字列に初期化されている場合は何も読み取られません)。

    bytes_recieved = recv(pass_arg.connected,
                              recv_data_c, strlen(recv_data_c), 0);
    

    また、特に戻り値が配列のインデックスに使用されているため、戻り値を確認してください。失敗した場合recv()は を返します-1。これにより、配列への範囲外アクセスが発生し、未定義の動作が発生します。

于 2012-06-21T22:53:51.747 に答える
1
while (fgets(line, sizeof(line), crt) != NULL)
{
    send(sock, line, sizeof(line), 0);
}

fgets()行が空白の場合、1 バイトしか読み取れないことを忘れないでください。したがって、あなたのsend()呼び出しは、呼び出しのたびに大量の初期化されていないデータを送信しています-前の行の内容またはfree()アプリケーションによって以前に作成されたランダムメモリのいずれかです。

したがって、受信プログラムは以下と比較する必要があります。

endoffiletten to the file

最後に最後の文字列を表示します。line(バッファが ASCII 文字でいっぱいになったと仮定しNULます。)

于 2012-06-21T22:51:29.040 に答える