非阻塞连接到环回地址(127.0.0.1或localhost)

时间:2011-06-07 15:44:14

标签: ios macos freebsd ios-simulator

当我从iOS模拟器(它可能使用与Mac和FreeBSD相同的TCP堆栈)进行非阻塞连接到环回地址时,我发现连接总是成功,即使服务器进程没有运行。

我通过使用select()和零超时来检测连接是否成功。因此,只要select()返回0,我假设连接正在进行中,如果它返回-1我失败并出现错误,如果它返回1,则套接字已准备好读取(因为服务器必须已响应) ,我在报告连接成功后开始阅读。

这适用于除环回之外的所有地址。在环回上,select()总是返回1,即使没有服务器正在运行。所以,我开始阅读,失败了,我处理它。但我应该通过select()!

检测到这一点

2 个答案:

答案 0 :(得分:3)

您正在<{1}}上收到之前的错误。 在继续connect()之前,请检查select()errno而不是其他内容。在* BSD中,与EINPROGRESS上的非监听端口的连接错误输出(或可能错误输出)。

我刚刚运行了一个非常简单的测试(跳过标题):

localhost

没有收听端口int main(void) { int fd; int r; struct sockaddr_in remote; struct hostent *he; he = gethostbyname("localhost"); if (he == NULL) return -1; memcpy(&remote.sin_addr, he->h_addr, sizeof(remote.sin_addr)); remote.sin_port = htons(9671); remote.sin_family = AF_INET; fd = socket(PF_INET, SOCK_STREAM, 0); fcntl(fd, F_SETFL, O_NONBLOCK); r = connect(fd, (struct sockaddr *)&remote, sizeof remote); if (r < 0) { perror("connect"); } return 0; } ,我得到了:

    Linux上的
  • 9671
  • 在FreeBSD上:connect: Operation now in progress

当然,检查所有系统调用的错误代码始终是一个好主意(上面的例子为了简单起见并不这样做 - 毕竟这只是一个例子)。

答案 1 :(得分:0)

问题是我依靠select()告诉我连接是否成功。选择仅告诉您该fd上是否有更改。我应该在套接字上再次调用connect()并验证它是否失败,errno是EINPROGRESS,ECONN还是EALREADY。除了ECONN之外,所有其他值都意味着我们应该重试; ECONN意味着它已经连接。任何其他errno值意味着我们无法连接。