即使客户端未先向我发送消息,我仍在尝试向连接的客户端发送数据。
这是我当前的代码:
while (true) {
// open a new socket to transmit data per connection
int sock;
if ((sock = accept(listen_sock, (sockaddr *) &client_address, &client_address_len)) < 0) {
logger.log(TYPE::ERROR, "server::could not open a socket to accept data");
exit(0);
}
int n = 0, total_received_bytes = 0, max_len = 4096;
std::vector<char> buffer(max_len);
logger.log(TYPE::SUCCESS,
"server::client connected with ip address: " + std::string(inet_ntoa(client_address.sin_addr)));
// keep running as long as the client keeps the connection open
while (true) {
n = recv(sock, &buffer[0], buffer.size(), 0);
if (n > 0) {
total_received_bytes += n;
std::string str(buffer.begin(), buffer.end());
KV key_value = kv_from(vector_from(str));
messaging.set_command(key_value);
}
std::string message = "hmc::" + messaging.get_value("hmc") + "---" + "sonar::" + messaging.get_value("sonar") + "\n";
send(sock, message.c_str(), message.length(), 0);
}
logger.log(TYPE::INFO, "server::connection closed");
close(sock);
}
我认为通过将n = recv(sock, &buffer[0], buffer.size(), 0);
移到while
条件之外,它将无限期地发送数据,但这不是事实。
谢谢。
在MSG_DONTWAIT
函数中添加recv
启用了我正在寻找的非阻塞操作。
答案 0 :(得分:1)
首先,我将解释为什么它不起作用,然后我将提出解决方案的建议。基本上,您可以在man7.org> Linux>手册页中找到答案,对于特定的here也可以找到答案。
当调用函数“ recv”时,它将不返回,直到数据可用并且可以读取为止。功能的这种行为称为“阻塞”。意思是,当前执行线程被阻塞,直到读取数据为止。
所以,调用函数
n = recv(sock, &buffer[0], buffer.size(), 0);
像您一样,会造成麻烦。您还需要检查返回码。 0表示连接已关闭,-1表示错误,您必须检查errno以获取更多信息。
您可以在套接字的整个生命周期中使用函数fnctl和O_NONBLOCK标志将套接字修改为以非阻塞模式工作。您还可以将标志MSG_DONTWAIT用作第4个参数(标志),以按功能调用为基础解除对功能的阻塞。
在两种情况下,如果没有可用数据,函数将返回-1,并且您需要检查errno的EAGAIN或EWOULDBLOCK。
返回值0表示连接已关闭。
但是从体系结构的角度来看,我不建议使用这种方法。您可以使用多个线程来接收和发送数据,或者使用Linux,可以使用select,poll或类似功能之一。甚至有一个通用的设计模式。它称为“反应器”,也有可用的相关模式,例如“接收器/连接器”和“反应器” /“ ACT”。如果您打算编写一个更强大的应用程序,则可以考虑使用。
您将找到Acceptor,Connector,Reactor,Proactor,ACT here
的实现。希望这会有所帮助