• ベストアンサー

ソケットのrecvの戻り値が0

linuxにてソケットの勉強をしようと思い、 簡単なソケット通信のプログラムをCで組みました。 ret = recv(ID, Buff, sizeof(Buff), 0); といった感じでサーバ側を組んだのですが、 この戻り値retに0が入ることがあり、思うように動いてくれません。 私の認識だと、recvは受信するまで待ち、 受信したサイズを返すと思っているのですが、 それが0とは、いったいどういう意味を持つのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • shige_70
  • ベストアンサー率17% (168/946)
回答No.3

recv()の切断時の返り値は-1とは限りません。 むしろ、通常の切断では0以上が返ると思ってください。 つまり、recv()の返り値だけで切断を検出することは出来ません。 単純に1回の接続で短いデータを1回受信するだけのような場合はrecv()が返ってきた時点で切断されていると見なすことは出来るでしょう。 通常は、プロトコルで切断手順を定めて、切断することがプログラムで分かるよう工夫します。 例えば、終了時には必ず"EOF"という行を送るようにする、等です。 しかし、クライアントが強制終了した場合などは上記方法では対応できないので、alarm()を用いて一定時間通信がなければ自動終了するようにするなどしてタイムアウトを定めるわけです。 もちろん、可能ならばクライアント側で強制終了時もシグナルを拾って切断手順を実行できるようにすることも大事です。

pinch-i
質問者

お礼

回答ありがとうございます。 なるほど、切断状態でも-1とは限らないのですね。 alert()を勉強してみます。

その他の回答 (2)

  • muyoshid
  • ベストアンサー率72% (230/318)
回答No.2

こんにちわ。 recv の復帰値が0 は、確か相手プロセスとの コネクション切断だった筈です。

回答No.1

んー、パッと見で非ブロッキングになってるんじゃないかな、とか思ったんですが。 エラーやら切断なら -1 が返却されると思うんで(うろ覚えです) fcntlで非ブロッキングに設定してある、とかではないですかね?

pinch-i
質問者

補足

回答ありがとうございます。 非ブロッキングに設定はしていません。 (存在すら知りませんでしたが。。。) 一応ブロッキングにしてやってみましたが、同じでした。 どうやら、相手(クライアント側)のプログラムをSIGINT等で終了させると起こるようです。 無限ループの中でrecvをさせてますので、 相手側を終了させると、受信サイズ0で進んで、 ひたすらrecvを繰り返しています。 この場合、おっしゃる通り -1 で返却されるのであれば理解できるのですが。。。

