2010-12-09 5 views
8
#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 

int main() 
{  
    struct sockaddr_in addr; 
    int fd, cnt,ret; 
    char ch = 'y',msg[] ="How are you"; 

    if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) { 
     printf("Error: socket"); 
     exit(1); 
    } 
    printf("\nDone socket\n"); 

    /* set up destination address */ 
    memset(&addr,0,sizeof(addr)); 
    addr.sin_family=AF_INET; 
    addr.sin_addr.s_addr=inet_addr("128.88.143.113"); 
    addr.sin_port=htons(9090); 

    ret=connect(fd,(struct sockaddr *)&addr,sizeof(addr)); 
    perror("Connect:"); 

    while(ch == 'y'){ 
     cnt = send(fd,msg,sizeof(msg),0); 
     if(cnt < 0) 
     perror("send:"); 
     printf("\nNumber of bytes sent = %d , \n",cnt); 
     printf("Continue (y/n)\n"); 
     scanf(" %c",&ch); 

    } 

    return 0; 
} 

上記のコードは、Linuxマシンで実行するようにコンパイルされています。UDPはconnect()後の動作を送信します。

上記のコードがIPアドレス128.88.143.113のマシンにデータを送信したとします。 UDPソケットは9090128.88.143.113にバインドされていません。 whileループにおいて

send()の最初の呼び出しが成功(パケットが実際にワイヤー上に出る。traceを使用してチェックする)と第二send()Connection refusedで失敗します。 third send()は成功し、後は失敗します。

最初にsend()の後にスタックは、ソケット構造に保存されたICMPエラーメッセージ(Linuxマシンではtcpdumpに表示されます)を受信すると考えられます。 2番目のsend()はこのエラーが発生すると失敗し、実際にパケットは送信されません。 2番目のsend()は、ソケット構造のエラーもクリアします。したがって、3番目のsend()は成功し、4番目は失敗します。

質問:

  1. この仮定が正しいですか?
  2. 正しい動作は何ですか?このような動作を定義するRFC標準はありますか?
  3. UDPは接続状態を維持しないので、すべてsend()が成功するとは限りませんか?
+0

別名インターフェースを経由送信するとき、私はアーチのLinuxマシン上で同様の動作を参照してください。これは解決しましたか? –

答えて

1

もう一方の端から開始するには、UDPソケットを接続すると次の送信時にエラーを収集できます。あなたがそれを望まないなら、接続しないでください!

2

connect()send()ではなく、sendto()を使用して同等のコードを比較すると面白いでしょう。

各送信の間に一定の時間を置かないと、コードが同じように失敗するかどうか、つまりICMPエラー状態が一定期間ソケットに保持されているか、あなたは一時間、それを去ったのですか?

私はあなたの前提が正しいと思っています。ネットワークスタックは賢明にしようとしています。 connect()呼び出しが発行されたときに何も送られないので、ソケットが「論理的に」接続され、send()への呼び出しが機能するように与えられたアドレスを格納するだけで、「接続が拒否されました。 linux man page for udpによると

5

すべての致命的なエラーが ソケットが接続されていない場合でも、エラーリターンとして ユーザーに渡されます。これには、 ネットワークから受信した非同期エラー が含まれます。 同じソケットで送信された先のパケット のエラーが発生することがあります。この動作は、 と多くの他のBSDソケット の実装が異なります。ソケットが接続されていない限り、 のエラーは発生しません。 Linuxの動作はRFC 1122で義務づけられています。

具体RFC(4.1.3.3)状態:

UDPは、すべてのICMPエラーをアプリケーション層には、IP層から受信 メッセージを渡さなければなりません。概念的に は、少なくとも、これはあなたの仮説が正しい

3

ルーチン ERROR_REPORTへのアップコールを用いて達成することができます。 Linux UDP(7)のmanページは、このような状況を説明します

すべての致命的なエラーはエラーリターンソケットが接続されていなくても としてユーザーに を渡されます。 これは、ネットワークから受信 非同期エラーを含んでいます。あなたは 同じソケット上で送信された以前のパケット のエラーを得ることができます。
この動作は、ソケットが接続されて でない限り は、すべてのエラーを渡さない、他の多くの BSDソケットの実装とは異なります。 Linuxの動作は で、RFC 1122である。 IP_RECVERRオプションがある

は、すべてのエラーが ソケットのエラー・キューに格納され、 MSG_ERRQUEUEフラグを設定してrecvmsg(2)によって を受信することができる可能にしました。

0

私は同じ問題を抱えていました。これは、誰も待機していない場合にudpメッセージキューがいっぱいになるためです。

関連する問題