UDP datagram is being split on space character - c++

I am trying to get my head into SDLnet and I am encountering a problem where any UDP packets that I send from the client to the server are being broken up on the space character. I can't see any reason for this happening as I am not explicitly programming this behaviour in - I am literally just sending across a string.
The source code I am using is part of an online example on The Game Programming Wiki
Server
printf("Fill the buffer\n>");
scanf("%s", (char *)p->data);
p->address.host = srvadd.host; /* Set the destination host */
p->address.port = srvadd.port; /* And destination port */
p->len = strlen((char *)p->data) + 1;
SDLNet_UDP_Send(sd, -1, p); /* This sets the p->channel */
/* Quit if packet contains "quit" */
if (!strcmp((char *)p->data, "quit"))
quit = 1;
Client
/* Wait a packet. UDP_Recv returns != 0 if a packet is coming */
if (SDLNet_UDP_Recv(sd, p))
{
printf("UDP Packet incoming\n");
printf("\tChan: %d\n", p->channel);
printf("\tData: %s\n", (char *)p->data);
printf("\tLen: %d\n", p->len);
printf("\tMaxlen: %d\n", p->maxlen);
printf("\tStatus: %d\n", p->status);
printf("\tAddress: %x %x\n", p->address.host, p->address.port);
/* Quit if packet contains "quit" */
if (strcmp((char *)p->data, "quit") == 0)
quit = 1;
}
Output
The output looks like this image.
The operating system I am running on is Windows 7 64-bit and I'm wondering if this could be something OS-related.

This is not the fault of UDP, it's go to do with the char* being split up when using scanf. ( I'm not a 100% sure about the details here. ) But as a general rule, in C, you shouldn't use scanf
Since you are using C++ ( at least according to the tags), you should do this the C++ way :
std::string msg = "";
std::cout << "Type a message and hit enter\n";
// Let user type a message
std::cin.ignore();
std::getline(std::cin, msg );
// UDPpacket uses Uint8, whereas msg.c_str() gives us a char*
// This simply copies the integer value of the chars into packet->data
memcpy(packet->data, msg.c_str(), msg.length() );
packet->len = msg.length();
Note :
The std::cin.ignore(); is there to make sure we stop and wait for the user to type in the message.

Related

Simplest IPC from one Linux app to another in C++ on raspberry pi

I need the simplest most reliable IPC method from one C++ app running on the RPi to another app.
All I'm trying to do is send a string message of 40 characters from one app to another
The first app is running as a service on boot, the other app is started at a later time and is frequently exited and restarted for debugging
The frequent debugging for the second app is whats causing problems with the IPCs I've tried so far
I've tried about 3 different methods and here is where they failed:
File FIFO, the problem is one program hangs while the other program is writing to the file
Shared memory: cannot initialize on one thread and read from another thread. Also frequent exiting while debugging causing GDB crashes with the following GDB command is taking too long to complete -stack-list-frames --thread 1
UDP socket with localhost - same issue as above, plus improper exits block the socket, forcing me to reboot device
Non blocking pipe - not getting any messages on the receiving process
What else can I try? I dont want to get the DBus library, seems too complex for this application.
Any simple server and client code or a link to it would be helpful
Here is my non-blockign pipe code, that doesnt work for me,
I assume its because I dont have a reference to the pipe from one app to the other
Code sourced from here: https://www.geeksforgeeks.org/non-blocking-io-with-pipes-in-c/
char* msg1 = "hello";
char* msg2 = "bye !!";
int p[2], i;
bool InitClient()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Read
int nread;
char buf[MSGSIZE];
// write link
close(p[1]);
while (1) {
// read call if return -1 then pipe is
// empty because of fcntl
nread = read(p[0], buf, MSGSIZE);
switch (nread) {
case -1:
// case -1 means pipe is empty and errono
// set EAGAIN
if(errno == EAGAIN) {
printf("(pipe empty)\n");
sleep(1);
break;
}
default:
// text read
// by default return no. of bytes
// which read call read at that time
printf("MSG = % s\n", buf);
}
}
return true;
}
bool InitServer()
{
// error checking for pipe
if(pipe(p) < 0)
exit(1);
// error checking for fcntl
if(fcntl(p[0], F_SETFL, O_NONBLOCK) < 0)
exit(2);
//Write
// read link
close(p[0]);
// write 3 times "hello" in 3 second interval
for(i = 0 ; i < 3000000000 ; i++) {
write(p[0], msg1, MSGSIZE);
sleep(3);
}
// write "bye" one times
write(p[0], msg2, MSGSIZE);
return true;
}
Please consider ZeroMQ
https://zeromq.org/
It is lightweight and has wrapper for all major programming languages.

