我正在用c ++编写TCP通信脚本,以便在我的计算机和Aldebaran Nao机器人之间进行通信。
一般来说,我的脚本正在运行。但是,我遇到的麻烦是,当我从客户端调用connect时(当服务器应用程序关闭或以太网连接被删除时),我得到一个错误,表明操作正在进行中。
但是,一旦重新启动服务器应用程序/重新连接以太网电缆,我仍然无法调用connect来成功重新建立连接。我仍然收到操作正在进行的错误。
注意,每当我的客户端确定无法建立连接时,套接字描述符将在重新尝试连接之前关闭。这是我在客户端连接的代码:
如果有更多有用的信息,我很乐意提供。这个项目比较大,所以我不想在这里包含太多不相关的信息。
TCPStream* TCPConnector::connect(const char* serverIP, int port, int timeoutSec)
{
if (timeoutSec == 0)
{
return connect(serverIP, port);
}
struct sockaddr_in address;
// Store all zeros for address struct.
memset(&address, 0, sizeof(address));
// Configure address struct.
address.sin_family = AF_INET;
address.sin_port = htons(port); // Convert from host to TCP network byte order.
inet_pton(PF_INET, serverIP, &(address.sin_addr)); // Convert IP address to network byte order.
// Create a socket. The socket signature is as follows: socket(int domain, int type, int protocol)
int sd = socket(AF_INET, SOCK_STREAM, 0);
int optval = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1)
{
std::cout << "failed to set socket option" << std::endl;
}
// Set socket to be non-blocking.
int arg;
arg = fcntl(sd, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(sd, F_SETFL, arg);
// Connect with time limit.
fd_set set;
FD_ZERO(&set); // Clear the set.
FD_SET(sd, &set); // Add our file descriptor to the set.
struct timeval timeout;
timeout.tv_sec = timeoutSec;
timeout.tv_usec = 0;
// If the connect call returns 0, then the connection was established. Otherwise,
// check if the three-way handshake is underway.
if (::connect(sd, (struct sockaddr *)&address, sizeof(address)) < 0)
{
// If the handshake is underway.
if (errno == EINPROGRESS)
{
std::cout << "handshake in progress" << std::endl;
// Designate timeout period.
int ret = select(sd + 1, NULL, &set, NULL, &timeout);
std::cout << "return value from select : " << ret << std::endl;
// Check if timeout or an error occurred.
if (ret <= 0)
{
return NULL;
}
else
{
// Check if select returned 1 due to an error.
int valopt;
socklen_t len = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len);
if (valopt)
{
char * errorMessage = strerror( errno); // get string message from errn
std::string msg (errorMessage);
std::cout << msg << std::endl;
return NULL;
}
}
}
else
{
return NULL;
}
}
// Return socket to blocking mode
arg = fcntl(sd, F_GETFL, NULL);
arg &= (~O_NONBLOCK);
fcntl(sd, F_SETFL, arg);
// Create stream object.
return new TCPStream(sd, &address);
}
答案 0 :(得分:1)
您的套接字是非阻止模式(您明确地执行此操作)。
因此,您的连接将立即返回“连接正在进行中”。当套接字是非阻塞的时,你需要在这个套接字上使用poll
并等待它变得可读和/或可写 - 这意味着连接已经完成(成功与否)。
我认为更好的选择是使用阻塞套接字 - 我认为你没有理由在这里使用非阻塞调用。