1

你如何循环读取 C++ 套接字。

stringstream ss;
while (1) {
    char buf [2];
    ssize_t e = read(fd, buf, 2);

    ss << buf[0];
    ss << buf[1];



    cout << e << endl;
    cout << buf[0] << endl;
    cout << buf[1] << endl;

    if (e <= 0) {
        break;
    }
}
string msg = "";
ss >> msg;

当我 telnet 并输入 hello 然后输入以进行测试时,我得到了

2
h
e
2
l
l
2
o

1

它只是在那里等待,没有循环。发生了什么,我如何读取套接字?

如何使用 EOF 来表示

  1. 远程登录

  2. buf 在 write(fd, buf, bufSize) 的上下文中;

4

3 回答 3

1

如何使用 EOF 来表示

1) 远程登录

2) 写上下文中的buf(fd, buf, bufSize);

首先,您要发出信号的不是 EOF。它是“消息结束”或“您刚刚收到的数据是一个完整的协议数据单元,您现在应该处理它”。答案是,无论你想要什么,只要双方同意。

例如,您可以~专门保留字符以标记消息的结尾。为了指示消息的结束,一方发送一个~. 对方知道,当它收到一个 时~,之前的所有内容都是一条消息,之后的所有内容都是一条新消息。

您还可以在发送实际消息之前发送消息的长度。您可以在文本中执行此操作,后跟零字节或换行符。或者,您可以将每条消息设为一行。

您可以这样做,但是在您的特定应用程序中最有意义,但您实际上必须这样做。

TCP 会在两种情况下为您做到这一点:

1)当一方完成发送并且知道另一方无论如何都不会再发送数据时,它可以close在套接字上使用。对方将读取已发送的其余数据,然后read返回0

2)当一方不再发送任何数据但另一方可能发送更多数据时,它可以shutdown连接它的一方。但它永远无法发送更多数据。另一方将知道此关闭,并且如果专门为此进行编码,则可以继续发送数据,直到关闭它的一半。然后对方read将返回零。(请注意,如果您对一个并非设计用于接收它的程序执行此操作,它可能会感到困惑并且没有意识到它仍然可以向您发送数据。)

否则,一切都取决于你。

于 2012-05-10T09:11:45.413 回答
1

你是什​​么意思没有循环?再打一些,按回车,你会看到更多的输出..

如果你完成了,你必须按 Ctrl+D 来表示输入结束 (EOF)。

于 2012-05-10T08:38:49.567 回答
0

TCP 数据包是流,而不是文件。如何读取流由您决定。

通常,如果您在一端写入 20 个字节,则在一次读取中您将在另一端获得 20 个字节,除非使用一些常见的 tcp/ip 选项。

有以下假设。一些假设是:

假设所有的脚手架代码都在那里。

假设我犯了错误并自己调试。

假设处理了所有字节顺序问题。

假设您足够聪明,不会将浮点类型作为二进制发送。

  • 一些程序员选择使用以长度为前缀的数据包并读取长度字节(2),然后读取该长度表示的尽可能多的字节,就像这样。

     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
    
     read( fd, sizeof( length ), &length );
     // Handle failure from read
     while( bytesRead < length )
     {
         int readRv = read( fd, &buffer[bytesRead], length - bytesRead );
         if( readRv <= 0 )  // 0 usually means socket was closed. -1 is an erro
         {
             // Handle socket error/closed socket
         }
         else if( readRv < length )
         {
             bytesRead += readRv;
         }
         else if( readRv == length )
         {
             bytesRead = readRv;
             break;
         }
     }
    
  • 一些程序员阅读可用的内容并寻找数据包结束标记

     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
     int readRv = read( fd, buffer, sizeof( buffer ) );
     int eopFound = 0;
    
    
     if( (eopFound = findEndOfPacketMarker( buffer )) > 0 )
     {
         // Less than 0 = error.
     }
     else if( eopFound == 0 )
     {
         // No end of packet, must read more bytes here
     }
     else
     {
         // Found an end of packet marker
     }
    
     // Here you deal with bytes that are "over read"
     // Either the
     // 1) packet was bigger than buffer,
     // 2) there were bytes left over after the EOP marker
     // 3) Martians crapped in your code and screwed it all up. :)
    
  • 一些程序员使用一组固定大小的数据包和一个数据包类型 id

    int packetType;
    
     unsigned char buffer[MAX_CHAR] = "";
     unsigned char length = 0;
     int bytesRead = 0;
    
     read( fd, sizeof( packetType ), &packetType );
     read( fd, getLengthFromPacketType( packetType ), buffer );
    

这应该涵盖大多数事情......如果您有更多问题,请在评论中与@JimR thingy 一起提问,以便它显示为我阅读的消息。

于 2012-05-10T10:13:56.073 回答