我是靠谱客的博主 沉默小土豆,最近开发中收集的这篇文章主要介绍linux获取udp报文的ip和 端口,linux udp 套接字编程获取源地址和目的地址(一),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

通过设置套接字的选项(IP_PKTINFO) 来获取收到报文的源地址和目的地址。

这里使用的是调用的是recvmsg接口,实际上一个还有更简单的接口recvfrom接口也能够满足要求,可以参考这篇博客。

https://blog.csdn.net/fuyuande/article/details/80588453

代码如下:

/*

* Description : UDP套接字编程获取源地址和目的地址

* Date : 20180527

*/

#include #include #include #include #include #include #include #include #include #include #include #include #include "udptest.h"

void main() {

int on = 1;

int ret, fd, addr_len, recv_len;

char buffer[512] = {0}; /* 接收缓存 */

struct msghdr msg;

struct iovec iov[1];

struct sockaddr_in saddr; /* src */

struct sockaddr_in daddr; /* dst */

struct cmsghdr *cmhp;

struct sockaddr_in server_addr;

struct in_pktinfo *pktinfo = NULL; /* 用于指向获取的本地地址信息 */

char buff[CMSG_SPACE(sizeof(struct in_pktinfo) + CMSG_SPACE(sizeof(int)))] = {0}; /* 控制信息 */

struct cmsghdr *cmh = (struct cmsghdr *)buff; /* 控制信息 */

addr_len = sizeof(struct sockaddr_in);

memset(&buffer, 0, sizeof(buffer));

memset(&msg, 0, sizeof(struct msghdr));

memset(&iov, 0, sizeof(struct iovec));

memset(&saddr, 0, sizeof(struct sockaddr_in));

memset(&daddr, 0, sizeof(struct sockaddr_in));

// 创建UDP套接字

fd = socket(AF_INET, SOCK_DGRAM, 0);

if (fd == -1) {

log("create socket fail rn");

return ;

}

// 设置监听地址

server_addr.sin_family = AF_INET;

server_addr.sin_addr.s_addr = INADDR_ANY; // 所有地址

server_addr.sin_port = htons(3500);

// 设置SO_REUSEADDR属性, 地址复用

if ((ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) != 0) {

log("setsockopt reuseaddr fail, ret : %d,error : %d rn", ret, errno);

close(fd);

return ;

}

/* 设置IP_PKTINFO属性 */

if (0 != setsockopt(fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on))) {

log("setsockopt ip_pktinfo fail, errno : %d rn", errno);

close(fd);

return ;

}

// 绑定本地监听地址

if (0 != bind(fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in))) {

printf("bind local listening addr fail,errno : %d rn", errno);

close(fd);

return ;

}

// 接收信息

while(1) {

msg.msg_name = &saddr; // 存储报文来源地址,端口

msg.msg_namelen = addr_len;

msg.msg_iov = &iov[0];

msg.msg_iovlen = 1;

msg.msg_control = cmh;

msg.msg_controllen = sizeof(buff);

iov[0].iov_base = &buffer;

iov[0].iov_len = sizeof(buffer);

// 超时退出

recv_len = recvmsg(fd, &msg, 0);

if (recv_len > 0)

{

/* 辅助信息 */

msg.msg_control = cmh;

msg.msg_controllen = sizeof(buff);

for (cmhp = CMSG_FIRSTHDR(&msg); cmhp; cmhp = CMSG_NXTHDR(&msg, cmhp)) {

if (cmhp->cmsg_level == IPPROTO_IP) {

if (cmhp->cmsg_type == IP_PKTINFO) {

pktinfo = (struct in_pktinfo *)CMSG_DATA(cmhp);

daddr.sin_family = AF_INET;

daddr.sin_addr = pktinfo->ipi_addr;

/* 报文源地址、端口 */

log("saddr : %u:%u:%u:%u:%hu rn", NIPQUAD(saddr.sin_addr), ntohs(saddr.sin_port));

/* 报文目的地址 */

log("daddr : %u:%u:%u:%u rn", NIPQUAD(daddr.sin_addr));

log("daddr : %u:%u:%u:%u rn", NIPQUAD(pktinfo->ipi_spec_dst));

}

}

}

}

memset(buffer, 0, sizeof(buffer));

memset(buff, 0, sizeof(buff));

memset(&saddr, 0, sizeof(struct sockaddr_in));

memset(&daddr, 0, sizeof(struct sockaddr_in));

}

return ;

}

头文件:

#ifndef _UDPTEST_H

#define _UDPTEST_H

#define log(fmt, arg...) printf("[udptest] %s:%d "fmt, __FUNCTION__, __LINE__, ##arg)

#ifndef NIPQUAD

#define NIPQUAD(addr)

((unsigned char *)&addr)[0],

((unsigned char *)&addr)[1],

((unsigned char *)&addr)[2],

((unsigned char *)&addr)[3]

#endif

#endif

Makefile:

default:

@gcc -o udptest udptest.c

clean:

@rm -rf udptest

命令行执行程序后使用网络调试助手发送报文查看打印信息:

e66f829858c8f109fa1adafb88d2f0c3.png

这里可以看到有两个目的地址。这是因为在设置IP_PKTINFO 选项后,返回的结构体包含两个目的地址,通常情况下这两个地址是一样的,路由目的地址指的是报文原始的目的地址,如果是广播报文的话这里就是255.255.255.255,头标识目的地址指的是本地程序的地址,例如一台路由器可能连接多台PC,当外部程序发送报文的时候填写到目的地址是路由器的地址,路由器会把这样到报文转发到对应到设备,这时头标识目的地址就是对应设备的地址。

structin_pktinfo

{

unsignedint ipi_ifindex; /*接口索引*/

struct in_addr ipi_spec_dst; /*路由目的地址*/

struct in_addr ipi_addr; /*头标识目的地址*/};

通过wireshark 可以看出:

bbab64c7150fffc2b10a2dcca7fc195f.png

linux 网络调试助手可以在这里下载,当然也可以找到对应到windows版本

链接: https://pan.baidu.com/s/1Z15YxE1r-dIOU_l9saEO0A

密码: i7am

参考文档:

https://www.cnblogs.com/kissazi2/p/3158603.html

最后

以上就是沉默小土豆为你收集整理的linux获取udp报文的ip和 端口,linux udp 套接字编程获取源地址和目的地址(一)的全部内容,希望文章能够帮你解决linux获取udp报文的ip和 端口,linux udp 套接字编程获取源地址和目的地址(一)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部