24275


いま、1つのアプリケーションで描画した画像を、もう1つのアプリケーションにリアルタイムで送信し、表示するようなプログラムを作成しています。ネットワークに関しては初心者なのですが、調べた限りでは、実際の映像ストリーミングではUDPが使われているということで、同じくUDPを使った通信を実装しました。  
具体的には、200 x
200の画像データを適当なアルゴリズムで圧縮し、約15000バイトほどのデータにしたあと、それを1398バイトの部分データに区切って、2バイトのデータのインデックス情報を付加した計1400バイトのデータをパケットに載せて送信します。送受信にはboostのasioライブラリを使用しました。送信側、受信側のともに、それ用のスレッドを用意し、それぞれひたすら送信・受信を行うようにしました。疑似的なコードで表すと以下のような感じです。

[code]

    //送信側のコード
    while(!stop_sending)
    {
        //データの取得
        data = get_image();
        //データを分割して送信
        for(int idx = 0; idx < max; ++idx)
        {
            s_buf[idx] = segment(data, idx);
            udp_sock_.send_to(boost::asio::buffer(s_buf[idx]), endpoint);
            //一応のスリープ（これは必要？）
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
        //送信間隔は30ms
        std::this_thread::sleep_for(std::chrono::milliseconds(30));
    }
    
[/code]

* * *
[code]

    //受信側
    while(!stop_receiving)
    {
        //データの受信
        auto len = sock_udp.receive_from(boost::asio::buffer(recv_buf_udp), sender_ep, 0, error);
        //取得したデータから画像を復元
        ...
    }
    
[/code]

以上の方法で、一応の画像の送受信は成功したのですが、送信の間隔を狭めるほど受信側でのパケットロスがひどくなり、リアルタイムな画像送受信が上手くいっていないような状況です。具体的には…

[code]

    送信先 : 127.0.0.1  送受信のポート : 58900
     - 送信間隔 100 ms [推定送信速度 150kB/s] → パケットロスト率 約0~10%
     - 送信間隔 30 ms [推定送信速度 450kB/s] → パケットロスト率 約40~70%
    
[/code]

のように、多くのパケットが受信時に失われており、画像が半分以上再現されないような状況です。ただ、送信開始から10フレームほどは（遅延はあるものの）完全に受信できており、その後突然としてパケットが失われ始めます。その原因も分かりかねています。450kB/sという伝送速度は、ローカルホストや同一LAN内の通信なら実現できると考えていたのですが、このパケットロスト率は仕方ないものなのでしょうか。改善できる方法などがあればご助言いただきたいです。


CC BY-SA 3.0
2016-04-22T14:30:11.213
24265
2016-04-22T21:30:17.490
14575
question
c++ boost network
UDPによるデータ送信のパケットロスを減らす方法について


UDPの場合、フロー制御はアプリケーション側で行う必要があります。

> //取得したデータから画像を復元

復元処理に1ms以上要していれば当然バッファが溢れますが、その点はどうでしょうか？


CC BY-SA 3.0
2016-04-22T21:20:06.733
24274
2016-04-22T21:20:06.733
4236
24265
answer


送信間隔100msでゆっくりと送信して450kB/sで送信しているつもりかもしれませんが、実態としては1500kB/sで送信した後に33msのディレイを入れているに過ぎません。1500kB/sで送信したときに受信側のドライバの処理が追いつかなければ、容易にパケットをロストしてしまうでしょう。

1msのディレイを4msに変更して、33msのディレイを無くせば随分と安定するはずです。


CC BY-SA 3.0
2016-04-22T21:30:17.490
24275
2016-04-22T21:30:17.490
12774
24265
answer