Skip to main content

ログ取得ツール (移転先予定地)

TCPでsendmsg()を使う

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.. 
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

アドレスを隠す意味などあるのだろうか??