Winsock 2, condensing variables into a string, sending it out, then recieving it and reading it back

I am writing some code that involves using an inertia cube tracker, that actively changes its yaw pitch and roll (in degrees) and I need to set up a server that reads that information in order to network the info. So far I have created a client and server, but the problem I am having is either to send the information in one chunck then read it back as three and print it, or to specify which send matches with which recieve.
if( currentTrackerH > 0 )
{
int iSendResult1;
int iSendResult2;
int iSendResult3;
char EulerBuffer0[64];
char EulerBuffer1[64];
char EulerBuffer2[64];
showStationData( currentTrackerH, &TrackerInfo,
&Stations[station-1], &data.Station[station-1],
&StationsHwInfo[currentTrackerH-1][station-1],
showTemp);
//send to the server
do{
sprintf(EulerBuffer0, "%f", data.Station[station-1].Euler[0]);
iSendResult1= send(Connection, EulerBuffer0, sizeof(data.Station[station-1].Euler[0]), NULL);
sprintf(EulerBuffer1, "%f", data.Station[station-1].Euler[1]);
iSendResult2= send(Connection, EulerBuffer1, sizeof(data.Station[station-1].Euler[1]), NULL);
sprintf(EulerBuffer2, "%f", data.Station[station-1].Euler[2]);
iSendResult3= send(Connection, EulerBuffer2, sizeof(data.Station[station-1].Euler[2]), NULL);
}while ((iSendResult1 || iSendResult2 || iSendResult3)>0);
//shutdown the socket when there is no more data to send
iSendResult1 = shutdown(Connection, SD_SEND);
if (iSendResult1 == SOCKET_ERROR)
{
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(Connection);
WSACleanup();
return 1;
}
}
}
This is my client side and here I will put my server side. The networks connect and my tracker code works just fine but sending and recieving is where it all gets wonky.
//begin recieving data
char yaw[256];
char pitch[256];
char roll[256];
int iResult1;
int iResult2;
int iResult3;
float fyaw, fpitch, froll;
do{
do {
iResult1= recv(newConnection, yaw,sizeof(yaw),NULL);
} while( iResult1 == 0 );
fyaw = atof(yaw);
do {
iResult2= recv(newConnection, pitch,sizeof(pitch),NULL);
} while( iResult1 == 0 );
fpitch = atof(pitch);
do {
iResult3= recv(newConnection, roll,sizeof(roll),NULL);
} while( iResult1 == 0 );
froll = atof(roll);
printf("(%f,%f,%f)deg \n",
fyaw, fpitch, froll);
}while(1);
my knowledge of c++ is not fantastic and any help would be lovely. Thanks!
There is all kinds of wrong in your code. Let's try to break down and correct misconceptions (I assume you're using TCP.) You are sending buffers of one size, but recv'ing potentially a buffer of another size. sizeof(yaw) which is a float, is not the same as the size of the string representation of this float.
Calling send/recv for individual item is slow. Ideally you would define a simple protocol. A message in this protocol would be a string containing all the values you wish to transmit. You send that message using a single send() On the receiving side you read in the stream of data, and look for specific markers that tell you when you have received a complete message. You then process that message, splitting out the different components into your yaw/pitch/roll variables.
An example of a string message would be: "{yaw=1.34;pitch=2.45;roll=5.67}"
Then on the client you continually read into a buffer your data until you reach the "}" Then you can process this message and parse out the different components.

Using c++ to send smtp mail

