Macでudpソケットプログラミング中のエラー "sendto: message too long"

大学の実験で、UDP上でTCPっぽい振る舞いを作れという課題があって、その課題を解いているうちにぶち当たったエラー

int error = sendto(sock, sendpkt, (int)sizeof(sendpkt), 0, distination_addr, sizeof(distination_addr));
if(error < 1){
  perror("sendto");
  exit(1);
}

こんなコードがあったとして、sendpktの大きさが9000ぐらいになると

”message too long”
こんなエラーを受け取って、データを送れない。

バッファの容量が足りてないのかな?と思って、

printf("SO_SNDBUF:%d",SO_SNDBUF);

”SO_SNDBUF:4097”

ソケットの送信バッファは4097!?これバッファ漏れ発生するんじゃね?

バッファ漏れはしませんでした。ってことは、本当はバッファサイズもっとデカいのか?

試します。

int val;
int len = sizeof(val);
getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &val, &len);
printf("%d¥n",val);

”9216”

おっと、getsockoptで設定されているバッファサイズは9216バイトらしい。

SO_SNDBUFに必ず正しい値が入ってるとは限らないんですね。。。。

この流れだと、setsockoptでbufferサイズを変更しても変わらないので、カーネルのパラメータでそれっぽいのを探します。

$sysctl -a | grep udp
..
net.inet.udp.maxdgram: 9216
..

この、net.inet.udp.maxdgramがカーネルが設定しているUDPデータグラムの最大サイズなのでこの値を、変更してあげるとソケットのバッファサイズの最大サイズもあげることができるようになります。

$sysctl -w net.inet.udp.maxdgram=<大きい値>

これで、"sendto: message too long" のエラーは解消されます。

まとめ

"sendto: message too long"エラーの原因は、カーネルのパラメータのnet.inet.udp.maxdgramが送りたいバイト数より小さかったのでsocketでエラーが起きました。