0

UDP ベースのストリーミング サーバーを作成していて、奇妙な問題に遭遇しました。単純なエラーだと確信していますが、解決策が見つかりません。サーバーは次の行に沿って何かを行います。

FILE* infile = fopen(inf, "rb");
register int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int16_t buffer[LENGTH+HEADER];
struct header header;
int16_t data[LENGTH];
uint32_t number = 0;

/*set socket options etc. */

while(!feof(infile)){
    fread(data, 1, LENGTH, infile);
    /* if i write the contents of data to a file here, the error below occurs*/
    fwrite(data, 1, LENGTH, testfile);
    /*create a header, encode everything with htons/htonl*/


    if(sendto(sock, buffer, LENGTH+HEADER, 0, (struct sockaddr*) &to,
                    sizeof to) < 0)
         /*die*/            
}

これはうまくいくようです。デコードでき、データは破損していません。ただし、次のように動作する(または動作しない)テストクライアントを作成しました。

struct sockaddr_in si_other, si_me;
register int s;
unsigned int slen = sizeof(si_other);
int16_t buf[LENGTH+HEADER];
int16_t data[LENGTH];
FILE* file = fopen(of, "wb");

/*open socket, set options, etc. */

while(1){
    if(recvfrom(s, (char *)buf, LENGTH+HEADER, 0, (struct sockaddr*) &si_other,
                 &slen) < 0)
        /*die*/    
    decode(buf, data);
    /* If I write the decoded data to a file here, the error below occurs */
    fwrite(data, 1, LENGTH, testfile);
    if(is_empty(data) == 0){
        printf("End signal received.\n");
        break;
    }
} 

今私の問題に。を使用して16進数でテストファイルを検査するとdiff <(xxd test_before) <(xxd test_after)、次のようになります(差分行の例):

< 03d5ff0: f3fd f3fd 99fe 99fe 40ff 40ff e7ff e7ff  ........@.@.....
---
> 03d5ff0: f3fd f3fd 0000 0000 0000 0000 0000 0000  ................

つまり、パケットのデータの最後の 12 バイトが失われます。他のすべては問題ありません。

これは単なるテスト コードなので、それほど重要ではありませんが (私は推測します)、奇妙であり、その理由を知りたいと考えています。

何か案は?

編集:

私は今、答えからいくつかのアプローチを試みましたが、これまでのところどこにも行きませんでした。私は努力し続けます。

編集2:

コードは別のマシンで動作します。何が問題だったのかはわかりませんが、私以外の誰にとってもうまくいくようです。時間を無駄にして申し訳ありません。コードの改善方法などについて、親切な提案をありがとうございました。

前もってありがとう、カーソン

4

3 に答える 3

2

あなたのコードは非常に不完全であるため、確実なことを言うのは困難です。int16_t buffer[LENGTH+HEADER]送信側ではどのようにデータを入れるのですか?デコードおよびエンコード機能はどのように見えますか?

私が見ることができる明らかな危険の 1 つは、バッファーのタイプuint16_tが 2 バイトであることです。関数sendto()および関数recvfrom()は、バッファー長をバイト単位で期待します。言い換えれば、あなたの buf は、実際に伝える長さ (バイト単位) の 2 倍ですsendto()。したがって、エンコード機能により、送受信のPOVから一部のデータが消える可能性があります。

12 バイトの欠落は適切な 4 バイトの値か、htonl()処理されて送信中に失われた他のデータである可能性があります。

より良い推測のために、より完全なコードを投稿してください。

于 2014-10-01T13:57:56.763 に答える
2

2 バイトのbuf をcharにキャストし、その半分を読み取ります。

recvfrom(s, (char *)buf, LENGTH+HEADER, 0, (struct sockaddr*) &si_other,
             &slen) 

buf配列には(LENGTH+HEADER) * 2バイトがあり、その半分を読み取ります

sendreceiveの両方にchar配列を使用します。

編集

これはファイルを読む方法です:

unsigned char data[LENGTH];

fseek(inf, 0, SEEK_END);
int file_Size = ftell(inf);
fseek(inf, 0, SEEK_SET);
if(file_Size  > LENGTH){
    //file larger than data
}
fread(data, sizeof(unsigned char), file_Size, inf);
于 2014-10-01T13:39:35.957 に答える
0

編集 2 で述べたように、コードは私がコードをテストしたすべてのマシンで動作します。問題が何であるかはわかりませんが、私以外の誰にとってもうまくいくようです。時間を無駄にして申し訳ありません。コードの改善方法などについて、親切な提案をありがとうございました。

于 2014-10-02T16:49:50.303 に答える