如何在套接字上设置不分段 (DF) 标志?
我正在尝试设置 DF(不分段标志)以使用 UDP 发送数据包.
I am trying to set the DF (don't fragment flag) for sending packets using UDP.
看Richard Steven 的书Volume 1 Unix Network Programming;Sockets Networking API,我找不到如何设置它.
Looking at the Richard Steven's book Volume 1 Unix Network Programming; The Sockets Networking API, I am unable to find how to set this.
我怀疑我会用 setsockopt() 来做,但在第 193 页的表格中找不到它.
I suspect that I would do it with setsockopt() but can't find it in the table on page 193.
请建议如何做到这一点.
Please suggest how this is done.
推荐答案
您可以使用 setsockopt()
调用来实现,使用 IP_DONTFRAG
选项:
You do it with the setsockopt()
call, by using the IP_DONTFRAG
option:
int val = 1;
setsockopt(sd, IPPROTO_IP, IP_DONTFRAG, &val, sizeof(val));
这是一个解释这个的页面更详细.
Here's a page explaining this in further detail.
对于 Linux,您似乎必须使用值为 IP_PMTUDISC_DO
(或 IP_PMTUDISC_DONT
以将其关闭)的 IP_MTU_DISCOVER
选项:
For Linux, it appears you have to use the IP_MTU_DISCOVER
option with the value IP_PMTUDISC_DO
(or IP_PMTUDISC_DONT
to turn it off):
int val = IP_PMTUDISC_DO;
setsockopt(sd, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
我没有测试过这个,只是查看了头文件和一些网络搜索,所以你需要测试它.
I haven't tested this, just looked in the header files and a bit of a web search so you'll need to test it.
至于是否有另一种方式可以设置 DF 标志:
As to whether there's another way the DF flag could be set:
我在我的程序中找不到强制 DF 标志"的任何地方已设置,但 tcpdump
表明已设置.还有其他方法可以设置吗?
I find nowhere in my program where the "force DF flag" is set, yet
tcpdump
suggests it is. Is there any other way this could get set?
从这个优秀的页面这里:
IP_MTU_DISCOVER:
设置或接收套接字的路径 MTU 发现设置.启用后,Linux 将在此套接字上执行 RFC 1191 中定义的路径 MTU 发现.在所有传出数据报上都设置了不分段标志.系统范围的默认值由 ip_no_pmtu_disc
sysctl
控制,用于 SOCK_STREAM
套接字,并在所有其他套接字上禁用.对于非 SOCK_STREAM
套接字,用户有责任将数据打包成 MTU 大小的块,并在必要时进行重新传输.如果设置了此标志(使用 EMSGSIZE
),内核将拒绝大于已知路径 MTU 的数据包.
IP_MTU_DISCOVER:
Sets or receives the Path MTU Discovery setting for a socket. When enabled, Linux will perform Path MTU Discovery as defined in RFC 1191 on this socket. The don't fragment flag is set on all outgoing datagrams. The system-wide default is controlled by theip_no_pmtu_disc
sysctl
forSOCK_STREAM
sockets, and disabled on all others. For nonSOCK_STREAM
sockets it is the user's responsibility to packetize the data in MTU sized chunks and to do the retransmits if necessary. The kernel will reject packets that are bigger than the known path MTU if this flag is set (withEMSGSIZE
).
在我看来,您可以使用 sysctl
设置系统范围的默认值:
This looks to me like you can set the system-wide default using sysctl
:
sysctl ip_no_pmtu_disc
返回<代码>错误:ip_no_pmtu_disc";在我的系统上是一个未知的密钥,但它可能被设置在你的系统上.除此之外,我不知道还有什么会影响设置(除了前面提到的 setsockopt()
).
returns "error: "ip_no_pmtu_disc" is an unknown key"
on my system but it may be set on yours. Other than that, I'm not aware of anything else (other than setsockopt()
as previously mentioned) that can affect the setting.
相关文章