bool sendMessageToGraphics(char* msg)
{
//char ea[] = "SSS";
char* chRequest = msg; // Client -> Server
DWORD cbBytesWritten, cbRequestBytes;
// Send one message to the pipe.
cbRequestBytes = sizeof(TCHAR) * (lstrlen(chRequest) + 1);
if (*msg - '8' == 0)
{
char new_msg[1024] = { 0 };
string answer = "0" + '\0';
copy(answer.begin(), answer.end(), new_msg);
char *request = new_msg;
WriteFile(hPipe, request, cbRequestBytes, &cbRequestBytes, NULL);
}
BOOL bResult = WriteFile( // Write to the pipe.
hPipe, // Handle of the pipe
chRequest, // Message to be written
cbRequestBytes, // Number of bytes to writ
&cbBytesWritten, // Number of bytes written
NULL); // Not overlapped
if (!bResult/*Failed*/ || cbRequestBytes != cbBytesWritten/*Failed*/)
{
_tprintf(_T("WriteFile failed w/err 0x%08lx\n"), GetLastError());
return false;
}
_tprintf(_T("Sends %ld bytes; Message: \"%s\"\n"),
cbBytesWritten, chRequest);
return true;
}
after the first writefile in running (In case of '8') the other writefile function doesn't work right, can someone understand why ?
the function sendMessageToGraphics need to send move to chess board
There are 2 problems in your code:
First of all, there's a (minor) problem where you initialize a string in your conditional statement. You initialize it as so:
string answer = "0" + '\0';
This does not do what you think it does. It will invoke the operator+ using const char* and char as its argument types. This will perform pointer addition, adding the value of '\0' to where your constant is stored. Since '\0' will be converted to the integer value of 0, it will not add anything to the constant. But your string ends up not having a '\0' terminator. You could solve this by changing the statement to:
string answer = std::string("0") + '\0';
But the real problem lies in the way you use your size variables. You first initialize the size variable to the string length of your input variable (including the terminating '\0' character). Then in your conditional statement you create a new string which you pass to WriteFile, yet you still use the original size. This may cause a buffer overrun, which is undefined behavior. You also set your size variable to however many bytes you wrote to the file. Then later on you use this same value again in the next call. You never actually check this value, so this could cause problems.
The easiest way to change this, is to make sure your sizes are set up correctly. For example, instead of the first call, you could do this:
WriteFile(hPipe, request, answer.size(), &cbBytesWritten, NULL);
Then check the return value WriteFile and the value of cbBytesWritten before you make the next call to WriteFile, that way you know your first call succeeded too.
Also, do not forget to remove your sizeof(TCHAR) part in your size calculation. You are never using TCHAR in your code. Your input is a regular char* and so is the string you use in your conditional. I would also advice replacing WriteFile by WriteFileA to show you are using such characters.
Last of all, make sure your server is actually reading bytes from the handle you write to. If your server does not read from the handle, the WriteFile function will freeze until it can write to the handle again.
Related
I'm using RAW socket to capture udp packets. After capturing I want to parse the packet and see what's inside.
The input I get from the socket is an unsigned char* buffer and it's length. I tried to put the buffer into a string but I guess I did it wrong because when I checked the string it was empty.
Any advice?
I don't know what you want to parse, but your have the buffer and it's length. So you can do everything you want with this memory. Look for pointer arithmetic. If you want to make an C-String out of the content, simply add an '\0' to the end of the memory block. But this assumes, that no other 0x00 are inside the buffer. So maybe you have to check that. Like πάντα ῥεῖ said.
Steps:
1: receive UDP package
2: cast like:
unsigned char* buffer;
char* cString = (char*) buffer;
3: check casted cString if an '\0' occurred before buffer size was reached. If it does, then create a new char* pointer to the byte after the '\0', but be aware of the buffer size. Save the pointer in an vector.
I made an code example, but haven't checked if it is runnable!
char* firstPtr = (char*) buffer;
size_t indexer = 0;
std::vector<char*> pointerVec;
pointerVec.push_back(firstPtr);
while(indexer < bufferSize) {
if(*(buffer + indexer) == '\0') {
if(indexer + 1 < bufferSize) {
char* cString = (char*) (buffer + indexer);
pointerVec.push_back(cString);
}
}
} // end while
After that you should have the positions of the different strings saved with the pointers inside of the vector. Now you can handle them to an copy mechanism which takes every C-String pointer and saves it's content to one C-String or String.
Hope you searched for something like that, because you question was unclear.
I hate to ask this because I think this must be very trivial. But as someone who is used to high-level-languages this is a real problem.
I got a C++ program which uses PDFium to generate an Image to a PDF. And i have a C# program which communicates with the C++ program via Named Pipes. The PDF file (Which is saved as a byte-array) gets transmitted by the pipe. And here is my Problem.
On the 374th Position of the stream is a NUL byte (00) and im too stupid to somehow reach the data after it.
Here is my Code:
LPTSTR lpszPipename2 = TEXT("\\\\.\\pipe\\myNamedPipe2");
hPipe2=CreateFile(lpszPipename2, GENERIC_READ, 0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);
if(ReadFile( hPipe2, chBuf, dwBytesToRead, &cbRead, NULL))
{
PDFData = chBuf;
}
dwBytes to read is the size of the file and cbRead shows the correct number. But PDFData only contains the first 373 bytes. I checked that the data beyond the 373th position is there with the Immediate Window i just don't know how to process it.
I gotta put the Data into a char-array.
As I already said, i think this is very trivial. But although i know where the problem comes from, i have simply no idea how to fix it.
Many Thanks and Regards
Michael
Edit: The C#-Code. Its everything but perfect. But i'm very sure this Problem is on the C++ side.
public void SendRawData(byte[] data)
{
while (clientse == null || clientse.stream == null)
{ }
if (clientse.stream.CanWrite)
{
clientse.stream.Write(data, 0, data.Length);
clientse.stream.Flush();
}
}
private void ListenForClients()
{
while (true)
{
clientHandle = CreateNamedPipe(this.pipeName, DUPLEX | FILE_FLAG_OVERLAPPED, 0, 255, BUFFER_SIZE, BUFFER_SIZE, 0, IntPtr.Zero);
//could not create named pipe
if (clientHandle.IsInvalid)
return;
int success = ConnectNamedPipe(clientHandle, IntPtr.Zero);
//could not connect client
if (success == 0)
return;
clientse = new Client();
clientse.handle = clientHandle;
clientse.stream = new FileStream(clientse.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
if (ClientType == 0)
{
Thread readThread = new Thread(new ThreadStart(Read));
readThread.Start();
}
}
}
"Solution":
Actually this never was a real problem. I just got my wires crossed. While chBuf seemed after copying it into PDFData or when i read its value is VS to only have those 373 bytes. All ~20 kilobytes were copied to that position.
I knew that, but i didn't understand how the PDFium sources should know that if the string terminates after 373 chars.
Well... the PDFium-sources know it cause i have to pass the length. Which was determined by
size_t len = PDFData.length();
and was therefore of course only 373 bytes.
The null character '\0' is used by C/C++ to terminate char* strings. So any library function (i.e. strlen(), strncpy(), etc) will use the null character as an implicit end-of-string indicator. Your code is obviously doing this somewhere. Instead, use something more like memcpy() or a std::vector<char> with an explicit data length.
Have a look at string:assign (http://www.cplusplus.com/reference/string/string/assign/)
String assignment operator from char * uses the C-style end-of-string convention. You need the "buffer" assign call:
string& assign (const char* s, size_t n);
This will include any NULs.
That being said, vector of bytes may indeed be a better choice.
Actually this never was a real problem. I just got my wires crossed. While chBuf seemed after copying it into PDFData or when i read its value is VS to only have those 373 bytes. All ~20 kilobytes were copied to that position. I knew that, but i didn't understand how the PDFium sources should know that if the string terminates after 373 chars.
Well... the PDFium-sources know it cause i have to pass the length. Which was determined by
size_t len = PDFData.length();
and was therefore of course only 373 bytes.
I'm sorry that i bothered you with that stuff
I tried to use WM_COPYDATA to send a string from one window to another. The messaages gets received perfectly by my receiving window. Except the string I send does not stay intact.
Here is my code in the sending application:
HWND wndsend = 0;
wndsend = FindWindowA(0, "Receiving window");
if(wndsend == 0)
{
printf("Couldn't find window.");
}
TCHAR* lpszString = (TCHAR*)"De string is ontvangen";
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = sizeof(lpszString);
cds.lpData = (TCHAR*)lpszString;
SendMessage(wndsend, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)(LPVOID)&cds);
And this is the code in the receiving application:
case WM_COPYDATA :
COPYDATASTRUCT* pcds;
pcds = (COPYDATASTRUCT*)lParam;
if (pcds->dwData == 1)
{
TCHAR *lpszString;
lpszString = (TCHAR *) (pcds->lpData);
MessageBox(0, lpszString, TEXT("clicked"), MB_OK | MB_ICONINFORMATION);
}
return 0;
Now what happens is that the messagebox that gets called outputs chinese letters.
My guess is that I didn't convert it right, or that I don't actually send the string but just the pointer to it, which gives a totally different data in the receiver's window. I don't know how to fix it though.
sizeof(lpszString) is the size of the pointer, but you need the size in bytes of the buffer. You need to use:
sizeof(TCHAR)*(_tcsclen(lpszString)+1)
The code that reads the string should take care not to read off the end of the buffer by reading the value of cbData that is supplied to it.
Remember that sizeof evaluates at compile time. Keep that thought to the front of your mind when you use it and if ever you find yourself using sizeof with something that you know to be dynamic, take a step back.
As an extra, free, piece of advice I suggest that you stop using TCHAR and pick one character set. I would recommend Unicode. So, use wchar_t in place of TCHAR. You are already building a Unicode app.
Also, lpData is a pointer to the actual data, and cbData should be the size of the data, but you're actually setting the size of the pointer. Set it to the length of the string instead (and probably the terminating 0 character too: strlen(lpszString)+1
My goal is create an app client server, written in C++.
When the server read an input from the client, should process the string and give an output.
Basically, I have a simply echo server that send the same message.
But if the user types a special string (like "quit"), the program have to do something else.
My problem is that this one dont happend, because the comparison between strings is not working... I dunno why!
Here a simple code:
while(1) {
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0);
send(client, buffer, num, 0);
char hello[6] ="hello";
if(strcmp(hello,buffer)==0) {
send(client, "hello dude! ", 12, 0);
}
buffer[num] = '\0';
if (buffer[num-1] == '\n')
buffer[num-1] = '\0';
std::cout << buffer;
strcpy(buffer, "");
}
Why the comparison is not working?
I have tried many solutions...but all failed :(
Your data in buf may not be NULL-terminated, because buf contains random data if not initialized. You only know the content of the first num bytes. Therefore you also have to check how much data you've received before comparing the strings:
const char hello[6] ="hello";
size_t hello_sz = sizeof hello - 1;
if(num == hello_sz && memcmp(hello, buffer, hello_sz) == 0) { ...
As a side note, this protocol will be fragile unless you delimit your messages, so in the event of fragmented reads (receive "hel" on first read, "lo" on the second) you can tell where one message starts and another one ends.
strcmp requires null terminated strings. The buffer you read to might have non-null characters after the received message.
Either right before the read do:
ZeroMemory(buffer, BUFSIZE); //or your compiler defined equivalent
Or right after the read
buffer[num] = '\0';
This will ensure that there is a terminating null at the end of the received message and the comparison should work.
A string is defined to be an array of chars upto and including the terminating \0 byte. Initially your buffer contains arbitrary bytes, and is not even guaranteed to contain a string. You have to set buffer[num] = '\0' to make it a string.
That of course means that recv should not read sizeof buffer bytes but one byte less.
I am trying to read a serial response from a hardware device. The string I read is long and I only need a portion of it. To get to portion of the string I want I use std::string.substr(x,y); . The problem I run into however is sometimes I get an exception error because the buffer I am reading from doesn't have y characters. Here is the code I use now to read values:
while(1)
{
char szBuff[50+1] = {0};
char wzBuff[14] = {"AT+CSQ\r"};
DWORD dZBytesRead = 0;
DWORD dwBytesRead = 0;
if(!WriteFile(hSerial, wzBuff, 7, &dZBytesRead, NULL))
std::cout << "Write error";
if(!ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL))
std::cout << "Read Error";
std:: cout << szBuff;
std::string test = std::string(szBuff).substr(8,10);
std::cout << test;
Sleep(500);
I am issuing the command "AT+CSQ". This returns:
N, N
OK
It returns two integer values seperated by a comma followed by a new line, followed by "OK".
My question is, how can I make sure I read all values from the serial port before grabbing a substring? From what I understand, the last character received should be a new line.
The interface of your ReadFile function seems to provide you with the number of bytes read. If you know the length that is expected, you should loop trying reading from the file (probably port descriptor) until the expected number of bytes is read.
If the length of the response is not known, you might have to read and check in the read buffer whether the separator token has been read or not (in this case your protocol seems to indicate that a new-line can be used to determine EOM --end of message)
If you can use other libraries, I would consider using boost::asio and the read_until functionality (or the equivalent in whatever libraries you are using). While the code to manage this is not rocket science, in most cases there is no point in reinventing the wheel.
As you said yourself in the last line, you know that the terminator for the response is a new line character. You need to read from the serial until you receive a new line somewhere in the input. Everything you received from the previous new line to the current new line is the response, with everything after the current new line is part of the next response. This is achieved by reading in a loop, handling each response as it is discovered:
char* myBigBuff;
int indexToBuff = 0;
int startNewLine = 0;
while (ReadFile(hSerial, myBigBuff + indexToBuff, 100, &dwBytesRead, NULL))
{
if (strchr(myBigBuff, '\n') != NULL)
{
handleResponse(myBigBuff + startNewLine, indexToBuff + dwBytesRead);
startNewLine = indexToBuff + dwBytesRead;
}
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
This is the basic idea. You should handle the left overs characters via any way you choose (cyclic buffer, simple copy to a temp array, etc.)
You should use ReadFile to read a certain amount of bytes per cycle into your buffer. This buffer should be filled until ReadFile reads 0 bytes, you have reached your \n or \r\n characters, or filled your buffer to the max.
Once you have done this, there would be no need to substr your string and you can iterate through your character buffer.
For example,
while (awaitResponse) {
ReadFile(hSerial, szBuff, 50, &dwBytesRead, NULL);
if (dwBytesRead != 0) {
// move memory from szBuff to your class member (e.g. mySerialBuff)
} else {
// nothing to read
if (buffCounter > 0) {
// process buffer
}
else {
// zero out all buffers
}
}
}
Old question, but I modified #Eli Iser code to:
while (ReadFile(hSerial, myBigBuff + indexToBuff, 1, &dwBytesRead, NULL)) {
if (strchr(myBigBuff, '-') != NULL || dwBytesRead < 1)
break;
// Move forward in the buffer. This should be done cyclically
indexToBuff += dwBytesRead;
}
if (indexToBuff != 0) {
//Do whatever with the code, it received successfully.
}