http://blog.youkuaiyun.com/stpeace/article/details/73718836
select
//连接代理服务器
connect(socket, (sockaddr*)&servAddr, sizeof(sockaddr));
FD_ZERO(&r);
FD_SET(socket, &r);
timeout.tv_sec = 5;
timeout.tv_usec =0;
ret = select(0, 0, &r, 0, &timeout);
如果进程句柄超过1024,select很容易崩溃
后续:经验教训忘记了,今天碰到使用的一个库作为客户端,连接判断非阻塞时判断连接是否成功遇到了,超过1024会崩溃:
bool CheckConnect(const int nSocketfd)
{
fd_set rset;
FD_ZERO(&rset);
FD_SET(nSocketfd, &rset);
timeval tval;
tval.tv_sec = 5;
tval.tv_usec = 0;
if (select(nSocketfd + 1, NULL, &rset, NULL, &tval) <= 0)
{
return false;
}
if (FD_ISSET(nSocketfd, &rset))
{
int error = -1;
socklen_t len = sizeof(int);
if (getsockopt(nSocketfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
{
LOG_ERROR("errno: " << errno << " " << strerror(errno));
return false;
}
if (error)
{
errno = error;
LOG_ERROR("errno: " << errno << " " << strerror(errno));
return false;
}
}
需要将select改成poll或epoll
下面是rabittmq里面的做法:
if (0 == connect(sockfd, addr->ai_addr, addr->ai_addrlen)) {
return sockfd;
}
if (EINPROGRESS != errno) {
last_error = AMQP_STATUS_SOCKET_ERROR;
goto err;
}
last_error = amqp_poll(sockfd, AMQP_SF_POLLOUT, deadline);
if (AMQP_STATUS_OK != last_error) {
goto err;
}
{
int result;
socklen_t result_len = sizeof(result);
if (-1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &result, &result_len) ||
result != 0) {
last_error = AMQP_STATUS_SOCKET_ERROR;
goto err;
}
}
int amqp_poll(int fd, int event, amqp_time_t deadline) {
#ifdef HAVE_POLL
struct pollfd pfd;
int res;
int timeout_ms;
/* Function should only ever be called with one of these two */
assert(event == AMQP_SF_POLLIN || event == AMQP_SF_POLLOUT);
start_poll:
pfd.fd = fd;
switch (event) {
case AMQP_SF_POLLIN:
pfd.events = POLLIN;
break;
case AMQP_SF_POLLOUT:
pfd.events = POLLOUT;
break;
}
timeout_ms = amqp_time_ms_until(deadline);
if (-1 > timeout_ms) {
return timeout_ms;
}
res = poll(&pfd, 1, timeout_ms);
if (0 < res) {
/* TODO: optimize this a bit by returning the AMQP_STATUS_SOCKET_ERROR or
* equivalent when pdf.revent is POLLHUP or POLLERR, so an extra syscall
* doesn't need to be made. */
return AMQP_STATUS_OK;
} else if (0 == res) {
return AMQP_STATUS_TIMEOUT;
} else {
switch (amqp_os_socket_error()) {
case EINTR:
goto start_poll;
default:
return AMQP_STATUS_SOCKET_ERROR;
}
}
return AMQP_STATUS_OK;
}