LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1667|回复: 4

多IP、基于UDP的socket编程,如何确定信息包的接收IP

[复制链接]
发表于 2007-6-27 09:25:04 | 显示全部楼层 |阅读模式
Linux系统,一个有多个IP的server,基于UDP的SOCKET编程,用recvfrom函数接收数据,在bind时不绑定sock的ip地址。接收到数据后,怎样确定该数据包是由本机的哪个ip地址接收的呢?请各位不吝赐教,谢谢!
发表于 2007-6-27 10:16:46 | 显示全部楼层
普通的网络应用不需要知道这个吧?你为什么要确定这个
想知道就bind吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-6-27 17:21:57 | 显示全部楼层
我的程序里面必须要用到这个,而且必须是不bind的情况下知道本地接收ip,请问有什么办法没有,谢谢了!
回复 支持 反对

使用道具 举报

发表于 2007-6-28 06:59:38 | 显示全部楼层
http://lists.cistron.nl/pipermai ... 2-March/005600.html
  1. /*
  2. * recvfromto        Like recvfrom, but also stores the destination
  3. *                IP address. Useful on multihomed hosts.
  4. *
  5. *                Should work on Linux and BSD.
  6. *
  7. *                Copyright (C) 2002 Miquel van Smoorenburg.
  8. *
  9. *                This program is free software; you can redistribute it and/or
  10. *                modify it under the terms of the GNU Lesser General Public
  11. *                License as published by the Free Software Foundation; either
  12. *                version 2 of the License, or (at your option) any later version.
  13. */
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include <sys/uio.h>
  17. #include <netinet/in.h>
  18. #include <errno.h>
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. /* Remove this when autoconf can detect this. */
  22. #if defined(IP_PKTINFO) && !defined(HAVE_IP_PKTINFO)
  23. #  define HAVE_IP_PKTINFO 1
  24. #elif defined(IP_RECVDSTADDR) && !defined(HAVE_IP_RECVDSTADDR)
  25. #  define HAVE_IP_RECVDSTADDR
  26. #endif
  27. int recvfromto(int s, void *buf, size_t len, int flags,
  28.         struct sockaddr *from, socklen_t *fromlen,
  29.         struct sockaddr *to, socklen_t *tolen)
  30. {
  31.         struct msghdr msgh;
  32.         struct cmsghdr *cmsg;
  33.         struct iovec iov;
  34.         char cbuf[1024];
  35.         int opt, err;
  36.         /*
  37.          *        If from or to are set, they must be big enough
  38.          *        to store a struct sockaddr_in.
  39.          */
  40.         if ((from && (!fromlen || *fromlen < sizeof(struct sockaddr_in))) ||
  41.             (to   && (!tolen   || *tolen   < sizeof(struct sockaddr_in)))) {
  42.                 errno = EINVAL;
  43.                 return -1;
  44.         }
  45.         if (tolen) *tolen = 0;
  46. #ifdef HAVE_IP_PKTINFO
  47.         /*
  48.          *        IP_PKTINFO doesn't provide sin_port so we have to
  49.          *        retrieve it using getsockname().
  50.          */
  51.         if (to) {
  52.                 struct sockaddr_in si;
  53.                 socklen_t l = sizeof(si);
  54.                 ((struct sockaddr_in *)to)->sin_family = AF_INET;
  55.                 ((struct sockaddr_in *)to)->sin_port = 0;
  56.                 l = sizeof(si);
  57.                 if (getsockname(s, (struct sockaddr *)&si, &l) == 0) {
  58.                         ((struct sockaddr_in *)to)->sin_port = si.sin_port;
  59.                         ((struct sockaddr_in *)to)->sin_addr = si.sin_addr;
  60.                 }
  61.                 *tolen = sizeof(struct sockaddr_in);
  62.         }
  63. #endif
  64.         /* Set MSG_DONTWAIT if O_NONBLOCK was set. */
  65.         if (fcntl(s, F_GETFL) & O_NONBLOCK) flags |= MSG_DONTWAIT;
  66.         /* Set up iov and msgh structures. */
  67.         iov.iov_base = buf;
  68.         iov.iov_len  = len;
  69.         msgh.msg_control = cbuf;
  70.         msgh.msg_controllen = sizeof(cbuf);
  71.         msgh.msg_name = from;
  72.         msgh.msg_namelen = fromlen ? *fromlen : 0;
  73.         msgh.msg_iov  = &iov;
  74.         msgh.msg_iovlen = 1;
  75. #ifdef HAVE_IP_PKTINFO
  76.         /* Set the IP_PKTINFO option (Linux). */
  77.         opt = 1;
  78.         setsockopt(s, SOL_IP, IP_PKTINFO, &opt, sizeof(opt));
  79. #endif
  80. #ifdef HAVE_IP_RECVDSTADDR
  81.         /* Set the IP_RECVDSTADDR option (BSD). */
  82.         opt = 1;
  83.         setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt));
  84. #endif
  85.         /* Receive one packet. */
  86.         err = recvmsg(s, &msgh, flags);
  87.         if (fromlen) *fromlen = msgh.msg_namelen;
  88.         /* Process auxiliary received data in msgh */
  89.         for (cmsg = CMSG_FIRSTHDR(&msgh);
  90.              cmsg != NULL && cmsg->cmsg_len >= sizeof(*cmsg);
  91.              cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
  92. #ifdef HAVE_IP_PKTINFO
  93.                 if (cmsg->cmsg_level == SOL_IP
  94.                     && cmsg->cmsg_type == IP_PKTINFO) {
  95.                         struct in_pktinfo *i =
  96.                                 (struct in_pktinfo *)CMSG_DATA(cmsg);
  97.                         if (to) {
  98.                                 ((struct sockaddr_in *)to)->sin_addr =
  99.                                         i->ipi_addr;
  100.                                 *tolen = sizeof(struct sockaddr_in);
  101.                         }
  102.                         break;
  103.                 }
  104. #endif
  105. #ifdef HAVE_IP_RECVDSTADDR
  106.                 if (cmsg->cmsg_level == IPPROTO_IP
  107.                     && cmsg->cmsg_type == IP_RECVDSTADDR) {
  108.                         struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg);
  109.                         if (to) {
  110.                                 ((struct sockaddr_in *)to)->sin_addr = *i;
  111.                                 *tolen = sizeof(struct sockaddr_in);
  112.                         }
  113.                 }
  114. #endif
  115.         }
  116.         return err;
  117. }
  118. #ifdef STANDALONE
  119. #include <stdio.h>
  120. #include <stdlib.h>
  121. #include <arpa/inet.h>
  122. /*
  123. *        Small test program to test recvfromto
  124. */
  125. int main(int argc, char **argv)
  126. {
  127.         struct sockaddr_in from, to, in;
  128.         char buf[1024];
  129.         int port = 20000;
  130.         int n, s, fl, tl;
  131.         if (argc > 1) port = atoi(argv[1]);
  132.         s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  133.         in.sin_family = AF_INET;
  134.         in.sin_port = htons(port);
  135.         in.sin_addr.s_addr = INADDR_ANY;
  136.         bind(s, &in, sizeof(in));
  137.         while (1) {
  138.                 fl = tl = sizeof(struct sockaddr_in);
  139.                 memset(&from, 0, sizeof(from));
  140.                 memset(&to, 0, sizeof(to));
  141.                 if ((n = recvfromto(s, buf, sizeof(buf), 0,
  142.                     (struct sockaddr *)&from, &fl,
  143.                     (struct sockaddr *)&to, &tl)) < 0) {
  144.                         perror("recvfromto");
  145.                         break;
  146.                 }
  147.                 printf("Received a packet of %d bytes\n", n);
  148.                 printf("  src ip:port %s:%d\n",
  149.                         inet_ntoa(from.sin_addr), ntohs(from.sin_port));
  150.                 printf("  dst ip:port %s:%d\n",
  151.                         inet_ntoa(to.sin_addr), ntohs(to.sin_port));
  152.         }
  153.         return 0;
  154. }
  155. #endif /* STANDALONE */
复制代码
回复 支持 反对

使用道具 举报

发表于 2007-6-28 09:50:51 | 显示全部楼层
真复杂
翻了下UNP,原来有写
没好好读阿
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表