I was wondering if you could help me understand what is going wrong here. I am trying to write a little client that engages in SMTP dialogue on port 25.
If you recall SMTP, there's a few things you need to send, and then you write the email after the DATA message, ending with a period on it's own line to send the email.
There is something problematic in the way the program handles this. It handles the dialogue fine until after the DATA message. It will recognize the period only if I type it first. After any subsequent line, any code execution seems to be lost. The if statement fails to recognize if a period has been entered. Thank you again. Attached is the relevant code..
void readstuff(int sock, char* buf) {
int r = read (sock, buf, BUFSIZE -1);
buf[r] = NULL;
cout << buf << endl;
}
void doit(int sock, string arg, char* buf) {
int r = write(sock, arg.c_str(), arg.length());
readstuff(sock, buf);
}
int main(int argc, char *argv[]) {
char buf[BUFSIZE];
// Make a socket
int sock = MakeSocket(argv[1], argv[2]);
cout << "socket is " << sock << endl;
assert(sock != -1);
// Begin dialogue
doit(sock, "HELO " + org.substr(org.find("#") + 1) + "\r\n", buf);
doit(sock, "MAIL FROM: <" + org + "> \r\n", buf);
doit(sock, "RCPT TO: <" + dest + "> \r\n", buf);
doit(sock, "DATA \r\n", buf);
readstuff(sock, buf); //should say "go ahead"
//User writes email here
while (true) {
string line = "";
getline(cin, line);
doit(sock, line + "\r\n", buf);
if (line == ".") {
readstuff(sock, buf); //should say "email cleared to send"
return 0;
}
}
}
Please read the SMTP specification, RFC 5321, particularly sections 4.1.1.4 DATA and 4.5.2 Transparency:
4.1.1.4. DATA (DATA)
The receiver normally sends a 354 response to DATA, and then treats
the lines (strings ending in <CRLF> sequences, as described in
Section 2.3.7) following the command as mail data from the sender.
This command causes the mail data to be appended to the mail data
buffer. The mail data may contain any of the 128 ASCII character
codes, although experience has indicated that use of control
characters other than SP, HT, CR, and LF may cause problems and
SHOULD be avoided when possible.
The mail data are terminated by a line containing only a period, that
is, the character sequence "<CRLF>.<CRLF>", where the first <CRLF> is
actually the terminator of the previous line (see Section 4.5.2).
This is the end of mail data indication. The first <CRLF> of this
terminating sequence is also the <CRLF> that ends the final line of
the data (message text) or, if there was no mail data, ends the DATA
command itself (the "no mail data" case does not conform to this
specification since it would require that neither the trace header
fields required by this specification nor the message header section
required by RFC 5322 [4] be transmitted). An extra <CRLF> MUST NOT
be added, as that would cause an empty line to be added to the
message. The only exception to this rule would arise if the message
body were passed to the originating SMTP-sender with a final "line"
that did not end in <CRLF>; in that case, the originating SMTP system
MUST either reject the message as invalid or add <CRLF> in order to
have the receiving SMTP server recognize the "end of data" condition.
The custom of accepting lines ending only in <LF>, as a concession to
non-conforming behavior on the part of some UNIX systems, has proven
to cause more interoperability problems than it solves, and SMTP
server systems MUST NOT do this, even in the name of improved
robustness. In particular, the sequence "<LF>.<LF>" (bare line
feeds, without carriage returns) MUST NOT be treated as equivalent to
<CRLF>.<CRLF> as the end of mail data indication.
Receipt of the end of mail data indication requires the server to
process the stored mail transaction information. This processing
consumes the information in the reverse-path buffer, the forward-path
buffer, and the mail data buffer, and on the completion of this
command these buffers are cleared. If the processing is successful,
the receiver MUST send an OK reply. If the processing fails, the
receiver MUST send a failure reply. The SMTP model does not allow
for partial failures at this point: either the message is accepted by
the server for delivery and a positive response is returned or it is
not accepted and a failure reply is returned. In sending a positive
"250 OK" completion reply to the end of data indication, the receiver
takes full responsibility for the message (see Section 6.1). Errors
that are diagnosed subsequently MUST be reported in a mail message,
as discussed in Section 4.4.
When the SMTP server accepts a message either for relaying or for
final delivery, it inserts a trace record (also referred to
interchangeably as a "time stamp line" or "Received" line) at the top
of the mail data. This trace record indicates the identity of the
host that sent the message, the identity of the host that received
the message (and is inserting this time stamp), and the date and time
the message was received. Relayed messages will have multiple time
stamp lines. Details for formation of these lines, including their
syntax, is specified in Section 4.4.
Additional discussion about the operation of the DATA command appears
in Section 3.3.
Syntax:
data = "DATA" CRLF
4.5.2. Transparency
Without some provision for data transparency, the character sequence
"<CRLF>.<CRLF>" ends the mail text and cannot be sent by the user.
In general, users are not aware of such "forbidden" sequences. To
allow all user composed text to be transmitted transparently, the
following procedures are used:
o Before sending a line of mail text, the SMTP client checks the
first character of the line. If it is a period, one additional
period is inserted at the beginning of the line.
o When a line of mail text is received by the SMTP server, it checks
the line. If the line is composed of a single period, it is
treated as the end of mail indicator. If the first character is a
period and there are other characters on the line, the first
character is deleted.
...
Your DATA command needs to account for that:
Your doit() function is expecting a response after sending a string. That is the wrong logic to use while sending the email data. You can't read a response until after the final terminating <CRLF>.<CRLF> has been sent.
you have to apply transparency to any line in the email that begins with a . character.
With that said, try something more like this:
int readLine(int sock, string &line)
{
// read a line from sock until CRLF is reached.
// I leave this as an exercise for you to implement...
line = ...;
return -1 on error, else 0;
}
int readResponse(int sock)
{
// Please read RFC 5321 section 4.2 for the PROPER format
// of an SMTP response. You should be reading from the
// socket until you receive the terminating
// "Reply-code [ SP textstring ] CRLF" line...
string line;
int r = readLine(sock, line);
if (r < 0) return r;
string code = line.substr(0, 3);
string text = line.substr(4);
if ((line.length() >= 4) && (line[3] = '-'))
{
do
{
r = readLine(sock, line);
if (r < 0) return r;
text += (" " + line.substr(4));
}
while (line.compare(0, 4, code+"-") == 0);
}
cout << code << ": " << text << endl;
return stoi(code);
}
int sendText(int sock, const string &arg)
{
const char *p = arg.c_str();
int len = arg.length();
while (len > 0)
{
int r = write(sock, p, len);
if (r <= 0) return -1;
p += r;
len -= r;
}
return 0;
}
int sendCmd(int sock, const string &arg)
{
int r = sendText(sock, arg + "\r\n");
if (r < 0) return r;
return readResponse(sock);
}
int main(int argc, char *argv[])
{
// Make a socket
int sock = MakeSocket(argv[1], argv[2]);
cout << "socket is " << sock << endl;
assert(sock != -1);
// Begin dialogue
// read the server greeting first...
if (readResponse(sock) != 220) {
// failed, do something...
}
if (sendCmd(sock, "HELO " + org.substr(org.find("#") + 1)) != 250) {
// failed, do something...
}
if (sendCmd(sock, "MAIL FROM: <" + org + ">") != 250) {
// failed, do something...
}
int r = sendCmd(sock, "RCPT TO: <" + dest + ">");
if ((r != 250) && (r != 251)) {
// failed, do something...
}
if (sendCmd(sock, "DATA") != 354) {
// failed, do something...
}
//User writes email here
while (true) {
string line;
getline(cin, line);
// A line consisting of only "." is a valid line in an email
// message, so you should not use that as a terminator in your
// input, use something else, like an EOF marker, or CTRL-C,
// or something...
if (some termination condition)
break;
// DO NOT call readResponse() here!
if (!line.empty() && (line[0] == '.')) {
if (sendText(sock, ".") < 0) {
// failed, do something...
}
}
if (sendText(sock, line) < 0) {
// failed, do something...
}
if (sendText(sock, "\r\n") < 0) {
// failed, do something...
}
}
// NOW call readResponse() here!
if (sendCmd(sock, ".") != 250) {
// failed, do something...
}
sendCmd(sock, "QUIT");
close(sock);
return 0;
}

