LoginSignup
6
7

More than 5 years have passed since last update.

udpで65507バイト送りまくってみる(ios -> osx)

Last updated at Posted at 2016-02-27

動機

65507バイトのデータをまるっと別なところに送りたい。だけどせっかくなので、
ちょっと低レベルAPIで遊んで見たくなりました。
なのでちょっと不慣れですがudpソケット通信を試して見ようと思います。

環境

ios9.2.1, osx 10.11.1, xcode 7.2.1になります。

実装(ios: 送信側)


#import "ViewController.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

@implementation ViewController {
    NSTimer *_timer;
    int _index;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];
}

- (void)tick:(id)sender {
    const int kSendSize = 65507;

    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(3000);
    addr.sin_addr.s_addr = inet_addr("192.168.10.3");

    int maxsize = kSendSize;
    int r = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &maxsize, sizeof(int));
    assert(r == 0);

    char bytes[kSendSize] = "";
    sprintf(bytes, "index = %d", _index);
    ssize_t s = sendto(sock, bytes, sizeof(bytes), 0, (struct sockaddr *)&addr, sizeof(addr));
    if(s != kSendSize) {
        printf("failed to sendto: errno = %d, %s\n", errno, strerror(errno));
    }

    close(sock);

    _index++;
}

@end 

実装(osx: 受信側)


#include <iostream>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, const char * argv[]) {
    const int kSendSize = 65507;
    int sock = socket(AF_INET, SOCK_DGRAM, 0);

    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(3000);
    addr.sin_addr.s_addr = INADDR_ANY;

    bind(sock, (struct sockaddr *)&addr, sizeof(addr));

    for(int i = 0 ; i < 10000 ; ++i) {
        char buf[kSendSize] = {0};
        ssize_t r = recv(sock, buf, sizeof(buf), 0);
        if(r == kSendSize) {
            printf("%s\n", buf);
        }
    }

    close(sock);

    return 0;
}


Note

どうやらsetsockoptで、SO_SNDBUFを広げてあげないとうまく送れないようでした。
また、通信頻度を、1.0 / 60.0から1.0 / 120など上げてみると、
頻繁に、failed to sendto: errno = 55, No buffer space available
とエラーが吐かれて通信が不安定になるようでした。
帯域がいっぱいになった、ということのようです。

windows (vvvv)

今日から始めたvvvvなら、
iosからのudp送信、そのまま受信することができます。

SnapCrab_NoName_2016-2-27_22-47-50_No-00.png

素晴らしく簡単です

まとめ

低レベルAPIは得てして面倒だったり複雑になりがちです。
しかしながら、UDPの持つ、投げっぱなしでパケットロスを気にしない、という性質もあって、案外シンプルな実装で通信をすることができて少し驚いています。今までちょっと毛嫌いしていましたが、下手に高レベルなライブラリを使うよりも、実はこちらのほうがメリットが大きい場面もあるかもしれません。

参考

以下ページ等を参考にさせていただきました。

ソケット入門
http://software.aufheben.info/kouza/senior/kouza_socket.html

UDPを使う
http://www.geekpage.jp/programming/linux-network/udp.php

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7