获取传入UDP数据包的目标端口

时间:2017-04-28 09:00:25

标签: c++ linux sockets c++11 udp

我已经阅读了ip手册页以及套接字手册页,我所能找到的只是标题中IP_PKTINFO控制消息中的目标IP地址,似乎没办法从数据包的标头中拉出目标端口。或者有吗?

如果没有,有没有办法从数据包到达套接字的端口获取端口?

1 个答案:

答案 0 :(得分:0)

当您使用普通套接字时,可以在套接字fd上使用recvfrom。 recvfrom的手册页:

  

RECV(2)

     

NAME

   recv, recvfrom, recvmsg - receive a message from a socket
     

概要

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

        ssize_t recv(int sockfd, void *buf, size_t len, int flags);

        ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                         struct sockaddr *src_addr, socklen_t *addrlen);

        ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
  

说明

   The  recv(),  recvfrom(),  and recvmsg() calls are used to receive messages from a socket.  They
   may be used to receive data on both connectionless and connection-oriented sockets. 
     

recvfrom的()          recvfrom()将收到的消息放入缓冲区buf中。调用者必须指定大小          len中的缓冲区。

   If src_addr is not NULL, and the underlying protocol provides the source address of the message,
   that source address is placed in the buffer pointed to by src_addr.  In this case, addrlen is  a
   value-result  argument.   Before  the  call,  it should be initialized to the size of the buffer
   associated with src_addr.  Upon return, addrlen is updated to contain the  actual  size  of  the
   source  address.  The returned address is truncated if the buffer provided is too small; in this
   case, addrlen will return a value greater than was supplied to the call.

   If the caller is not interested in the source address, src_addr and addrlen should be  specified
   as NULL.

beej指南中的一个例子:

// datagram sockets and recvfrom()

struct addrinfo hints, *res;
int sockfd;
int byte_count;
socklen_t fromlen;
struct sockaddr_storage addr;
char buf[512];
char ipstr[INET6_ADDRSTRLEN];

// get host info, make socket, bind it to port 4950
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, "4950", &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);

// no need to accept(), just recvfrom():

fromlen = sizeof addr;
byte_count = recvfrom(sockfd, buf, sizeof buf, 0, &addr, &fromlen);

printf("recv()'d %d bytes of data in buf\n", byte_count);
printf("from IP address %s\n",
    inet_ntop(addr.ss_family,
        addr.ss_family == AF_INET?
            ((struct sockadd_in *)&addr)->sin_addr:
            ((struct sockadd_in6 *)&addr)->sin6_addr,
        ipstr, sizeof ipstr);

Example of recvfromman page of recvfrom

希望这有帮助