原始套接字的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原始套接字的问题相关的知识,希望对你有一定的参考价值。
01 int ts_create_raw_socket(char *device, BYTE *mac)
02
03 int sock_fd;
04 struct ifreq ifr;
05 struct sockaddr_ll sll;
06
07 memset(&ifr, 0, sizeof(ifr));
08 memset(&sll, 0, sizeof(sll));
09
10 sock_fd = socket (PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
11 if (sock_fd == 0)
12
13 printf(" TRFSQRERR: socket creation for device: %s\n", device);
14 return 0;
15
16
17 strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
18 if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) == -1)
19
20 printf(" TRFSQERR: ioctl failed for device: %s\n", device);
21 return 0;
22
23 sll.sll_family = AF_PACKET;
24 sll.sll_ifindex = ifr.ifr_ifindex;
25 sll.sll_protocol = htons(ETH_P_ALL);
26 if (bind(sock_fd, (struct sockaddr *) &sll, sizeof(sll)) == -1)
27
28 printf(" TRFSQERR: bind failed for device: %s\n", device);
29 return 0;
30
31
32 memset(&ifr, 0, sizeof(ifr));
33 strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
34 if (ioctl(sock_fd, SIOCGIFHWADDR, &ifr) == -1)
35
36 printf(" TRFSQERR: ioctl failed for device: %s\n", device);
37 return 0;
38
39 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
40 /* set promisc mode: Added: 6-May-07: Kiran */
41 ifr.ifr_flags |= IFF_PROMISC;
42 if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1)
43
44 return 0;
45
46
47 return sock_fd;
48 /* ts_create_raw_socket */
首先:也是最迫切知道的,该套接字能接收到什么样的数据包,
其次:三次调用ioctl函数的用意。
最后:请着重讲一下第10行。
在此,谢谢了
问题二:
SIOCGIFINDEX-获取网络接口索引
SIOCGIFHWADDR-获取MAC地址
SIOCSIFFLAGS-不知道 参考技术A 我会努力想的!!放心吧追问
感谢
原始套接字的数据包碎片
【中文标题】原始套接字的数据包碎片【英文标题】:packet fragmentation for raw sockets 【发布时间】:2011-05-10 10:14:03 【问题描述】:如果我使用原始套接字发送大小为 3000 字节的 UDP 数据包,我是否需要在代码中自己处理数据包碎片,还是应该使用原始套接字处理类似于 DGRAM 套接字的碎片?
【问题讨论】:
如果我没记错的话,我怀疑我是这个,你必须担心丢包等等,UDP是一种尽力而为的协议。 数据包(如果已接收)很好 - 但是,不能保证保留订单。显然,如果您是发送/响应/发送/响应,这不是问题,但如果您正在流式传输,则会出现问题。 UDP 的问题在于,一旦你实现了所有的内务处理,你就希望你一开始就完成了 TCP。通常,当您不担心丢失数据包时,情况并非如此。 你能澄清一下在这种情况下你所说的 raw 到底是什么意思吗?您是否在编写原始以太网帧、原始 IP 数据包?你在什么系统上做这个?有些系统提供某种“半-n-半”套接字... 我的意思是通过 IP_RAW 套接字发送 IP 数据包。 后续问题在这里***.com/questions/4191253/…。 【参考方案1】:对于 Linux,答案是肯定的。如果你看一下 Linux 的 raw socket implementation,原始套接字不会发生重组。
【讨论】:
【参考方案2】:好吧,如果您使用的是 UDP,那么您实际上并没有发送 RAW。 RAW 根本就没有 IP,在这种情况下,是的,您必须自己处理碎片。
使用 UDP,您可以获得 IP 分片支持,恕我直言,这对于应该尽量减少冲突的短途网络来说已经足够好了。使两个系统之间的链接成为一个专用子网,这根本不是问题。
TCP 通过 UDP 为您带来的好处(除其他外)是堆栈的能力,如果它以某种方式丢失或损坏,则只需重新发送一个片段。如果发生这种情况,使用 UDP 必须丢弃整个消息。不过,这样做会产生开销,对于大多数现代网络,您可能可以接受这种权衡。
【讨论】:
同意其他答案缺少“原始”的观点。虽然不同意您的结论,但某些系统具有“原始 IP”套接字,您仍然指定 ip 标头的源地址和目标地址,但您自己编写数据包的其余部分。在这种情况下,将有一个 IP 标头(一半由应用程序构建,一半由较低级别管理),并且它会像往常一样有一个 DF 位。 @awoodland - 很有趣。我的经验主要是编写自己的堆栈。如果用户正在处理填写 IP 数据包,我认为他们还必须处理将传入的 IP 片段组装成消息。 我以为问题只是关于传输,因为它询问了发送!问题是在这种情况下,“原始”的含义并不是很清楚。 我在***.com/questions/4191253/… 添加了关于如何处理碎片的后续问题。谢谢你的回答。【参考方案3】:根据您的系统,这可以完全不同地处理。例如,在 Linux 上,如果您尝试发送大于(已知)路径 MTU 的内容,您可以要求较低层处理路径 MTU 发现并给出错误 (EMSGSIZE)。
您所说的原始套接字有多“原始”?其他系统可能只是让您控制 DF 位(或者您可能自己构建大部分 IP 标头),在这种情况下,行为也将取决于此。
通常,如果您使用 DF 集进行传输,您通常会选择在用户空间中查看错误,或者让主机上的较低级别处理 PMTU 发现并阻止您发送过大的内容。如果您不设置 DF,那么您(可能)会看到沿路径来自路由器的适当碎片。
【讨论】:
【参考方案4】:底层协议 IP 仍然处理碎片。只要你不设置DF(不要分段)位,我认为你应该没问题。
【讨论】:
【参考方案5】:不,数据包分段在较低级别处理。您应该确切地看到您放入数据包的内容回来了。也就是说UDP保证了消息边界。
【讨论】:
以上是关于原始套接字的问题的主要内容,如果未能解决你的问题,请参考以下文章