繁体   English   中英

UNIX域套接字C ++服务器无法将数据返回给客户端

[英]UNIX domain socket C++ server can not return data to client

这是我正在使用的简单回显服务器,该服务器将接受来自客户端的请求并返回客户端发送给它的内容。 该程序可以在socat ,但是在使用我自己的客户端时将冻结。

我的旧代码存在的问题是我使用read而不是read_some read将阻塞管道,直到它读取一定数量的字节或出现管道异常中断read_some ,而read_some将一次读取一个块。 更新后的版本使用read_some读取输入流,并检查程序读取的最后一个字符是否为\\0 ,如果为\\0 ,则意味着它到达命令的末尾,因此它将回显。 之所以可行,是因为我只传递字符串文字,并且管道中没有二进制数据。

服务器的代码是

using namespace std;

const char* epStr = "/tmp/socketDemo";

int main() {
  namespace local = boost::asio::local;

  boost::asio::io_service io_service;

  ::unlink(epStr);

  local::stream_protocol::endpoint ep(epStr);
  local::stream_protocol::acceptor acceptor(io_service, ep);

  while(1) {
    local::stream_protocol::socket *socket = new local::stream_protocol::socket(io_service);
    acceptor.accept(*socket);

    char buf[2048] = {0};
    boost::system::error_code error;

    size_t len = 0;
      while(1) {
        len += socket->read_some(boost::asio::buffer(buf + len, 2048 - len));
        cout << "read " << len << endl;
        if (buf[len] == '\0') {
          break;
        }
      }

    cout << "read " << len << " bytes" << endl;
    cout << buf << endl;

    boost::asio::write(*socket, boost::asio::buffer(buf, len), boost::asio::transfer_all());
  }
}

例如,使用socat命令测试服务器时

echo "12345" | socat - UNIX-CONNECT:/tmp/socketDemo

它将返回所需的结果。

我的客户代码是

const char* epStr = "/tmp/socketDemo";

int main(int argc, const char* argv[]) {
  boost::asio::io_service io_service;
  boost::asio::local::stream_protocol::endpoint ep(epStr);
  boost::asio::local::stream_protocol::socket socket(io_service);

  socket.connect(ep);

  boost::asio::write(socket, boost::asio::buffer(argv[1], strlen(argv[1])), boost::asio::transfer_all());

  char buf[1024] = {0};

  size_t len = 0;
    while(1) {
      len += socket.read_some(boost::asio::buffer(buf + len, 2048 - len));
      std::cout << "read " << len << std::endl;
      if (buf[len] == '\0') {
        break;
      }
    }

  std::cout << "read " << len << " bytes\n";

  std::cout << buf << std::endl;

  socket.close();

当执行客户端时,起初两者都没有输出,在我杀死了客户端之后,服务器将输出它读取n个字节并得到一个坏管道异常的信息。

这可能是由服务器中的read功能引起的吗? 如果是这样,是否有一种方法可以让它知道应该读取多少数据,而不必在每个消息的开头发送数据块的大小? 我也想知道为什么socat可以在此服务器上正常工作? 谢谢!

我也想知道为什么socat可以在此服务器上正常工作?

可能是因为socat关闭了套接字,而您的客户端却没有。

如果是这样,是否有一种方法可以让它知道应该读取多少数据,而不必在每个消息的开头发送数据块的大小?

例如,假设您正在定义/使用包含EOM的协议,则一次读取一个字节,直到读取消息结尾字符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM