【问题标题】:Reading from and writing to socket读取和写入套接字
【发布时间】:2012-11-24 15:51:43
【问题描述】:

我制作了一个简单的 tcp 服务器/客户端应用程序,客户端向服务器写入一些内容,然后将其回显给客户端。但是,当我尝试读取服务器在客户端中回显的内容时遇到了一些问题。

string s;
while((n = read(socketFD[0],readBuf, BUFFER_SIZE)) > 0){
  cout<<"\nBytes read: "<<n<<endl;
  s.append(readBuf, n);
}
cout<<"\nTest after read\n";

我将 16 KB 的文本写入服务器。当我在客户端读取时,我一次读取 4 KB。

这段代码的输出是:

Bytes read: 4096

Bytes read: 4096

Bytes read: 4096

Bytes read: 4046

读取调用似乎在从套接字读取完成后阻塞并且永远不会离开循环。我该如何解决这个问题?

编辑:这是服务器中处理连接客户端的代码。

if((childpid = fork()) == 0){
  close(listenFD);
  while ((n = read(connectFD, buf, BUFFSIZE)) > 0){
    cout<<"\nBytes read: "<<n<<endl;
    write(connectFD, buf, n);
  }
  cout<<"\nTest after read\n";
  exit(0);
}

这个输出是:

Bytes read: 4096

Bytes read: 4096

Bytes read: 4096

Bytes read: 4046

Test after read

与客户端中的代码相比,这里有什么不同?为什么读取调用不像在客户端那样阻塞?

【问题讨论】:

  • readArr 是什么?当服务器关闭连接时,循环应该退出 -- read() 将返回 0 表示 EOF。
  • 打错字了,应该是readBuf
  • 那行不通,因为readBuf 不是 C++ 字符串或 C 字符串。 C 字符串需要以 null 结尾,而 read 不这样做,因为它可以用于非字符串的数据。

标签: c++ sockets


【解决方案1】:

读取调用似乎在从套接字读取完成后阻塞并且永远不会离开循环。我该如何解决这个问题?

简短回答,收到所有数据后不要拨打read

编写代码以检测您何时收到了当时想要接收的所有数据,如果是,则退出循环。你必须实际实现某种协议。

s+=readBuf;

这不可能。它怎么知道要向s添加多少字节的数据?

【讨论】:

  • 你能检查一下帖子中添加的代码吗?为什么我会得到不同的结果?
  • 查看n的值。如果为零,那是因为另一端关闭了连接。如果是-1,请检查errno 以了解返回read 的原因。
  • 所以read中的返回值0总是意味着连接的另一端已经关闭?
  • 读取为零表示双向连接的入站一半已正常关闭。如果你没有关闭它,那么对方一定有。 (例如,您可以使用shutdown 函数将其关闭。)
【解决方案2】:

如果您不想将读取循环放在另一个线程中,您将需要pollselect,这样您就可以查看队列中是否存在某些内容而无需实际读取。

【讨论】:

  • 在阻塞套接字上,read 调用将阻塞,直到至少读取一个字节或发生错误或连接关闭。如果需要,您可以使套接字成为非阻塞的。
【解决方案3】:

这是 Python 中套接字的精彩介绍的摘录。它是 Python,是的,但它公开了 C-Socket API,所以那里写的内容在您的上下文中也是正确的。你可以在这里阅读:http://docs.python.org/dev/howto/sockets.html

关于“使用套接字”的部分会准确地告诉您所观察到的问题。它讨论了recv 函数,但它转换为文件描述符上的read 函数。

但是,如果您打算重复使用您的套接字进行进一步的传输,您需要意识到套接字上没有 EOT。我再说一遍:如果一个套接字 send 或 recv 在处理 0 个字节后返回,则连接已断开。如果连接没有断开,你可能会永远等待一个 recv,因为套接字不会告诉你没有什么要读的了(现在)。现在,如果您稍微考虑一下,您就会意识到套接字的一个基本事实:消息必须是固定长度的(yuck),或者是定界的(耸肩),或者表明它们有多长(更好),或者以关闭连接结束。选择完全由您自己决定,(但有些方法比其他方法更正确)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2020-09-15
    • 2013-05-06
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多