0

\n 文字に到達するまで各文字を読み、それらをすべて結合して返すことになっていますか、それとももっと良い方法がありますか? これには std::string または char を使用する必要がありますか?

次の2つの例を試しましたが、それらを別々の行として読む必要があります

例 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 のラインベースの操作を使用します。

多くの一般的に使用されるインターネット プロトコルは行ベースです。つまり、文字シーケンス "\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 に答える