【问题标题】:UNIX domain socket C++ server can not return data to clientUNIX域套接字C ++服务器无法向客户端返回数据
【发布时间】:2016-04-08 14:14:42
【问题描述】:

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

我的旧代码的问题是我使用read 而不是read_someread 将阻塞管道,直到它读取一定数量的字节或出现损坏的管道异常,而 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 可以毫无问题地使用此服务器?谢谢!

【问题讨论】:

  • 使用static 限定符来表示epStr
  • @self,和这个问题有什么关系?
  • 我想你在找read_some
  • @DavidSchwartz 谢谢,read_some 和 @llya 的回答我已经解决了这个问题。
  • 不要对未引用的文本使用引号格式。

标签: c++ sockets unix boost-asio socat


【解决方案1】:

我也想知道为什么socat可以在没有任何服务器的情况下使用 有问题吗?

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

如果是这样,有没有办法让它知道它应该读取多少数据 在每个开始时不发送数据块的大小 留言?

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

【讨论】:

  • 你是对的,我没有关闭客户端中的套接字。感谢您指出了这一点。但是这并不能解决这个问题......消息结束是一个很好的解决方案,但我不知道这是否可以解决这个问题......
  • 如果服务器等待固定数量的字节(2048)而客户端写入较少,则双向通信将不起作用。客户端必须至少发送服务器期望的字节数。
  • @llya 感谢您的提示。我使用read_some 更改了我的代码,并通过检查最后一个字符是否为\0 来检测是否到达输入的末尾。
猜你喜欢
  • 2018-01-20
  • 2015-07-02
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 2016-02-23
相关资源
最近更新 更多