関連するQ&A

  • recv関数の戻り値について

    おせわになります。 socket関数(WinSock2)のrecv関数のことで質問なのですが、 第4引数にMSG_PEEKを指定したときと、指定しない時(=0) の戻り値が、明らかに違うのです。 実際は、20000バイトを送信し、受信側でrecvすると、 MSG_PEEKを指定すると、8760が返り、 MSG_PEEKを指定しない(=0)と、20000が返ります。 (もっと試して、200000と10倍にしても一回で受信しました。) recvが一度に受信できる容量のテストをしていたときに発見したのですが、こういうものなのでしょうか? 以上、よろしくおねがいします。

  • ソケットプログラミングとスレッドについて

    TCP/IPソケットを用いた通信プログラムを作成しています。その上でacceptする処理を専用スレッドにしており、accept後の受信処理をまた別のスレッドで処理しています。コンソールプログラムにおいてサーバとクライアントを用意しテストをしてみるとうまくいくのですが、MFCプログラムにおいて同じネットワーク処理を行ってみると、サーバ側へのconnectは成功するのですが、クライアント側からsendしたときにサーバ側でrecvの戻り値が必ず0にしかならず切断された状態になってしまいます。これはどういったときに発生すると考えられるでしょうか?ちなみにMFCが絡んでいるかどうかということは特にわかっておりません。 どなたかこのような経験をお持ちであればご教授お願い致します。

  • バイナリデータ受信時のデータ順

    Winsockを用いてバイナリデータの送受信を行うプログラムを作成しました。 サイズは約4MBです。 データはすべて送受信できたようなのですが、バイナリエディタで確認したところ受信データがばらばらに入っているようなのです。完全にばらばらなのか、それとも塊ごとに後ろから順に入ってるのかまでは確認してません 受信方法としては BYTE buff; size_t fsize; recv( Recv, (char *)buff, sizeof(size_t), 0 ); memmove( &fsize, buff, sizeof(size_t) ); size_t Total = 0; BYTE *SubBuff = new BYTE[fsize*2]; BYTE *Buff = new BYTE[fsize]; while( Total < fsize ) { int n = recv(); memmove( &Buff[Total], SubBuff, n ); Total += n; } としています。 どのようにすれば、正しい受信ができるのかわかりません。教えていただけないでしょうか?

  • 配列とポインタについて

    こんばんわ。 WinSockを利用してネットワークプログラミングを行っています。 以下のようなプログラムを作成したのですが、実行できません。 以下のプログラムは質問箇所を抜き出したものです。 [プログラム] int Receive(u_short portNo) { char recv_Buf[1025],recv_Buff[1025]; size = recvfrom(s2, recv_Buf, (int)sizeof(recv_Buf) - 1, 0, (SOCKADDR *)&from, &fromlen); recv_Buff = recv_Buf; Sender(portNo,szServer,recv_Buff); } int Send(unsigned short portNo,char *szServer,char *recv_Buff) { sendto(s1, recv_Buff, (int)strlen(recv_Buff), 0, (LPSOCKADDR)&addrin1, sizeof(addrin1)); } このプログラムは、Receive関数内のrecvfrom関数で1024Byte(recv_Buf[1025])受信したデータをSend関数内のsendto関数で送信するというプログラムです。 recv_Buf = recv_Buffにてエラーが発生します。なにか解決策はりますでしょうか? また、Receive関数およびSend関数は何回も呼ばれるのですが、配列は初期化する必要があるのでしょうか? よろしくお願いします。

  • socket: recvはいつ,どれだけ受け取るのか?

     現在,参考書にしたがってC++でソケットプログラミングを書いています.  sendとrecvを非同期にするために,本では select関数やWSAAsyncSelect関数などを利用していて,実際,本のとおりに書いて上手く動いています.  ここで伺いたいのですが,recvは,どうやって「データが届いたか」を知るのでしょうか.  同期ならば,トランシーバでの会話のように送信側が「どうぞ」といって送受信を交代させることができますが,非同期ならばそれができません.  NICとかが,プログラムに「届いたぞ!( or これから届くぞ!)」と教えてくれるのでしょうか.あるいは逆に,プログラムがNICに「届いてる?」と聞いているのでしょうか.仮に,ここに書いたような方法で届いたことが分かったとしても,どれくらい受け取ればいいかは分かりません(それも併せて教えてもらっているのでしょうか.データを送るときには,どれだけ送ればいいか分かりますよね.受信するときはどうしてるのかを知りたいと思っています).

  • recv関数でフリーズしてしまう

    現在Winsockを用いた簡単なパケット送受信のソフトを作成しています。 開発環境はVisual Studio2008で、ダイアログベースで作成しています。 パケットの受信側の処理なんですが、いつパケットが来てもいいように、 Ontimerで、定期的に受信処理をしようと思っています。 そこでOntimer内に以下のようにプログラムしたところ、コンパイルエラー はないものの、数秒経つと応答なしとなりフリーズしてしまいます。 原因を探ったところrecv関数が原因で、recv関数をコメントアウトした ところ、フリーズはしなくなりました。また、エラー処理は省略していま すが、ソケットの作成失敗などはありませんでした。 なぜrecv関数でフリーズが起きてしまうのか、原因が分かる方は いらっしゃいますか? OnTimer(UINT nIDEvent){ WSAData wsaData; SOCKET sock; struct sockaddr_in addr; char buf[2048]; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); memset(buf, 0, sizeof(buf)); recv(sock, buf, sizeof(buf), 0); closesocket(sock); WSACleanup(); }

  • vb2010でソケット通信を使いたいのですが

    はじめまして。 vb2010でソケット通信を使いたくて、今TCPサーバーを作っています。 クライアント側から受信した瞬間にサーバー側から返信というのは可能でしょうか。 受信したタイミングで接続が切れてしまって困っています。 初めてソケット通信に触れてイマイチ分かってないので説明がうまくいきませんが、 どなたかわかる方がいらっしゃいましたらご回答よろしくお願いします。

  • JNI 戻り値の渡し方について

    javaからCのdllを呼出すJNIを作っています。 やりたい事は ・C側で実行した結果がchar[256]に設定され、戻り値としてjava側に渡される。 ・java側でその中身を編集する ですが、java側で例外が発生します。 jcharArrayと言う型に入れさえすれば良いと思ってたのですが・・・ char[]をjava側で見る&編集する方法をどなたかご教授ください・・・。 よろしくお願いします。 ----------jnitest.dll---------- #include "stdafx.h" #include "../../JNI_test.h" #include <Windows.h> #include <stdio.h> #ifdef _MANAGED #pragma managed(push, off) #endif BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } #ifdef _MANAGED #pragma managed(pop) #endif JNIEXPORT jcharArray JNICALL Java_JNI_1test_getScreenData(JNIEnv *env, jobject obj){ LONG ret; LONG id; char buff[256]; LPVOID lpvoid; DWORD len = 0; memset(buff,0x00,sizeof(buff)); lpvoid = buff; len = sizeof(buff); ~ここでbuffに値を設定する~ jcharArray result = (jcharArray)buff; return result; } ----------JNI_test.java---------- public class JNI_test { public native char[] getScreenData(); static{ System.loadLibrary("jnitest"); } public static void main(String[] args) { JNI_test jniObj = new JNI_test(); char[] kekka = jniObj.getScreenData(); System.out.println("出力内容:"+kekka);←ここで例外発生。 } }

  • ソケットプログラミングのrecv時にFD_READイベントが終わらない

    現在Winsockを用いているのですが、クライアントからのデータを受信したときにおこるFD_READイベントをWSAWaitForMultipleEventで受け取って処理しているのですが、recvからの戻り値が常に0にも関わらずFD_READイベントが発生し続けます。クライアント側での送信は成功しています。 このような事態が発生する原因としてはどのようなことが考えられますでしょうか?

  • recvfrom関数の戻り値について

    初めて質問させて頂きます。 現在、LinuxのUnixドメインを使用した内部通信プログラムを 作成しているのですが、recvfrom関数の戻り値で-512という値が 返ってきて頭を悩ませています。 いろいろなHP等でrecvfrom関数の戻り値について記述されている内容は 受信サイズか-1となっているのですが・・・-512という値については さっぱりでした。 -1の場合は、errnoが入るようなのですが、-512の場合、errnoが0のままで何もはいっていないように見えます。 どの様な問題が発生しているかの見当もつかない状態です。 すみませんが、宜しくお願い致します。