最初に長い質問をさせてください - 私は UDP クライアント サーバー プログラムを書いていますが、奇妙なことに、プロトコル ファミリにこのフラグを使用するたびに、このパケット損失の問題が発生しました。症状は、パケットが送信側ホストを離れることはありません (tcpdump からのキャプチャがない) が、sendto() は正しい正の値を返します。これは 200 バイトを超えることはありません。これがIPv4を強制することで解決できることを理解するのにばかげた時間がかかりましたが、理由がわかりませんか? サーバーとクライアントが同じシステム (scientific linux 6) で実行されている状態で何度もテストされているため、一般的な信頼性の低い UDP 送信はおそらくここでの原因ではなく、何もドロップしないファイアウォール ルールもありません。誰か原因を知っている人がいるかどうか疑問に思っていますか?
また、コードを投稿することも考えましたが、必要ではないようです..簡単に言えば、AF_UNSPEC を使用すると、すべての UDP パケットが送信者から離れることはありませんが、エラーは発生せず、AF_INET を使用するとすべてが完璧になります。これは奇妙な質問かもしれませんが、洞察をいただければ幸いです。どうもありがとう!
サーバー初期化のコード:
int udp_srv_init(char * port)
{
struct addrinfo hints, *servinfo, *p;
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return EXIT_FAILURE;
}
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((self_udp = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("socket");
continue;
}
if (bind(self_udp, p->ai_addr, p->ai_addrlen) == -1) {
close(self_udp);
fprintf(stderr, "Port %s: ",port);
perror("bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind socket\n");
return EXIT_FAILURE;
}
freeaddrinfo(servinfo);
int buffsize = 65536; // I added this because I thought it was some buffer problem, but didn't change a thing
setsockopt(self_udp, SOL_SOCKET, SO_RCVBUF, (void*)&buffsize, sizeof(buffsize));
return EXIT_SUCCESS;
}
そして送信するために:
//...
for(i=0; i<num_neighbors; i++)
{
if(neighbors[i].cost == -1)
continue;
int bytes_sent = 0, ret;
while(bytes_sent < packet_size)
{
if(-1 == (ret = sendto(neighbors[i].skt, (void*)&my_neighs +
(ptrdiff_t)bytes_sent, packet_size-bytes_sent,
0, neighbors[i].p->ai_addr, neighbors[i].p->ai_addrlen)))
{
perror("sendto1");
return EXIT_FAILURE;
}
bytes_sent += ret;
}
}
//....
neighbors は、メンバー フィールドを持つ要素を含む構造体配列です。
struct addrinfo *servinfo, *p;
それらはソケットの初期化から取得され、freeaddrinfo() はプログラム実行の最後にのみ呼び出されるため、すべて有効です。