2016-12-27 4 views
0

私はUDPソケットをiOS上で使用しています。ノンブロッキングモードに設定したり、不正な接続をシミュレートすると、私は非常に奇妙な動作を経験します。通常のfcntlと非ブロックモードでソケットを設定するにはUDPソケットのインコヒーレントな動作

fcntl(socketfd, F_SETFL, O_NONBLOCK); 

5/5イン/アウト、パケットロスや50KBpsと私はネットワークリンクConditioneerを使用し、接続不良をシミュレートするには限界(保証します私の場合、システムのバッファはある時点でいっぱいになるでしょう)。

私はsendto()でデータを送信し、clock()printf()でコールをします。ここで


私のテストからのデータを、ミリ秒でのデータです:

  1. ブロッキング、良好な接続:min 0/max 929//std 111
  2. ブロッキング、接続不良:min 0/max 611/avg 38/std 84
  3. 非ブロッキング、接続良好:min 0/max 6244/avg 601/std 1071
  4. 非ブロッキング、接続不良:min 0/max 5774/avg 400/std 747

は私もsendto()がすぐに戻ってきたことを意味し、場合2に多くのエントリが0 msであることがわかり、低説明ケースの平均および標準偏差。

いつも、sendto()は、送信が要求されたバイト数に対応する正の値を返しました。

さて、私は理解できないいくつかのものがあります

  1. モードをブロックで、私はそれではなく、データがあると思われ、データを格納するために利用可能なシステムバッファがあるまで、それはブロックすることが予想されるがスペースが実際に存在するまで、私が代わりにデータから、sendto()は、それがブロックされるエラーを返すことを期待する非ブロックモードで
  2. (すぐに呼び出しが戻るので)捨て
を実行するために、コール・ブロックと思われます

Th eの動作は反転しているように見えますが、sendtoはエラーを報告しません。

私は間違っていますか?


ソケットの作成:への送信

int socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); 
// error checks 
setsockopt(socketfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); 

int tos = 0xB8; // VOICE 
setsockopt(socketfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); 

int rc = fcntl(m_iSocket, F_SETFL, O_NONBLOCK); 
if (rc != 0) { 
    // error of fcntl is notified 
} 

sendto(socketfd, buffer, buffer_length, 0, (struct sockaddr *) &m_sRemoteHost, sizeof(m_sRemoteHost)) 

答えて

2

はどのようにあなたのシステムの送信バッファがフルになっている知っているのですか?接続の速度を制限しているため、データは送信バッファにバックアップされていると仮定しています。それは他のどこかに落ちている可能性が高いです。 UDPはパケットが配信されることを保証しないため、パケットパス上の任意の場所にあるソフトウェアまたはハードウェアは、何らかの理由でいつでも破棄することができます。 UDP page on Wikipedia当たり

UDPは はRFCに768 UDPメッセージ配信用上層 プロトコルとUDPに保証を提供しないと記載され、最小限のメッセージ指向のトランスポート層プロトコルでありますレイヤーは一度送信された UDPメッセージの状態を保持しません。このため、UDPは と呼ばれ、として信頼性がありません。データグラムプロトコル。

+0

私はUDPがいかなる保証も提供しないことを理解します。私はまた、フロー制御が関与していないことを理解しています。なぜ私が理解できないのは、sendto()コールの時間が接続品質によって大きく変わるのか、それがどうして変化するのかを解釈できないことです。完全な送信バッファのためにパケットが実際にシステムによって廃棄されたことを実際に検出する方法はありますか?フロー制御がないので、バッファーはいっぱいになる可能性がありますか? –