【发布时间】:2011-08-17 07:16:27
【问题描述】:
我的问题如下: 我正在 Linux 中编写接口以通过以太网控制 GPIB 控制器。为此,我打开一个 TCP 套接字并将命令发送到控制器。到目前为止,这工作正常。我在为我的接口编写某种单元测试时遇到的问题: 要检查我是否在单独的线程中使用来自 boost lib 的 tcp 接受器,只需连接到它而不是实际的控制器。这也有效,但前提是来自接口的 connect() 调用被阻塞。但是,由于我需要为 connect() 调用指定超时时间,所以我必须使用 select() 函数进行连接:
// Open TCP Socket
m_Socket = socket(PF_INET,SOCK_STREAM,0);
if( m_Socket < 0 )
{
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
struct sockaddr_in addr;
inet_aton(m_Host.c_str(), &addr.sin_addr);
addr.sin_port = htons(m_Port);
addr.sin_family = PF_INET;
// Set timeout values for socket
struct timeval timeouts;
timeouts.tv_sec = SOCKET_TIMEOUT_SEC ; // const -> 5
timeouts.tv_usec = SOCKET_TIMEOUT_USEC ; // const -> 0
uint8_t optlen = sizeof(timeouts);
if( setsockopt( m_Socket, SOL_SOCKET, SO_RCVTIMEO,&timeouts,(socklen_t)optlen) < 0 )
{
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
// Set the Socket to TCP Nodelay ( Send immediatly after a send / write command )
int flag_TCP_nodelay = 1;
if ( (setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY,
(char *)&flag_TCP_nodelay, sizeof(flag_TCP_nodelay))) < 0)
{
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
// Save Socket Flags
int opts_blocking = fcntl(m_Socket, F_GETFL);
if ( opts_blocking < 0 )
{
return ERR_NET_SOCKET;
}
int opts_noblocking = (opts_blocking | O_NONBLOCK);
// Set Socket to Non-Blocking
if (fcntl(m_Socket, F_SETFL, opts_noblocking)<0)
{
return ERR_NET_SOCKET;
}
// Connect
if ( connect(m_Socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
// EINPROGRESS always appears on Non Blocking connect
if ( errno != EINPROGRESS )
{
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
// Create a set of sockets for select
fd_set socks;
FD_ZERO(&socks);
FD_SET(m_Socket,&socks);
// Wait for connection or timeout
int fdcnt = select(m_Socket+1,NULL,&socks,NULL,&timeouts);
if ( fdcnt < 0 )
{
return ERR_NET_SOCKET;
}
else if ( fdcnt == 0 )
{
return ERR_TIMEOUT;
}
}
//Set Socket to Blocking again
if(fcntl(m_Socket,F_SETFL,opts_blocking)<0)
{
return ERR_NET_SOCKET;
}
m_connectionStatus = STATUS_OPEN;
return x2e::OK;
如果我使用此功能,我仍然可以连接到真实控制器并与之通信。但是,如果我使用我的测试服务器,我就是无法连接,选择只是离开,返回值为 0。 所以现在有人可能会说我的测试服务器无法正常工作......但是如果我使用阻塞的 connect() 调用,我可以毫无问题地发送到我的测试服务器...... 也许有人知道我能做什么......?
【问题讨论】:
-
返回值为零表示超时。这可能是也可能不是问题,但您似乎没有在发布的摘录中设置超时结构。引用手册页“在 Linux 上,select() 修改超时以反映未睡眠的时间量......在 select() 返回后考虑超时未定义。”如果您在不重置值的情况下再次调用它会导致问题。
-
对不起我的错,我忘了在我的代码中添加超时结构的定义!!!会解决这个问题......但这也意味着这不是问题://所以现在代码包含处理连接的整个函数
-
你知道你没有在任何地方关闭套接字吗?你没有重用它,用同一个套接字多次调用连接,是吗?
-
我刚刚发布的代码是全局“连接函数”的一部分,它实际上不应实现套接字的关闭。稍后将通过另一个函数调用关闭套接字,但在此之前我想做一些通信。
-
但请注意,如果任何套接字功能失败,您将无法可靠地再次使用它,您必须关闭它并创建一个新的。
标签: linux sockets select boost tcp