我是否应该阅读每个角色,直到它到达\ 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;
}
}
答案 0 :(得分: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;
}
答案 1 :(得分:0)
使用Boost.ASIO - 基于行的操作涵盖here。
许多常用的互联网协议 是基于行的,这意味着它们 有协议元素 由字符序列分隔 “\ r \ n”。示例包括HTTP,SMTP 和FTP。更容易许可 实现基于行的 协议,以及其他协议 使用分隔符,Boost.Asio 包括函数read_until() 和async_read_until()。