pcap_next_ex() never sets the pointer to the raw packet?

I tried to read in the raw packet with libpcap (1.4.0 on CentOS 6).
However, for some reasons, rawPacket is always NULL after pcap_next_ex().
However, pcap_next_ex() does return 1 though it could mean timeout expired (where the timeout is set by the way?).
First, I thought that the filter string I passed into pcap_compile() was wrong. But I tried to copy and paste the same string to tcpdump, it worked fine -- I see expected packets being captured.
struct pcap_pkthdr *pHeader;
const u_char* rawPacket = NULL;
int rc = 0;
while (1) {
rc = pcap_next_ex(pDevice, &pHeader, &rawPacket);
if (-1 != rc && NULL != rawPacket) {
// process
struct ether_header* eptr = (struct ether_header *) rawPacket;
if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
printf("Ethernet type hex:%x dec:%d is an IP packet\n",
ntohs(eptr->ether_type),
ntohs(eptr->ether_type));
}
}
}
Any idea?
Thanks in advance.
Actually, what the pcap_next_ex() man page says is
pcap_next_ex() returns 1 if the packet was read without problems, 0 if
packets are being read from a live capture, and the timeout expired, -1
if an error occurred while reading the packet, and -2 if packets are
being read from a ``savefile'', and there are no more packets to read
from the savefile. If -1 is returned, pcap_geterr() or pcap_perror()
may be called with p as an argument to fetch or display the error text.
I need to edit it to remove the comment between "live capture" and "and the timeout expired", because what that means is that pcap_next_ex() returns:
1, if a packet was read or captured, in which case the pointer should be set to the raw packet;
0, if this is a live capture and the timeout (as specified in pcap_open_live() or, if you used pcap_create() and pcap_activate(), pcap_set_timeout()) expired while waiting for a packet, in which case no packet was read and the pointer will be set to NULL;
-1, if an error occurred while reading or capturing, in which case no packet was read and the pointer will be set to NULL;
-2, if this is a file being read and there are no more packets left to be read, in which case no packet was read and the pointer will be set to NULL.
So what you should do, after the pcap_next_ex() call, is:
if (1 == rc) {
// process
struct ether_header* eptr = (struct ether_header *) rawPacket;
if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
printf("Ethernet type hex:%x dec:%d is an IP packet\n",
ntohs(eptr->ether_type),
ntohs(eptr->ether_type));
}
} else if (0 == rc) {
// do nothing here - this isn't an error, but you have no packet
;
} else if (-1 == rc) {
// error
fprintf(stderr, "Error capturing or reading: %s\n", pcap_geterr(pDevice));
// quit trying to read or capture packets here
} else if (-2 == rc) {
// end of file if you're reading from a file
// this isn't an error, but there are no more packets to read
// so quit trying to read packets here
}

