记一个原始套接字不能在同一网段发包的问题

本文探讨了使用原始套接字发送自定义IP包时遇到的问题。当IP包源地址与本地地址相同时,发送到同一网段会失败。通过调整发送地址解决了该问题。
    最近编写一个原始套接字程序,自己构造IP包发送给对方,TCP和IP的校验和都计算正确了。测试的时候发现发送到不同网段成功,但是发送到同一网段却不行。
    发送的代码大约是这样的:
void Send(IP_HEADER* ip)
{
    
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    assert(sock
>0);
    
int nValue = 1;
    setsockopt(sock, IPPROTO_IP, IP_HDRINCL, 
&nValue, sizeof(nValue));
    
struct sockaddr_in addr;
    memset(
&addr, 0sizeof(struct sockaddr_in));
    addr.sin_family 
= AF_INET;
    addr.sin_addr.s_addr 
= ip->SrcIP;
    sendto(sock, (
void*)ip, ntohs(ip->Length), 0,
            (
struct sockaddr *)&addr, sizeof(struct sockaddr_in));
    close(sock);
    sock 
= 0;
}

   后来发现,问题出在发送出去的IP与IP包的IP一致的时候,发送到同一网段就会失败。
    将addr.sin_addr.s_addr = ip->SrcIP;修改成:addr.sin_addr.s_addr = inet_addr("1.1.1.1");后,同一网段也能发送成功了。

    呵呵,看来还没摸到原始套接字的脾气!
