2009-12-11 12 views
8

サーバからの応答を取得中に、私のrecv関数がハングします。ソケットプログラミングC/C++ - recv関数がハングしますか?

C/C++でのクライアント側のコードに:

void sockStuff() { 

int sock, bytes_recieved,bytes_send; 
char send_data[1024], recv_data[4096]; 

struct hostent *host; 
struct sockaddr_in server_addr; 

host = gethostbyname("127.0.0.1"); 

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    perror("SocketError"); 
    exit(1); 
} 
server_addr.sin_family = AF_INET; 
server_addr.sin_port = htons(50500); 
server_addr.sin_addr = *((struct in_addr *) host->h_addr); 
bzero(&(server_addr.sin_zero), 8); 


if (connect(sock, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) 
    == -1) { 
    perror("ConnectToError"); 
    exit(1); 
} 


    bytes_send = send(sock, a, strlen(a), 0); 
    bytes_send = shutdown(sock, 1); 


bytes_recieved = recv(sock, recv_data, 4096, 0); //Where the program hangs?? 
recv_data[bytes_recieved] = '\0'; 
printf("\nRecieved data = %s ", recv_data); 
cout << endl << endl; 

shutdown(sock,2); 



} 

私のクライアントは、C/C++で、サーバ側はOpenEdge進捗状況です。 コードを見て、何が問題になったのかを教えてください。

+0

あなたはマジックナンバー8ではなく、sizeof(server_addr.sin_zero)を使用してください。構造全体をゼロにして、興味のあるフィールドを設定してください。 –

+0

こんにちはニール、sizeof server_addr.sin_zero)は8番ではありませんが、運はまだありません。 – Vishal

答えて

1

recvは、応答フォームをサーバーに送信するまでハングする必要がありますが、応答が送信されていることを伝えてください。
wiresharkなどを試してネットワークを盗聴し、実際の応答の有無を確認してください。

+0

実際にはrecv()がハングした後、このタスクマネージャを開くとCtrl + Alt + Del.Byを試みましたが、このタスクマネージャを閉じて(突然すべてのプロセスを終了しませんでした)、突然返信once.But私のプログラムは、 。 – Vishal

1

うーんは....なぜシャットダウンソケットをしました....

 
bytes_send = send(sock, a, strlen(a), 0); 
    bytes_send = shutdown(sock, 1); /*** That I think is the problem! ***/ 


bytes_recieved = recv(sock, recv_data, 4096, 0); 

そして、まだあなたがシャットダウンした同じソケットから受信したコードに続けて?

これは正しい方向を示唆していますか、 お礼、 トム。

+0

Thnx。トムは返事をする。 しかし、シャットダウン(sock、1);私はこの行を削除しても、私のrecv()はハングします。 – Vishal

+0

@Vishal:Ok ... http://www.developerweb.net/forum/showthread.php?t = 2940 - シャットダウンを使用するときに興味深い議論があります。コードは同期モードにあり、可能ですシャットダウン前にデータの受信が既に行われているためハングアップすることがあります。あなたはそれを考えましたか?申し訳ありませんが私はここに多くの助けではない... :( – t0mm13b

1

Recvは、ソケットがブロッキングモードになっている限り、読み取る情報があるまでブロックします。これはfcntlで変更できます。

なぜそれがぶら下がっているのだろうと思うなら、私の推測では、ソケット上の書き込みパイプをシャットダウンしたとき(より良いスタイルとしてSHUT_WR定数を使用することもあります)、サーバーはEOFを受け取り、接続を切断していますが、サーバがそれを処理するように設定されている場合はそうではないかもしれません。

ソケットを非ブロックモードに設定してから、ソケットが読み込み/書き込み可能になるかタイムアウトが発生するまでブロックするselectを呼び出すことをお勧めします。あなたがやっていることに応じて、それは違いを生むでしょう。

1

ノンブロッキングモードをお試しください。つまり、recvはデータが読み込まれなければリターンしますので、このケースを処理してください(whileループやselectまではあなた次第です)

もっと詳しくは、POSIX準拠のシステムを使用していると仮定します)これを読んで http://www.opengroup.org/onlinepubs/009695399/functions/recv.html

8

あなたのコードは、サーバーがデータを返すまでrecv呼び出しでブロックされます。それは起こっていないので、あなたのクライアントが完全な要求を送ったかどうかあなた自身に尋ねてください。完全な要求が受信されるまで、サーバーはおそらく応答の送信を開始しません。

HTTP/SMTPなどのクライアント/サーバープロトコルがテキストベースの場合は、応答が正しく終了していることを確認してください。サーバはCR + LFだけでなくLFの( '\ rをする\ n')( '\ n' を)期待してもよいし、空行が要求終了することを期待:

char *request = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"; 

PSを。コードスニペットで 'a'を宣言したり初期化したりすることはありません。

4

あなたのコードは、サーバーがデータを返すまでrecv呼び出しでブロックされます。それは起こっていないので、あなたのクライアントが完全な要求を送ったかどうかあなた自身に尋ねてください。完全な要求が受信されるまで、サーバーはおそらく応答の送信を開始しません。

HTTP/SMTPなどのクライアント/サーバープロトコルがテキストベースの場合は、応答が正しく終了していることを確認してください。サーバーは、単にLF( '\ n')の代わりにCR + LF( '\ r \ n')を期待しているか、空の行が要求を終了することを期待している可能性があります:

char * request = "GET/index。 html HTTP/1.1 \ r \ nHost:www.example.com \ r \ n \ r \ n "; PS。あなたはコードスニペットで 'a'を宣言したり初期化したりしません。notacat

私は初期のwinsock 1.0と1.1の実装をC++でやっていました。 私のコードはrecv )コールし、そこにたどり着くだけです。私はblocking \ Non blockingソケットについて知っていましたが、それは私が必要とした解決策ではありませんでした。wiresharkなどで私の要求を見たので、ポート80、私のコードは、私のクライアントとサーバーの間の通信がないためにrecv()コールがフリーズしてしまいましたが、私は正当なリクエストをしなかったと信じていました。私のリクエスト(「GET /index.html HTTP/1.1 \ r \ nHost:www.example.com \ r \ n \ r \ n」)に変更すると、すべてが魅力的なように機能しているようです! !!

関連する問題