我是 Linux 网络方面的新手。我特别查看了一些 ICMP 协议的示例,特别是查看了 ping 请求和回复。通常都是从打开原始套接字开始的
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
然后就有了类似的东西(粗略的代码)
while (1) {
sendto(sockfd, ...);
usleep(CERTAIN_TIME);
recvfrom(sockfd, ...);
// then the reply is elaborated
}
我想知道是否也可以打开其中两个原始套接字:一个仅用于sendto
,另一个用于recvfrom
并由两个不同的线程使用它们:
// initialization
int sendsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
int recvsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
然后
// thread 1
while (1) {
sendto(sendsock, ...);
usleep(CERTAIN_TIME);
}
// thread 2
while (1) {
recvfrom(recvsock, ...);
usleeep(CERTAIN_TIME);
}
它安全吗?
由于 ICMP 协议是无连接的,并且没有要绑定的端口号,因此所有 ICMP 套接字本质上都是等效的。同一进程中的多个套接字与不同进程中的套接字没有区别。调用
recvfrom()
其中任何一个都会返回任何传入的 ICMP 数据包。您可以选择
connect()
在 ICMP 套接字上调用 来指定远程地址。在这种情况下,您可以使用调用send()
而不是sendto()
,它将仅发送到该地址。并且您可以调用recv()
,它将仅返回来自该远程地址的数据包。这将使其中一些套接字不等同于未连接的套接字或连接到不同地址的套接字。但是,如果您正在 ping 同一个地址,您仍然可以使用两个连接到该地址的套接字,一个用于发送,另一个用于接收。但在两个方向上使用单独的套接字没有任何好处。套接字本质上是线程安全的。