У вас есть несколько вариантов, в зависимости от того, как выложен остальной код вашего сокета.
Самый простой подход, с точки зрения кодирования, состоит в том, чтобы просто читать 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;
}