0

我应该阅读每个字符直到它到达 \n 字符,将它们全部连接在一起并返回还是有更好的方法?我应该为此使用 std::string 还是 char ?

我尝试了以下两个示例,但我需要将它们作为单独的行阅读

示例 1:

std::string sockread()
{
    std::string s;
    s.resize(DEFAULT_BUFLEN);
    int result = recv(m_socket, &s[0], DEFAULT_BUFLEN, 0);

    if (result > 0) {
        return s;
    } else if (result == 0) {
        connected = false;
    } else {
        std::cout << "recv failed with error " << WSAGetLastError() << "\n";
    }
    throw std::runtime_error("Socket connection failed!");
}

示例 2:

char sockread(void)

  {
    int result;
    char buffer[DEFAULT_BUFLEN];
        result = recv(m_socket, buffer, DEFAULT_BUFLEN, 0);

        if (result > 0) {
             return *buffer;
              }
          else if (result == 0)
              {
             connected = false;
                 return *buffer;
              }
          else {
         printf("recv failed with error: %d\n", WSAGetLastError());
         return *buffer;
        }

   }
4

2 回答 2

0

使用此处介绍的 Boost.ASIO 基于行的操作。

许多常用的 Internet 协议都是基于行的,这意味着它们具有由字符序列“\r\n”分隔的协议元素。示例包括 HTTP、SMTP 和 FTP。为了更容易地实现基于行的协议以及其他使用分隔符的协议,Boost.Asio 包含函数 read_until() 和 async_read_until()。

于 2010-11-29T21:21:23.270 回答
0

您有几个选项,具体取决于您的套接字代码的其余部分是如何布局的。

从编码的角度来看,最简单的方法是一次读取 1 个字符,直到遇到您要查找的字符。从性能角度来看,这不是最好的方法,尽管您可以使用本地缓冲区来帮助您至少避免内存碎片,例如:

std::string sockread(void) 
{ 
    char buffer[DEFAULT_BUFLEN]; 
    int buflen = 0;
    char c;
    std::string s;

    do
    {
        int result = recv(m_socket, &c, 1, 0); 
        if (result > 0)
        { 
            if (c == '\n')
                break;

            if (buflen == DEFAULT_BUFLEN)
            {
                s += std::string(buffer, buflen);
                buflen = 0;
            }

            buffer[buflen] = c;
            ++buflen;

            continue;
        } 

        if (result == SOCKET_ERROR) 
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
                continue;

            std::cout << "recv failed with error " << WSAGetLastError() << "\n";
        }
        else
            connected = false; 

        throw std::runtime_error("Socket connection failed!");
    }
    while (true);

    if (buflen > 0)
        s += std::string(buffer, buflen);

    return s;
}

另一方面,将原始套接字数据读取到一个中间缓冲区中,其余的读取函数在需要时访问该缓冲区可以更有效地读取套接字,因此数据可以更快地从套接字缓冲区中取出(另一方面减少阻塞侧),例如:

std::vector<unsigned char> buffer;

std::string sockread(void) 
{ 
    unsigned char buf[DEFAULT_BUFLEN];
    int result;
    std:vector<unsigned char>::iterator it;

    do
    {
        it = std::find(buffer.begin(), buffer.end(), '\n');
        if (it != buffer.end())
            break;

        result = recv(m_socket, buf, DEFAULT_BUFLEN, 0); 
        if (result > 0)
        { 
            std::vector<unsigned char>::size_type pos = buffer.size();
            buffer.resize(pos + result);
            memcpy(&buffer[pos], buf, result);
            continue;
        } 

        if (result == SOCKET_ERROR) 
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
                continue;

            std::cout << "recv failed with error " << WSAGetLastError() << "\n";
        }
        else
            connected = false; 

        throw std::runtime_error("Socket connection failed!");
    }
    while (true);

    std::string s((char*)&buffer[0], std::distance(buffer.begin(), it));
    buffer.erase(buffer.begin(), it);
    return s;
}
于 2010-11-29T20:19:44.337 回答