Android中的Linux套接字连接失败
我想用NDK在Android中创建一个套接字,但有时在连接到服务器时会出现一些错误,我可以确保用户的手机网络可用。 一种情况是超时错误,另一种情况似乎是连接被拒绝,因为我得到了以下日志,我认为第二种错误是连接被拒绝,因为Android中的Linux套接字连接失败,android,linux,sockets,Android,Linux,Sockets,我想用NDK在Android中创建一个套接字,但有时在连接到服务器时会出现一些错误,我可以确保用户的手机网络可用。 一种情况是超时错误,另一种情况似乎是连接被拒绝,因为我得到了以下日志,我认为第二种错误是连接被拒绝,因为getsockopt的错误是111,即使strerror现在正在给我操作,但服务器地址是有效的: connect::socket error: Operation now in progress Or connect::error:111, Operation now in
getsockopt
的错误是111,即使strerror
现在正在给我操作,但服务器地址是有效的:
connect::socket error: Operation now in progress
Or
connect::error:111, Operation now in progress
以下是我的代码片段:
bool connect(int sockfd, struct sockaddr *address, socklen_t address_len, int timeout) {
int ret = 0;
struct timeval tv;
fd_set mask;
// set socket non block
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
// use select to check socket connection
ret = connect(sockfd, address, address_len);
if (-1 == ret) {
if (errno != EINPROGRESS) {
perror("connect");
inetConnectFailCode = errno;
LOG(TAG.c_str(), "connect::errno != EINPROGRESS: %s", strerror(errno));
return false;
}
LOG(TAG.c_str(), "connecting...\n");
FD_ZERO(&mask);
FD_SET(sockfd, &mask);
tv.tv_sec = timeout;
tv.tv_usec = 0;
if (select(sockfd + 1, NULL, &mask, NULL, &tv) > 0) {
int error = 0;
socklen_t tmpLen = sizeof(int);
int retopt = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &tmpLen);
if (retopt != -1) {
if (0 == error) {
LOG(TAG.c_str(), "has connect");
return true;
} else {
//I get error here
LOG(TAG.c_str(), "connect::error:%d, %s", error, strerror(errno));
return false;
}
} else {
LOG(TAG.c_str(), "connect::socket error:%d", error);
return false;
}
} else {
//timeout, and I get error here sometimes
LOG(TAG.c_str(), "connect::socket error: %s", strerror(errno));
return false;
}
}
LOG(TAG.c_str(), "has connect");
return true;
}
这个问题困扰了我很长时间,任何人都可以帮我一个忙,谢谢您的帮助。您显示了错误的错误消息。
如果getsockopt(SO_ERROR)
失败,即使它没有有效值,也会输出ERROR
。但是,更重要的是,如果getsockopt(SO_ERROR)
成功,但ERROR
不是0,则将errno
传递到strerror()
而不是传递ERROR
errno
仍然是从最初失败的connect()
调用开始的EINPROGRESS
,因此您的错误消息显示“操作正在进行”
。错误111是ECONNREFUSED
,这将是“连接被拒绝”
另外,如果select()
返回,则显示错误的错误消息。
如果getsockopt(SO_ERROR)
失败,即使它没有有效值,也会输出ERROR
。但是,更重要的是,如果getsockopt(SO_ERROR)
成功,但ERROR
不是0,则将errno
传递到strerror()
而不是传递ERROR
errno
仍然是从最初失败的connect()
调用开始的EINPROGRESS
,因此您的错误消息显示“操作正在进行”
。错误111是ECONNREFUSED
,这将是“连接被拒绝”
另外,如果
select()
返回感谢,但您发布的原因可能不会发生,因为要连接的服务器是IM服务器,它会连续工作,我们没有发现任何异常情况。此应用的其他网络请求(不是到IM服务器)是正常的,这会使它更加混乱。@wqycsu您收到一个ETIMEDOUT
(110)或econnrefered
(111)错误。在connect()
期间,无论您连接到的服务器类型如何,这些错误都有几种可能发生。1)您连接到错误的IP/端口,或者它没有侦听连接;2)服务器太忙,无法在此时接受连接;或者3)连接被防火墙/路由器阻止。谢谢,但您发布的原因可能不会发生,因为要连接的服务器是IM服务器,它会连续工作,我们没有发现任何例外情况。此应用的其他网络请求(不是到IM服务器)是正常的,这会使它更加混乱。@wqycsu您收到一个ETIMEDOUT
(110)或econnrefered
(111)错误。在connect()
期间,无论您连接到的服务器类型如何,这些错误都有几种可能发生。1)您连接到错误的IP/端口,或者它没有侦听连接;2)服务器太忙,无法在此时接受连接;或者3)连接被防火墙/路由器阻止。
bool connect(int sockfd, struct sockaddr *address, socklen_t address_len, int timeout) {
// set socket non block
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
// use select to check socket connection
int ret = connect(sockfd, address, address_len);
if (-1 == ret) {
int error = errno;
if (EINPROGRESS == error) {
LOG(TAG.c_str(), "connecting...\n");
fd_set mask;
struct timeval tv;
FD_ZERO(&mask);
FD_SET(sockfd, &mask);
tv.tv_sec = timeout;
tv.tv_usec = 0;
ret = select(sockfd + 1, NULL, &mask, NULL, &tv);
if (0 < ret) {
socklen_t tmpLen = sizeof(int);
ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &tmpLen);
if (-1 == ret) {
error = errno;
}
} else if (0 == ret) {
error = ETIMEDOUT;
} else {
error = errno;
}
}
if (0 != error) {
inetConnectFailCode = error;
LOG(TAG.c_str(), "connect::error:%d, %s", error, strerror(error));
return false;
}
}
LOG(TAG.c_str(), "has connect");
return true;
}