プロが教える店舗&オフィスのセキュリティ対策術

UNIX/gcc。
TCP/IPでチャットプログラムを作っているんですが
ログアウトメッセージなるものを送る前に
sendto() sent a different number of bytes than expected: Socket operation on non-socketというエラーが出ます。
起こる箇所:クライアント
msgStruct.option = htonl(option);
msgStruct.seatLog = htonl(loggedIn);
if (sendto(sock, &msgStruct, sizeof(msgStruct), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr)) != sizeof(msgStruct)) {
printf("sizeof(msgStruct): %d\n", sizeof(msgStruct));
DieWithError("sendto() sent a different number of bytes than expected");

これはどういうときに起こるのでしょうか?
このエラーが起こり始めたのはファイルの中のポート番号の値を変えてからです。
元通りにポート番号をコマンドの引数から得た値に直せば
このエラーは消えますが、そうするとチャットプログラムとして動作しなくなってしまいます。

//これで各自のクライアントが独自のポート番号を持てます
echoDummyAddr.sin_port = 29990 + (unsigned short)recordNumber;
//元々はechoServPort = atoi(argv[1]);で得た値を送ってました

loggedIn = logIn(option, msgString, seatLog, inet_ntoa(echoClntAddr.sin_addr), echoDummyAddr.sin_port);

関数側(端折ってます):
int logIn(int option, char *id, int loggedIn, char *ip, unsigned short portNum)
{
FILE *file_ptr;
user record_file;
record_file.portNum = portNum;

fwrite(&record_file, sizeof(record_file), 1, file_ptr);
fclose(file_ptr);
}
return loggedIn;
}
小さなヒントでもいいですから、どうか宜しくお願いします。

A 回答 (2件)

このエラー(Socket operation on non-socket)


がでるのは、sockの値が破壊され、0になっていると考えられます。
sockはint型で確保されているはずので、printf文で、
sentoを呼び出す前に、sockの内容を表示してみては如何でしょうか。(エラーが発生したときに表示でもかまいませんが)
また、力づくになりますが、いたるところにprintf文をいれる方法もあります。
printf("sock=%d\n",sock);
又は、
sock = socket()のあとで
sock_save = sockとして(sock_saveはint型)
if (sock != sock_save) printf("sock=%d\n",sock);
とする手もあります。(sockが破壊された時に印字される)
そのとき
printf("src=%s line=%d sock=%d\n",__FILE__,__LINE__,sock);とすると、このprintfを実行した、ソース名と行番号も表示されますので、この方がよいかもしれません。
    • good
    • 0
この回答へのお礼

>>sockはint型で確保されているはずので
>>printf("src=%s line=%d sock=%d\n",__FILE__,__LINE__,sock);とすると、このprintfを実行した、ソース名と行番号も表示されますので

なるほど、勉強になりました。
お陰様で解決しました。
と今頃お礼してみます。
ありがとうございました!

お礼日時:2006/11/10 04:18

こんにちは


Socket()作成の部分は見えないので、なんともいえないですが、sockという変数は本当にSocket作成した変数ですか?
ちなみに、標準errnoの定義だと上記のエラーは:
ENOTSOCK
非ソケットに対するソケット操作です (Socket operation on non-socket)
と定義されています。
可能性としては
(1)sockは本当のSocketハンドルではない
(2)select()の時、fd_setのメンバーには間違ってるメンバーが含まれている
ですね。
    • good
    • 0
この回答へのお礼

ありがとうございます。
はい、sockは

/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) //←UDPです、はい
DieWithError("socket() failed");

のように正しく作成されていると思います。
現にloginや自前のwhoコマンドなどでもこのsockを使ってメッセージを送ってますが
正しく動作しています。
書き忘れていましたが、チャット部分はTCP/IPですが
それまでのメニューはUDPを使っていて、このエラー箇所もUDPのソケットです。
あと、このプログラムではselect()は使っていませんね。

sockの内容を確認する方法はないでしょうか?
もしそんな方法があるのならその行を至るところに埋め込んで
変化したところを見れば何が悪さをしているのか見つけられるはずです。
それとも他に解決方法がありますでしょうか?

お礼日時:2006/04/06 11:55

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!