recvfrom関数について
宜しくお願いします。
社内の複数のクライアントマシーンへ、ping 送信を行うプログラムを
IP パケットを生成する部分から書いています。
sendto/recvfrom を用いて、データの送受信を行っているのですが、ファイアーウォールや
セキュリィティーソフト(Outpost Security Suite Pro)等の設定が、クライアント側に
設定してある場合、
無応答で止まってしまいます、これは、仕様なのでしょうか?
一定時間応答が無ければ、timeoutさせたいのですが、そのような場合どのような処理を
すれば良いのでしょうか?
int recv_ping(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf,
int packet_size)
{
// Wait for the ping reply
int fromlen = sizeof(source);
int bread = recvfrom(sd, (char*)recv_buf, //ここで応答しない
packet_size + sizeof(IPHeader), 0,
(sockaddr*)&source, &fromlen);
if (bread == SOCKET_ERROR) {
cerr << read failed: ;
if (WSAGetLastError() == WSAEMSGSIZE) {
cerr << buffer too small << endl;
}
else {
cerr << error # << WSAGetLastError() << endl;
}
return -1;
}
return 0;
}
環境
Windows XP SP3
Visual Studio 2005 pro
recvやrecvfromで受信できるデータがない場合はブロックされます。
recvfromの前にselectで受信可能かどうか調べてもだめでしょうか?
subaruさんお世話になります。
>>recvfromの前にselectで受信可能かどうか調べてもだめでしょうか?
ヒントになりました、一部抜粋ですが、recvfromの前にSOCKETを生成して、selectの
戻り値を、判別し、戻り値0以下を弾くようにしたら、上手くいきました。
// Set up for Socket
SOCKET sd;
sockaddr_in dest, source;
int result = 0;
// Set up for pinging
size_t n = str.size();
i = 0;
fd_set fds;
while(i < (int)n) {
strcpy_s(tmp, ");
strcpy_s(tmp, str[i].c_str());
cout << tmp << endl;
if (setup_for_ping(tmp, ttl, sd, dest) < 0) {
goto cleanup;
}
if (allocate_buffers(send_buf, recv_buf, packet_size) < 0) {
goto cleanup;
}
init_ping_packet(send_buf, packet_size, seq_no);
// Send the ping and receive the reply
if (send_ping(sd, dest, send_buf, packet_size) >= 0) {
while (1) {
struct timeval timeout = {0, 0};
FD_ZERO(&fds); /* fd_set Initialization */
FD_SET(sd, &fds); /* sock Setting */
result = select((int)sd + 1,&fds,NULL,NULL,&timeout); /* Data reception
waiting */
if(result > 0) {
// Receive replies until we either get a successful read,
// or a fatal error occurs.
if (recv_ping(sd, source, recv_buf, MAX_PING_PACKET_SIZE) <
0) {
// Pull the sequence number out of the ICMP header. If
// it's bad, we just complain, but otherwise we take
// off, because the read failed for some reason.
unsigned short header_len = recv_buf->h_len * 4;
ICMPHeader* icmphdr = (ICMPHeader*)
((char*)recv_buf + header_len);
if (icmphdr->seq != seq_no) {
cerr << bad sequence number! << endl;
continue;
}
else {
break;
}
}
if (decode_reply(recv_buf, packet_size, &source) != -2) {
// Success or fatal error (as opposed to a minor error)
// so take off.
break;
}
} else {
// Socket close?
cout << time out << endl;
break;
}
}
}
i++;
}