Unable to receive data from serial port

Currently I try to write a serial port communication in VC++ to transfer data from PC and robot via XBee transmitter. But after I wrote some commands to poll data from robot, I didn't receive anything from the robot (the output of filesize is 0 in the code.). Because my MATLAB interface works, so the problem should happen in the code not the hardware or communication. Would you please give me help?
01/03/2014 Updated: I have updated my codes. It still can not receive any data from my robot (the output of read is 0). When I use "cout<<&read" in the while loop, I obtain "0041F01C1". I also don't know how to define the size of buffer, because I don't know the size of data I will receive. In the codes, I just give it a random size like 103. Please help me.
// This is the main DLL file.
#include "StdAfx.h"
#include <iostream>
#define WIN32_LEAN_AND_MEAN //for GetCommState command
#include "Windows.h"
#include <WinBase.h>
using namespace std;
int main(){
char init[]="";
HANDLE serialHandle;
// Open serial port
serialHandle = CreateFile("\\\\.\\COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// Do some basic settings
DCB serialParams;
DWORD read, written;
serialParams.DCBlength = sizeof(serialParams);
if((GetCommState(serialHandle, &serialParams)==0))
{
printf("Get configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
serialParams.BaudRate = CBR_57600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
//set flow control="hardware"
serialParams.fOutX=false;
serialParams.fInX=false;
serialParams.fOutxCtsFlow=true;
serialParams.fOutxDsrFlow=true;
serialParams.fDsrSensitivity=true;
serialParams.fRtsControl=RTS_CONTROL_HANDSHAKE;
serialParams.fDtrControl=DTR_CONTROL_HANDSHAKE;
if (!SetCommState(serialHandle, &serialParams))
{
printf("Set configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
// Set timeouts
COMMTIMEOUTS timeout = { 0 };
timeout.ReadIntervalTimeout = 30;
timeout.ReadTotalTimeoutConstant = 30;
timeout.ReadTotalTimeoutMultiplier = 30;
timeout.WriteTotalTimeoutConstant = 30;
timeout.WriteTotalTimeoutMultiplier = 30;
SetCommTimeouts(serialHandle, &timeout);
if (!SetCommTimeouts(serialHandle, &timeout))
{
printf("Set configuration port has a problem.");
return FALSE;
}
//write packet to poll data from robot
WriteFile(serialHandle,">*>p4",strlen(">*>p4"),&written,NULL);
//check whether the data can be received
char buffer[103];
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
} while (read!=0);
//buffer[read]="\0";
CloseHandle(serialHandle);
return 0;
}
GetFileSize is documented not to be valid when used with a serial port handle. Use the ReadFile function to receive serial port data.
You should use strlen instead of sizeof here:
WriteFile(serialHandle,init,strlen(init),&written,NULL)
You would be even better off creating a function like this:
function write_to_robot (const char * msg)
{
DWORD written;
BOOL ok = WriteFile(serialHandle, msg, strlen(msg), &written, NULL)
&& (written == strlen(msg));
if (!ok) printf ("Could not send message '%s' to robot\n", msg);
}
But that's only the appetizer. The main trouble is, as MDN says:
You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device.
If you want to read from the port, you can simply use ReadFile until it returns zero bytes.
If you already know the max size of your robot's response, try reading that many characters.
Continue reading until the read reports an actual number of bytes read inferior to the size of the buffer. For instance:
#define MAX_ROBOT_ANSWER_LENGTH 1000 /* bytes */
const char * read_robot_response ()
{
static char buffer[MAX_ROBOT_ANSWER_LENGTH];
DWORD read;
if (!ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL))
{
printf ("something wrong with the com port handle");
exit (-1);
}
if (read == sizeof(buffer))
{
// the robot response is bigger than it should
printf ("this robot is overly talkative. Flushing input\n");
// read the rest of the input so that the next answer will not be
// polluted by leftovers of the previous one.
do {
ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL);
} while (read != 0);
// report error
return "error: robot response exceeds maximal length";
}
else
{
// add a terminator to string in case Mr Robot forgot to provide one
buffer[read] = '\0';
printf ("Mr Robot said '%s'\n", buffer);
return buffer;
}
}
This simplistic function returns a static variable, which will be overwritten each time you call read_robot_response.
Of course the proper way of doing things would be to use blocking I/Os instead of waiting one second and praying for the robot to answer in time, but that would require a lot more effort.
If you feel adventurous, you can use overlapped I/O, as this lenghty MDN article thoroughly explores.
EDIT: after looking at your code
// this reads at most 103 bytes of the answer, and does not display them
if (!ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL))
{
printf("Reading data to port has a problem.");
return FALSE;
}
// this could display the length of the remaining of the answer,
// provided it is more than 103 bytes long
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
}
while (read!=0);
You are displaying nothing but the length of the response beyond the first 103 characters received.
This should do the trick:
#define BUFFER_LEN 1000
DWORD read;
char buffer [BUFFER_LEN];
do {
if (!ReadFile(
serialHandle, // handle
buffer, // where to put your characters
sizeof(buffer) // max nr of chars to read
-1, // leave space for terminator character
&read, // get the number of bytes actually read
NULL)) // Yet another blody stupid Microsoft parameter
{
// die if something went wrong
printf("Reading data to port has a problem.");
return FALSE;
}
// add a terminator after last character read,
// so as to have a null terminated C string to display
buffer[read] = '\0';
// display what you actually read
cout << buffer;
}
while (read!=0);
I advised you to wrap the actual calls to serial port accesses inside simpler functions for a reason.
As I said before, Microsoft interfaces are a disaster. They are verbose, cumbersome and only moderately consistent. Using them directly leads to awkward and obfuscated code.
Here, for instance, you seem to have gotten confused between read and buffer
read holds the number of bytes actually read from the serial port
buffer holds the actual data.
buffer is what you will want to display to see what the robot answered you
Also, you should have a documentation for your robot stating which kind of answers you are supposed to expect. It would help to know how they are formatted, for instance whether they are null-terminated strings or not. That could dispense to add the string terminator.