我试图让一方向客户端发送错误消息,但客户端无法正确解析它。
我的错误是>>>>>在我的parseString函数中,它让index = 0,因此我的'substr'调用超出了范围。
服务器端:::
#define ERRBUFSIZE 51
string error = "Error - Already Registered: ";
error.append(name);
char err[ERRBUFSIZE];
err[0] = 0;
std::copy(error.begin(), error.end(), err+1);
err[error.size() + 2] = '\0';
if (send(sock, &err, ERRBUFSIZE, 0) < 0)
{
DieWithError("send() failed");
}
客户方(谁正在接收)::
char msgBuffer[ERRBUFSIZE];
int bytesRcvd = 0;
int totalRcvd = 0;
while(totalRcvd != ERRBUFSIZE)
{
// Get Message from Server
if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
DieWithError("recv() failed or connection closed prematurely");
totalRcvd += bytesRcvd;
}
cout << "Bytes received: " << totalRcvd << endl;
msgBuffer[totalRcvd] = '\0';
string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
cout << rcvMsg << endl;
rcvMsg = parseString(rcvMsg);
return rcvMsg;
其中....
string TCPClient::parseString(string message)
{
cout << "parsing new string" << endl;
int index = message.find('\0');
string result = message.substr(0, index);
cout << "THE RESULT :: " << result << endl;
return result;
}
答案 0 :(得分:0)
为什么不将parseString更改为以下内容:
string TCPClient::parseString(const string& message, int strLength )
{
cout << "parsing new string" << endl;
string result = message.substr( 0, strLength );
cout << "THE RESULT :: " << result << endl;
return result;
}
然后将调用代码更改为:
rcvMsg = parseString(rcvMsg, totalRcvd );
如果没有,你甚至可以使用字符串的“size()”函数。
编辑:还值得注意的是,find会在字符串中前进,直到找到'\ 0'字符,但实际上并不会查找它。将字符串放入字符串对象(存储长度)然后尝试通过缓慢的迭代过程自己计算长度似乎有点奇怪。
Edit2:如果您只想使用字符数组,可以按如下方式进行手动搜索。
int index = 0;
while( *charString++ != '\0' ) index++;
就这么简单:)
答案 1 :(得分:0)
从(非常难以阅读)的代码中,我认为你可能会遇到“索引地狱”。
检查totalRecvd
实际上是您要编写\0
的索引,并在创建rcvMsg
时向其添加\0
索引(当你将字符串结束标记放在msgBuffer + totalRcvd
字节上时,totalRcvd
看起来很小便,通常你会在你写的(start,end-1)索引之间得到一个字符串。
另外 - 搜索\0
毫无意义,因为这只是一个标记。
另外(2) - 如果totalRcvd == ERRBUFSIZE
您无法访问msgBuffer [totalRcvd]
,则只能访问范围(0, ERRBUFSIZE -1)
答案 2 :(得分:0)
当您想要管理缓冲区时,请使用std :: vector而不是std :: string。 '\ 0'和std :: basic_string组合得不好。
答案 3 :(得分:0)
首先,协议是令人讨厌的。当你想发送一个以空字符结尾的字符串时,你正在发送固定大小的块...只是将字符串长度放在消息的前面会更简单。
其次,你没有正确地从套接字中读取,只要你在管道中没有任何其他消息,它就会正常工作。 如果你的while循环真的被运用了,你就会用随后的任何读取覆盖第一个片段。
无论如何,这个bug的最直接原因是你在字符串前面添加了一个nul终止符(separator?)。这不能解释为什么你总是在索引0找到你的nul? 如果您看不到它,请尝试写出已发送的缓冲区内容。
#define ERRBUFSIZE 51
void server(string const &name)
{
string error = "Error - Already Registered: ";
error.append(name);
char err[ERRBUFSIZE];
// you sure you want a NUL terminator at index 0??
err[0] = 0;
// can replace both lines with strcpy(err, error.c_str())
std::copy(error.begin(), error.end(), err+1);
err[error.size() + 2] = '\0';
if (send(sock, &err, ERRBUFSIZE, 0) < 0)
DieWithError("send() failed");
}
string parseString(string const &message) // no need to copy
{
// ... this is redundant anyway, see below
}
string client()
{
char msgBuffer[ERRBUFSIZE];
int bytesRcvd = 0;
int totalRcvd = 0;
while(totalRcvd != ERRBUFSIZE)
{
// Get Message from Server
// ... recv(sock, msgBuffer+totalRcvd, ERRBUFSIZE-totalRcvd) ...
if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
DieWithError("recv() failed or connection closed prematurely");
totalRcvd += bytesRcvd;
}
cout << "Bytes received: " << totalRcvd << endl;
//sizeof(msgBuffer)==ERRBUFSIZE==totalRcvd, so this overflows
msgBuffer[totalRcvd] = '\0';
// assuming you skip the leading \0, msgBuffer is already nul-terminated
// so use string rcvMsg(msgBuffer) and skip the parseString/substr
string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
cout << rcvMsg << endl;
// rcvMsg = parseString(rcvMsg);
return rcvMsg;
}