UDP 是 IPC 的可靠协议吗?
Is UDP a reliable protocol for IPC?
如果我纯粹使用 UDP 进行进程间通信(即在 1 个系统中,不涉及网络),我可以认为它是可靠的吗?还是我还需要担心丢包等问题?
注意这是一个实践问题,而不是理论问题。如果不同操作系统的答案不同,请解释如何,特别是 Windows、Linux 和 Mac.
编辑:不,它不可靠 -- 以下示例。
感谢当前的回答为我指明了正确的方向。
此代码在 Windows 8.1 上丢弃了一个数据包(我得到 Received: 18432 (DROPPED PACKET)
)。
(我不确定为什么它在 Linux 上没有 运行,但它应该接近工作。)
#include <stdio.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#endif
int main()
{
#ifdef _WIN32
typedef int socklen_t;
#else
typedef int SOCKET;
#endif
SOCKET r = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in addr = { AF_INET };
addr.sin_addr.s_addr = htonl(0x7F000001);
{
socklen_t addrlen = sizeof(addr);
if (bind(r, (struct sockaddr *)(&addr), addrlen) == -1 ||
getsockname(r, (struct sockaddr *)(&addr), &addrlen) == -1)
{
return 1;
}
}
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
int tids = 0;
for (long c = 0, i = 0, j = 0; c < 1000000; ++c)
{
if ((c + 1) % 10)
{
int n = sendto(s, (char const *)(&i), sizeof(i), 0, (struct sockaddr const *)(&addr), sizeof(addr));
if (n != sizeof(i)) { return 1; }
// else { fprintf(stderr, "Sent: %lu\n", i); }
++i;
}
else
{
struct sockaddr temp;
socklen_t templen = sizeof(temp);
long v;
int n = recvfrom(r, (char *)(&v), sizeof(v), 0, (struct sockaddr *)(&temp), &templen);
if (n != sizeof(v)) { return 2; }
else if (v != j) { fprintf(stderr, "Received: %lu (DROPPED PACKET)\n", v); return 3; }
// else { fprintf(stderr, "Received: %lu\n", v); }
++j;
}
}
}
If I use UDP purely for inter-process communication (i.e., in 1
system, with no network involved), can I consider it to be reliable?
没有。即使所有通信都在同一主机上完成,UDP 数据包仍可能(有时会)被丢弃。
如果你愿意,你可以自己演示一下;在同一台主机上设置两个使用 UDP 套接字的程序,程序 A 将 UDP 数据包发送给程序 B,程序 B 接收并记录它们。 (在 UDP 数据包中包含序列号,以便程序 B 可以轻松判断何时未收到数据包)。
一旦它工作并且数据包以合适的速率传输,将一些代码放入程序 B 以便它每隔一段时间调用 sleep(5) (或类似的,以便程序 B 无法调用 recv()在其 UDP 套接字上停留很长时间)。您可能会看到在 sleep() 调用 returns 之后,程序 B 报告跳过了一些数据包——因为当 B 处于睡眠状态时,其 UDP 套接字的传入数据包缓冲区已满,然后一些数据包被跳过被网络堆栈丢弃,因为没有地方放置它们。
如果我纯粹使用 UDP 进行进程间通信(即在 1 个系统中,不涉及网络),我可以认为它是可靠的吗?还是我还需要担心丢包等问题?
注意这是一个实践问题,而不是理论问题。如果不同操作系统的答案不同,请解释如何,特别是 Windows、Linux 和 Mac.
编辑:不,它不可靠 -- 以下示例。
感谢当前的回答为我指明了正确的方向。
此代码在 Windows 8.1 上丢弃了一个数据包(我得到 Received: 18432 (DROPPED PACKET)
)。
(我不确定为什么它在 Linux 上没有 运行,但它应该接近工作。)
#include <stdio.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#endif
int main()
{
#ifdef _WIN32
typedef int socklen_t;
#else
typedef int SOCKET;
#endif
SOCKET r = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in addr = { AF_INET };
addr.sin_addr.s_addr = htonl(0x7F000001);
{
socklen_t addrlen = sizeof(addr);
if (bind(r, (struct sockaddr *)(&addr), addrlen) == -1 ||
getsockname(r, (struct sockaddr *)(&addr), &addrlen) == -1)
{
return 1;
}
}
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
int tids = 0;
for (long c = 0, i = 0, j = 0; c < 1000000; ++c)
{
if ((c + 1) % 10)
{
int n = sendto(s, (char const *)(&i), sizeof(i), 0, (struct sockaddr const *)(&addr), sizeof(addr));
if (n != sizeof(i)) { return 1; }
// else { fprintf(stderr, "Sent: %lu\n", i); }
++i;
}
else
{
struct sockaddr temp;
socklen_t templen = sizeof(temp);
long v;
int n = recvfrom(r, (char *)(&v), sizeof(v), 0, (struct sockaddr *)(&temp), &templen);
if (n != sizeof(v)) { return 2; }
else if (v != j) { fprintf(stderr, "Received: %lu (DROPPED PACKET)\n", v); return 3; }
// else { fprintf(stderr, "Received: %lu\n", v); }
++j;
}
}
}
If I use UDP purely for inter-process communication (i.e., in 1 system, with no network involved), can I consider it to be reliable?
没有。即使所有通信都在同一主机上完成,UDP 数据包仍可能(有时会)被丢弃。
如果你愿意,你可以自己演示一下;在同一台主机上设置两个使用 UDP 套接字的程序,程序 A 将 UDP 数据包发送给程序 B,程序 B 接收并记录它们。 (在 UDP 数据包中包含序列号,以便程序 B 可以轻松判断何时未收到数据包)。
一旦它工作并且数据包以合适的速率传输,将一些代码放入程序 B 以便它每隔一段时间调用 sleep(5) (或类似的,以便程序 B 无法调用 recv()在其 UDP 套接字上停留很长时间)。您可能会看到在 sleep() 调用 returns 之后,程序 B 报告跳过了一些数据包——因为当 B 处于睡眠状态时,其 UDP 套接字的传入数据包缓冲区已满,然后一些数据包被跳过被网络堆栈丢弃,因为没有地方放置它们。