当没有互联网连接时,socket()和sendto()不返回错误代码
为什么socket()
没有返回INVALID_SOCKET
?我认为它会失败,然后我可以退出我的功能。我的函数的错误检查一直持续到recvfrom()
,然后在没有互联网连接时挂起。我以为socket()
或sendto()
会返回一个错误代码,当我没有互联网连接,但他们不是。我试图依靠他们的失败作为一个标志,用户没有互联网连接并退出我的功能,但这只是不工作的一些奇怪的原因。当没有互联网连接时,socket()和sendto()不返回错误代码
void myFunc()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("myipaddress");
server_addr.sin_port = htons(123);
// Doesn't fail when there's no internet connection
protoent *proto = getprotobyname("udp");
int s = socket(PF_INET, SOCK_DGRAM, proto->p_proto);
if (s == INVALID_SOCKET) {
goto Cleanup;
}
// Doesn't fail when there's no internet connection
char msg[48] = { 0x08, 0, 0, 0, 0, 0, 0, 0, 0 };
int iResult = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (iResult == SOCKET_ERROR) {
goto Cleanup;
}
// Hangs when there's no internet connection
memset(msg, 0, sizeof(msg));
struct sockaddr saddr;
socklen_t saddr_l = sizeof(saddr);
iResult = recvfrom(s, msg, 48, 0, &saddr, &saddr_l);
if (iResult == SOCKET_ERROR) {
goto Cleanup;
}
Cleanup:
closesocket(s);
WSACleanup();
}
因为没有要求将套接字连接到互联网。许多应用程序在一台机器上使用套接字进行进程间通信。没有互联网连接时,这些应用程序仍可以正常运行。
sendto()
可以说可以返回一个错误代码;它可以(在某些情况下,如桌面上有关网络连接状态的通知所示)知道该数据包永远不会被传送。然而,UDP通信和sendto()
不保证交付任何,显然你正在使用的实现不考虑缺乏连接值得错误代码。可以说这是一个实施质量问题。
recvfrom()
只要您为消息指定(可能无限期地),但从未接收到消息就等待。再次,这是在规范范围内,无论这种特定情况是否被标记,它都可以被认为是实施质量问题。
上使用定时等待机制(select,epoll,...)“它应该知道”究竟如何?你能提出一个机制吗? –
这不是很明显吗?一旦你指定了一个地址,就清楚它是否是本地机器上的地址。如果没有网络连接(可检测到的情况;至少我的机器会立即告诉我是否拉网线),则无法传送。 –
(1)网络电缆!=互联网连接(2)没有网络电缆!=无法送达的数据包(我的头顶上,你可以运行一个虚拟机,只有VM的定制内核模块知道哪些数据包可交付给它)。 –
我看着Linux手册页的sendto(假设所有相关的实现是充分类似于Berkeley套接字基线)位置:
http://linux.die.net/man/2/sendto
的文件没有提到如果报告和错误网络堆栈'知道'该消息无法传递。这是合理的,因为套接字的传输可能不是IP4或IP6。它可以是我们选择编写驱动程序的任何传输方式:数据包收音机,串行电缆或运载鸽子(如果我们能够计算将打印的信息加载到其书包中的硬件)。
唯一参照从传输可能的错误是在这里:
这些是由套接字层产生的一些标准误差。可能会生成其他错误并从底层协议模块返回; 参见他们各自的手册页。
正如其他人所说的,UDP是一种不可靠的数据报协议。预计不可靠。预计未送达消息。因此不是真的是一个错误。协议层作者编写代码来处理传输错误的动机不大 - 因为它们也是可以预期的,而不是在此协议的上下文中出现错误。
当通过TCP打开套接字时,套接字连续性缺失是一个错误。如果传输报告数据包传输不可能(足够长时间),那么这是协议中的错误条件。
风格问题 - 您可以通过使用RAII技术来清除那些'goto Cleanup;'调用,其中清理将在函数返回时自动发生。 – PaulMcKenzie
@PaulMcKenzie是的,但假设'myFunc()'的用户会一直足够体贴/记住在使用该函数后进行清理。 – Merl
你会如何定义“没有互联网连接”?请注意,您使用的数据报套接字定义不可靠。 –