如何在套接字上设置不分段(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_MTU_DISCOVER
选项(或 IP_PMTUDISC_DONT
将其关闭):
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.
相关文章