string readMessage(SOCKET clientSocket)
{
char buf[4096];
string storeInfo;
ZeroMemory(buf, 4096);
// Wait for the "Enter" key to be pressed
while (true)
{
int bytes = recv(clientSocket, buf, 4096, 0);
if (bytes == SOCKET_ERROR)
{
cerr << "Error or invalid input, please try again!" << buf << endl;
continue; // Restart the loop
}
for (int i = 0; i < bytes; i++)
{
storeInfo += buf[i];
if (buf[i] == 13) // 13 is the ASCII code for "Enter"
{
cout << " input:-" << storeInfo << "----" << endl;
ZeroMemory(buf, 4096); storeInfoPtr = &storeInfo;
return storeInfo;
storeInfo = "";
}
}
}
I'm using the above code to prompt the client to provide input, then read it using the 'recv()' function, and store the data into a buffer. Then transfer the contents to string variable called storeInfo. According to the console output, the program will transfer the content of the buffer to the content of the string, and output it accurately, except for 2 issues.
storeInfoPtr
to check its contents; initially it will print the correct text, which is just "placeholder," but after that it remains emptyCONSOLE OUTPUT
DESKTOP-AFNABTM.lan connected on port 2282
----ut:- √▼ √ √↑ √' ²☺ √♥ ²♥finley
bad username!
----ut:-fishsticks
bad username!
----ut:-falcon
bad username!
----ut:-falcon
bad username!
----ut:-p3anutbutt3r
bad username!
notice the odd appearance of the first line of text, and the presence of unsual shapes and characters. also notice the formatting is completely wrong: the word "input" is cut out and the hyphens that are supposed to appear after the 'storeInput' data are misplaced
TERMINAL INPUT
please enter a username:
placeholderfinley
bad username
please enter a username:
fishsticks
bad username
please enter a username:
falcon
bad username
please enter a username:
falcon
bad username
please enter a username:
p3anutbutt3r
bad username
please enter a username:
Notice the 'placeholder' text correctly appears in the first instance, but after updating the variable with some input, it becomes blank
Tried multiple strategies including using a pointer variable to try to store the data in another way and access it in different points of the program
I see a number of problems with your code.
You are looking for a specific byte, but you are reading whole blocks of data into a byte[] array. If the peer sends more data after the 0x0D
('\r'
) byte, you are throwing away the excess data instead of caching it for further processing.
If recv()
fails for any error other than WSAEWOULDBLOCK
, your code will get stuck in an endless loop. It will also get stuck in an endless loop if the peer disconnects gracefully, as recv()
will return 0 in that case, not SOCKET_ERROR
, which you are not handling.
Appending characters to a std;;string
1 char at a time is very inefficient, unless you reserve()
space for it ahead of time.
You have an external variable named storeInfoPtr
which you are pointing to the local storeInfo
before return
'ing to the caller. However, storeInfo
will be destroyed upon function exit, leaving storeInfoPtr
dangling.
Try something more like this instead:
string readMessage(SOCKET clientSocket)
{
char buf[4096], ch;
int inBuf = 0, numRead;
string storeInfo;
// Wait for the "Enter" key to be pressed
while (true)
{
numRead = recv(clientSocket, &ch, 1, 0);
if (numRead <= 0)
{
if (numRead == SOCKET_ERROR)
cerr << "Read error " << WSAGetLastError() << "!" << endl;
return ""; or throw an exception
}
if (ch == '\r')
{
storeInfo.append(buf, inBuf);
break;
}
if (inBuf == sizeof(buf))
{
storeInfo.append(buf, inBuf);
inBuf = 0;
}
buf[inBuf++] = ch;
}
cout << " input:-" << storeInfo << "----" << endl;
//storeInfoPtr = &storeInfo;
return storeInfo;
}
Note, most systems treat Enter as 0x0A
('\n'
) instead of 0x0D
. If your client doesn't, you should design your protocol so it does. Most common text-based Internet protocols actually send 0x0D 0x0A
instead, regardless of platform.
In which case, try this:
string readMessage(SOCKET clientSocket)
{
char buf[4096], ch;
int inBuf = 0, numRead;
string storeInfo;
// Wait for the "Enter" key to be pressed
while (true)
{
numRead = recv(clientSocket, &ch, 1, 0);
if (numRead <= 0)
{
if (numRead == SOCKET_ERROR)
cerr << "Read error " << WSAGetLastError() << "!" << endl;
return ""; or throw an exception
}
if (ch == '\n')
{
if ((inBuf > 0) && (buf[inBuf-1] == '\r'))
--inBuf;
storeInfo.append(buf, inBuf);
break;
}
if (inBuf == sizeof(buf))
{
if (buf[inBuf-1] == '\r')
{
storeInfo.append(buf, inBuf-1);
buf[0] = `'\r';
inBuf = 1;
}
else
{
storeInfo.append(buf, inBuf);
inBuf = 0;
}
}
buf[inBuf++] = ch;
}
cout << " input:-" << storeInfo << "----" << endl;
//storeInfoPtr = &storeInfo;
return storeInfo;
}