TCPでsendmsgによりiovecでscatter/gatherなバッファから送信した場合。
MTUにおさまる限り、正しく1つのパケットになります。etherealで角煮を…じゃない、確認してみた。まあ当然そうあるべき、と思っていたがちゃんと確認したのは初めて。コピーがどう起こるのかは知らない。
カーネル(TCPドライバ? Etherドライバ?)がユーザ空間からのコピーついでにつなげてるのか、Etherのハードまでs/gでいってハードがつなげて送ってるのかは知らない。まあでもTCPだし1つのバッファにコピーしてるんだろうな。まあそんなことはどうでもいい。使おうこれ。
…後で読んでも意味不明だろうな。
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> int main(int argc, char **argv) { int s, flags=0, r; struct msghdr msg; struct iovec iov[2]; struct sockaddr_in addr; int addrlen=sizeof(addr); const char *testdata1="test.\n"; const char *testdata2="test2.\n"; s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if(s==-1){ perror("socket"); return -1; } addr.sin_family=PF_INET; addr.sin_port=htons(9999); addr.sin_addr.s_addr=inet_addr("XXX.XXX.XXX.XXX"); r=connect(s, &addr, addrlen); if(r==-1){ perror("connect"); return -1; } iov[0].iov_base=testdata1; iov[0].iov_len=strlen(testdata1); iov[1].iov_base=testdata2; iov[1].iov_len=strlen(testdata2); msg.msg_name=NULL; msg.msg_namelen=0; msg.msg_iov=iov; msg.msg_iovlen=2; msg.msg_control=NULL; msg.msg_controllen=0; msg.msg_flags=0; // MSG_OOB|MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL r=sendmsg(s, &msg, flags); printf("sendmsg(%d, %p, %d)=%d\n", s, &msg, flags, r); if(r==-1){ perror("sendmsg"); } close(s); return 0; }
(前略) 0020 XX XX b4 61 27 0f c3 81 52 18 c3 98 f6 75 80 11 XX.a'... R....u.. 0030 7f ff 5b d2 00 00 01 01 08 0a 00 d9 9b c7 00 d9 ..[..... ........ 0040 9b c7 74 65 73 74 2e 0a 74 65 73 74 32 2e 0a ..test.. test2.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
アドレスを隠す意味などあるのだろうか??