如果要你来生成这个新功能代码,我再给你头文件.h和要求就可以了吗? 课题:ARP扫描功能 要求: 1、基于NVMP平台,为NSD模块添加一个用于定时扫描指定网段的主机的arp子模块。arp子模块的扫描需要通过socket编程收发ARP报文来实现。 2、arp子模块使用DS来保存用户配置,用户配置参数包括:功能开关、扫描周期(秒)、有效期(秒)、发包间隔(毫秒)、起始IP、结束IP。 例如可以指定192.168.1.100-192.168.1.200,每格60秒扫描一遍,发包间隔100毫秒,如果网络中有192.168.1.101和192.168.1.102两台主机,则扫描结果就是这两个IP地址及对应的MAC地址。扫描功能需在开关开启对情况下才进行; 扫描的结果需要在内存中管理维护,一个ARP条目如果超过有效期时间都未被再次扫描到则删除掉该条目。 3、arp子模块需要提供基于DMS的ubus服务接口,至少提供以下接口用于客户端调用,使用TDCP协议: set_arp_config(设置功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) get_arp_config(获取功能开关、扫描周期、有效期、发包间隔、起始IP、结束IP地址) start_scan(开始一次扫描) stop_scan(停止扫描) get_scan_status(扫描状态) get_scan_result(获取最近一次的扫描结果) clear_result(清除历史结果) 其次需要提供基于ubus工具的调测命令,用于在串口执行扫描,停止扫描,获取扫描结果,获取扫描状态,清除历史扫描结果等。 4、每次发现一台新的主机(之前扫描时未发现的),将主机信息打印到串口,同时在内存中进行存储。 5、写一个测试程序test_arpsd,通过C代码调用DMS/DS库API的方式(不能直接调用ubus命令),对各部分功能和接口进行测试。 7、编写为NVMP平台NSD的一个子模块软件包,包含所有的c、shell、html代码及Makefile文件 /****************************************************************************** Copyright © 2018-2020 TP-Link Technologies CO.,LTD. 文件名称: nsd_common.h 版 本: 1.0 摘 要: NSD 通用头文件 作 者: liyijieliyijie@tp-link.com.cn 创建时间: 2018-9-5 ******************************************************************************/ #ifndef NSD_COMMON_H #define NSD_COMMON_H #include “nvmp_utils.h” #include “libds.h” #include “slp_model.h” #include “slp_error.h” #include “libdms.h” #include “nsd_event.h” #define NSD_TIMESTAMP NVMP_TIMESTAMP #define NSD_SECTOUSEC NVMP_SECTOUSEC #define NSD_USECTOSEC NVMP_USECTOSEC #define NSD_SEND(mid, mbuf, mlen) msg_send(mid, mbuf, mlen) #define NSD_SENDTO(mid, mbuf, mlen,uid) msg_sendto(mid, mbuf, mlen, uid) #define NSD_DEBUG(fmt …) do { msg_debug(DEBUG_TRACE, FUNCTION, LINE, fmt); } while (0) #define NSD_WARN(fmt …) do { msg_debug(DEBUG_WARN, FUNCTION, LINE, fmt); } while (0) #define NSD_LOG(level, fmt, …) do { msg_push_log(level, FUNCTION, LINE, “[NSD]” fmt, ##VA_ARGS); } while (0) #ifdef VIGI_ENABLE_USER_LOG #define NSD_ERROR(fmt …) do { msg_debug_log(DEBUG_ERROR, FUNCTION, LINE, fmt); } while (0) #else #define NSD_ERROR(fmt …) do { msg_debug(DEBUG_ERROR, FUNCTION, LINE, fmt); } while (0) #endif #define NSD_ASSERT(exp) do { if (!(exp)) { printf(“[SYSTEM]func=%s, line=%d ASSERT %s failed.\n”, FUNCTION, LINE, #exp); abort(); } }while(0) #define NSD_FREE SAFE_FREE #define NSD_MALLOC SAFE_MALLOC #define NSD_INIT(fn) attribute((section(“.init_array”))) typeof(fn) *__##fn = fn #endif /* NSD_COMMON_H / /***************************************************************************** Copyright © 2018-2020 TP-Link Technologies CO.,LTD. 文件名称: nsd_event.h 版 本: 1.0 摘 要: NSD 消息头文件,这里定义的消息仅在NSD系统内部通信; 作 者: huanghanlinhuanghanlin@tp-link.com.cn 创建时间: 2018-11-26 ******************************************************************************/ #ifndef NSD_MSG_H #define NSD_MSG_H /********************************* LINK_STATUS切换所用消息 ***********************/ #define NSD_LINK_STATUS_UPDATE (NSD_LOCAL_MID_BASE + 0) / 消息体直接使用LINK_STATUS的结构体 */ /********************************* mac改变所用消息 **********************/ #define NSD_MAC_CHANGE (NSD_LOCAL_MID_BASE + 1) / 消息体直接传输6字节的MAC/ /***********************cloud_client 固件下载所用消息 ***************************/ #define FW_DOWNLOAD_COMPLETE (NSD_LOCAL_MID_BASE + 4) /* 根据相同的key值,能够找到同一块共享内存 */ #define FW_SHM_KEY 0x6c1234 typedef struct _FW_BUF_INFO { unsigned int buf_len; /* 用于存放固件的共享内存的大小 */ }FW_BUF_INFO; /*********************** onvif通知ipcd更改IP消息 ***************************/ #define NSD_PROBE_IP (NSD_LOCAL_MID_BASE + 5) /***********************cloud_client 插件下载所用消息 ***************************/ #define PLUGIN_DOWNLOAD_COMPLETE (NSD_LOCAL_MID_BASE + 6) /********************** plugin manage 插件下載完成所用消息 ***********************/ #define PLUGIN_UPGRADE_COMPLETE (NSD_LOCAL_MID_BASE + 7) typedef enum { PLUGIN_UPGRADE_SUCCESS = 0, PLUGIN_UPGRADE_FAIL, } PLUGIN_UPGRADE_STATUS; /********************** 产测RNDIS控制消息 ***********************/ #define RNDIS_CTRL_MSG (NSD_LOCAL_MID_BASE + 8) typedef enum { RNDIS_CTRL_START = 0, RNDIS_CTRL_STOP, } RNDIS_CTRL_CMD; #endif/* end of nsd_event.h */
08-26
博客地址:https://blog.youkuaiyun.com/weixin_41749063/article/details/104023987 摘要: ## 1.简介 其实Qt网络模块中自带的[QTcpsocket](https://doc.qt.io/archives/qt-5.6/qtcpsocket.html)已经封装的很好了,避免了用原始套接字编程繁琐的过程,不过大部分应用场景我们希望将收发数据 运行在一个单独的线程,不阻塞界面或其他线程。所以结合Qt自带的QThread类 简单的封装了一下QTcpsocket,使其工作 在单独线程,并加入了心跳和断线重连机制。 ## 2.EasyClient类说明 由于接触QT时间不是很长,所以写的不是很好,可能里边也有Bug,不过觉得这个思路应该是可行的。封装的比较简单,若有问题完全可以自己改改。主要提供一个思路就是的将一个继承自QObject的子类转移到一个线程,使其在这个线程里进行事件循环,开一个定时器用于发送心跳和重连。 经过采坑发现,定时器的开和关需放在实例化EasyClient子类的那个线程(下面称之为主线程),不能在事件循环线程中(下面称之为子线程中)否则会有错。实例化QTcpsock需要在 子线程中进行,否则会出现无法正常通信的现象。 使用时只需要实例化一个EasyClient的子类,重写SendHeartBeat()和DisPoseReceiveData()两个纯虚函数,SendHeartBeat()决定发什么内容作为心跳指令,当有数据可读时会全部读入,只需要在DisPoseReceiveData()做处理即可。.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值