2012-01-25 29 views
1

私はwinsockを使用してC++で小さなクライアント/サーバーアプリケーションを作成していますが、何が起こっているのか説明できません.. 私は2つの基本機能をTCPコネクション..Winsockは追加のデータを送信します

bool sending(SOCKET source, char* buff, int size, int flags = 0) 
{ 
    int sent = 0; 
    int totalst = 0; 
    int total = size; 
    while(totalst != total) 
    { 
     sent = send(source, buff+totalst, size-totalst, flags); 
     if(sent > 0) 
     { 
      totalst += sent; 
     } 
     if(sent == SOCKET_ERROR) 
     { 
      return false; 
     }  
    } 
    return true; 
} 

bool receive(SOCKET source, char* buff, int size, int flags = 0) 
{ 
    int rec = 0; 
    int totalrc = 0; 
    int total = size; 
    while(totalrc != total) 
    { 
     rec = recv(source, buff+totalrc, size-totalrc, flags); 
     if(rec > 0) 
     { 
      totalrc += rec; 
     } 
     if(rec == SOCKET_ERROR) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

サーバーがそれに続くデータブロックのサイズを含む整数を送信し、私の場合のデータブロックのこのサイズは変更しないでください..それは常に92600でなければなりませんクライアントが92604バイトを受信することがあります。奇妙なことは、それは、クライアントが間違った値を受け取ること

int i=0;      
while(i < 100) 
{ 
    i++; 
    dat = getData();         
    len = sizeof(dat); 
    sending(source, (char*)&len, sizeof(len)); 
    sending(source, dat, len); 
    Sleep(200);  
} 

..私はボックサイズと(スリープ付き)ブロック自体を送信した後、サーバーを待機させる場合、それは常に私が期待するものを送信していることであるハチができます遅れのためにバイトの? これを修正する方法はありますか? ご協力いただければ幸いです!

+0

あなたはすでに回答を受け入れています。しかし、私はちょうどtoddaが話していることの結果としてあなたが見ているものに関連している可能性が高いあなたのコードの2つのバグを指摘しました。下の私の答えを見てください。 – selbie

+0

ありがとうございます!ありがとうございました。コメントは既に指摘していますが、すぐ後に削除しました。私は質問を更新するのを忘れました。! – elephantintheroom

答えて

2

は、この例を考えてみましょう:

char *x = "!"; 
send(socket, x, 1); // destination, buffer, size 
send(socket, x, 1); 
send(socket, x, 1); 
send(socket, x, 1); 

あなたがここに起こることを期待しますか?実際に

char buffer[4]; 
recv(socket, buffer, 4); // source, buffer, size 

、sは1 recvに受信することができる4つsend」によって送信されたデータ。 nsendに電話すると、recvnが呼び出され、すべてのデータが受信されるという保証はありません。

nosがコメントしたとおり、TCPはメッセージ境界を実装していません。それはアプリケーション層でのあなたの仕事です。 Winsockは追加データを送信しません。

+0

は、それは、開発者がソケットで作る最大の過ちの一つだ – elephantintheroom

+0

..私は間違っているかを理解し始めていますありがとう - (そのRECVを仮定することである)、クライアントは「送信と呼ばれたのと同じチャンクブロック内のデータをお届けします"多くの時間がこのように動作しているように見えますが、コードはこのように展開されることが多く、異なる環境で動作するようになると微妙なバグが発生します。 – selbie

0

送信機能と受信機能の両方にバグがあります。

あなたが正しくループを終了するように送受信された合計バイトを正しく記録しますが、その後のsend/recvの呼び出しでは "buff"と "size"の値を調整するのを忘れてしまいます。送信するバッファが複数回の送信で送信されなければならない場合、間違ったデータが送信されます。

同様に、「recv」を複数回呼び出す必要がある場合は、バッファの先頭にコピーされたデータを上書きします。

読み込みする必要があります。同様に

sent = send(source, buff+totalst, size-totalst, 0); 

をrecvのケースのために:

rec = recv(source, buff + totalrc, size-totalrc, 0); 

私は、これはあなたの問題を引き起こしているかどうかわからないんだけど、シナリオが指摘したときに、私は感じていますtoddaがtrueの場合、このバグによってデータストリームが壊れてしまいます。

意味がありますか?また、recv()が0を返すケースを処理する必要があります。

これが役立つことを願っています。

関連する問題