|
If you're using a streaming protocol like TCP, sockets only understands bytes -
it knows nothing about structures.
You need to send until all the bytes you want to send are sent.
You're also responsible for knowing what to recv on the other end.
You need to recv until you've received all the bytes you're expecting.
There's lots of ways to implement it, the simplest being a loop - something like:
Packet packet;
...
int BytesToSend = sizeof(Packet);
const char *pBytesToSend = (const char *)&packet;
while (BytesToSend > 0)
{
int BytesSent = ::send(socket, pBytesToSend, BytesToSend, 0);
if (BytesSent == SOCKET_ERROR)
{
int SockErr = ::WSAGetLastError();
if (SockErr != WSAEWOULDBLOCK)
{
break;
}
BytesSent = 0;
}
pBytesToSend += BytesSent;
BytesToSend -= BytesSent;
} The code for receiving is similar except recv() returns 0 when the socket closes.
Note that looping on recv() is bad unless you know you're expecting incoming bytes.
Receiving is better done on a blocking socket in a separate thread or using a non-blocking
socket in a loop controlled by the async FD_READ event (so the loop isn't always spinning
waiting for incoming bytes).
Since your packet struct has a size member, you can make it more efficient by sending
the size member and only the number of bytes indicated by the size member.
On the receiving end, receive just a WORD (the size - note that receive may take two
tries to get the entire WORD!)). Now with that size, you know how many bytes to receive
into a Packet struct.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
So my problem was really...
My data don't get mixed...
My data got cut .. and i didn't send 100% ~.~ ajaja
I work now for ~3years on sockets and internet-stuff..
But i really looked for such a info ~.~ (maybe I searched wrong ?)
But hehe thx now I understand It a little more..
I will add this to my Server..
But .. I looked msnd..
and found this:
WSAAsyncSelect
unsigned int wMsg1=0;
WSAAsyncSelect(Socket, NULL, wMsg1, FD_READ);
I understand it like.. I can look with the function .. if the buffer is ready for new data or not..
Or I am wrong ? msdn is sometimes really confusing to me ..
|
|
|
|
|
WSAAsyncSelect() and/or WSAEventSelect() can help your asynchronous sockets by
sending you a window message or setting an event when certain network events occur.
To receive a window message when there's data available to be received from the socket
you can use something like
WSAAsyncSelect(Socket, hwndNotifyWindow, MY_WM_SOCKETEVENT, FD_READ);
The window with the handle "hwndNotifyWindow" will receive a "MY_WM_SOCKETEVENT"
window message, which will have an error code and event code encoded in the LPARAM.
Note that the FD_READ event just tells you there's SOME data available to be read from
the socket. It's still up to you to keep track of how much data is received - it may be
received in chunks a different size than the way data was sent.
You may also want to monitor FD_CLOSE events as well.
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Thx a lot .. fixed all my problems now.. and it works fine
|
|
|
|
|
Would this code make problems .. when I
while i use this procedure to send data..
try to recv data on a other thread ?
Because I got now the problem.. I get 100% recv .. means i get all data
But now I use this procedure to sent.. and lose some packets.. (somehow..)
For recv i am using WSARecv()
And for send .. I am using send()
... does this make problems ?
-- modified at 7:57 Wednesday 29th August, 2007
|
|
|
|
|
Hello Friends
I am using socket to send data on internet server and recieve data. For that first i am sending the header of http. It is as follow.
POST / HTTP/1.0<br />
Accept: image/gif, image/x-xbitmap,application/vnd.ms- Excel,application/msword,\napplication/vnd.ms-powerpoint, *
And Then I start receivin the data.(i know, i know first will be header).I am receiving the Header correct .
But the problem is, other data I receive is as follow for each and every site.
<br />
Your browser sent a request that this server could not understand.
I dont know what is worng with my code. but if any one knows what went wrong please tell me.
|
|
|
|
|
HMm I am doign it witht his header:
<br />
GET / HTTP/1.0<br />
Host: WWW.CODEPROJECT.COM
Worked for me.. normaly.. :P
|
|
|
|
|
Hi my pet program is crashing at "_ASSERTE(_CrtIsValidHeapPointer(pUserData))" ...
<br />
int main(int argc, char* argv[])<br />
{<br />
...<br />
char szBuffer1[10] = "abcde";<br />
char szBuffer2[10] = "fghij";<br />
char * pszBuffer = NULL;<br />
char ch;<br />
<br />
pszBuffer = new char[10];<br />
free(pszBuffer); << LOCATION1: OKAY<br />
pszBuffer = NULL;<br />
<br />
pszBuffer = CUtilities::NullTerminateString(szBuffer1); << From "Utilities" dll - i.e. different translation unit<br />
ch = pszBuffer[5];
free(pszBuffer); << LOCATION2: CRASH Here!<br />
pszBuffer = NULL;<br />
...<br />
}
It crashed at LOCATION1.
Looking into "Utilities" dll, looks like memory is allocated the very same way as "pszBuffer = new char[10]" - what makes the difference between LOCATION1 and LOCATION2:
char * CUtilities::NullTerminateString(char * pszData)<br />
{<br />
char * pszResult = NULL;<br />
<br />
if(pszData==NULL)<br />
{<br />
return NULL;<br />
}<br />
<br />
string strTemp(pszData);<br />
int nSize = strTemp.size() +1;<br />
<br />
pszResult = new char[nSize];<br />
strcpy(pszResult, pszData);<br />
pszResult[nSize-1] = '\0';<br />
<br />
return pszResult;<br />
}
The only difference it seems is that LOCATION1 is in "main" and LOCATION2 is in "Utilities" dll, is that significant?
Stack trace lead us to here:
_CRTIMP void __cdecl _free_dbg(<br />
void * pUserData,<br />
int nBlockUse<br />
)<br />
{<br />
...<br />
<br />
_ASSERTE(_CrtIsValidHeapPointer(pUserData)); << CRASH HERE!<br />
<br />
...<br />
}
Thanks
|
|
|
|
|
You are trying to free memory, that was new ed on one heap on another heap.
You either need to change your DLL-function to give it a buffer and a lenght or you need to provide a DLL-Function to free memory allocated in the DLL. (See SysAllocString /SysFreeString . These exist for the same reason.).
In C++/STL you could use allocators to get memory from the right heap.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
I have a feeling because you're allocating in one dll and deallocating from another you just need to use SysAllocString and SysFreeString
Any tutorial for the newbie? That's a lot of COM and BSTR.
Thanks
|
|
|
|
|
No, No!
I never said you would need to call SysAllocString and SysFreeString !
I only said that the COM-Code has a special SysFreeString function to have the same DLL do the deleting that did the newing. The same course of action I thought you could go.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
Just to expand on the other reply...
To tidy up after new , use delete , or for an array use delete [] .
To tidy up after malloc , use free . Malloc is fine for allocating chunks of memory, but not for objects. (It doesn't call the constructor).
Imagine you have two friends, Bob and Frank.
devvy: Bob, please give me your favourite screwdriver.
Bob: Ok, here you go. Please give it back when you're done with it.
... devvy puts up his shelves ...
devvy: Here you go Frank, have your screwdriver back.
Frank: Eek, I don't have a screwdriver, you're messing with my mind man!
Frank: I don't know what to do with this! It clashes with my other stuff! I'm depressed! Now where did I put that sharp object...
Here endeth the lesson.
Iain.
|
|
|
|
|
Iain Clarke wrote: Imagine you have two friends, Bob and Frank.
devvy: Bob, please give me your favourite screwdriver.
Bob: Ok, here you go. Please give it back when you're done with it.
... devvy puts up his shelves ...
devvy: Here you go Frank, have your screwdriver back.
Frank: Eek, I don't have a screwdriver, you're messing with my mind man!
Frank: I don't know what to do with this! It clashes with my other stuff! I'm depressed! Now where did I put that sharp object...
Iain Clarke wrote: after new, use delete
mmm...I was thinking the same
Russell
|
|
|
|
|
I tried:
(a) "new" with "delete"
and
(b) "free" with "malloc"
Still crashing the very same way... and besides I think I'm already doing this.
Do you mean?
<br />
char * pszBuffer = NULL;<br />
pszBuffer = new char[10];<br />
delete [] pszBuffer; << deleting array?<br />
pszBuffer = NULL;<br />
|
|
|
|
|
Yes, if you do
XXXX *pX = new XXXX [n];
then you should get rid of it with
delete [] pX
Try the above code with:
class XXXX
{
public:
XXXX ()
{
TRACE0("XXXX Constructed\n");
}
~XXXX ()
{
TRACE0("XXXX Destructed\n");
}
};
main ()
{
XXXX *pX = new XXXX [4];
delete pX;
XXXX *pX = new XXXX [4];
delete [] pX;
}
In answer to your main question...
It appears that you have memory allocated from within the DLL, and freed from within the EXE. This is another example of using different memory buckets, and can lead to difficulties. While I haven't been bitten by this myself, either I'm lucky, or careful. I didn't think new / delete suffered from this problem like malloc & free, but I could be wrong.
There are a number of ways to deal with this... For an object, you could use a Release () method, and get it to delete itself - and the code for that would be in the same dll as the creation.
For chunks of memory, windows has a bunch of LocalAllocs, GlobalAllocs, which point to the same functions under Win32 I think.
Or look at the IMalloc interface for allocating / freeing memory.
Good luck,
Iain.
|
|
|
|
|
|
You are missing the point, devvvy. You have two problems:
a) the new/delete pairing, which you said you've fixed (original post was new/free pairing which is not correct).
b) the actual location of the new/delete pairing - this is causing the CRASH.
devvvy wrote:
I tried:
(a) "new" with "delete"
and
(b) "free" with "malloc"
Still crashing the very same way... and besides I think I'm already doing this.
You are pairing new with free(), not with delete, so you need to make the change.
However, you need to use the correct pairing (new & delete) in the same routine.
Your logic:
Create a new buffer in main();
Free buffer in main(); // Works okay
Create a new buffer in the DLL;
Free that buffer outside of the DLL, in the main program; // Crashes
You can't do that because the main program and the DLL have different heaps. The main program does not have access to the DLL's heap, so the pointer is invalid upon return to main.
Either create the 2nd buffer in main and also pass the 2nd buffer to NullTerminateString, or add a new method to the CUtilities class that deletes pszResult when you are done with it.
Reread the comments on the _CrtIsValidHeapPointer() before the _ASSERTE(). That describes your problem exactly.
devvvy wrote: /*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
<br />
It is difficult to tell the intended purpose of NullTerminateString(). The logic (use of string.size()) and variable names (pszData) both indicate the input is already a null-terminated string, but my brain says that you actually want to add a null to a non-null-terminated string. Not clear...<br />
<br />
I assume the purpose of NullTerminateString() is therefore to add a second null to the end of an already null-terminated string, because the routine fails if char * pszData is not already null terminated. (It can't determine proper size at string.size().)<br />
<br />
<br />
<blockquote class="FQ"><div class="FQA">devvvy wrote:</div>ch = pszBuffer[5]; // Should be '\0'<br />
free(pszBuffer); << LOCATION2: CRASH Here!<br />
</blockquote><br />
<br />
Note: pszBuffer[5] WILL BE NULL even without calling NullTerminateString()!<br />
Set szBuffer1 to 'a','b','c','d','e','f','g','h','i','j' and watch things go crazy.<br />
Gary
|
|
|
|
|
Thanks - I did take care not to allocate and disallocate memory from different dll... howeever, may be I missed certain places the trouble remains.
Advised by another developer, I changed some of the methods to take "const string &" as supposed to just "string" - after which the problem persists when debugged under Visual Studio 6. And the problem disappeared when debugged under Visual Studio 2005...
passing by value invokes "temporaries", and destructor won't work properly for these temporaries when passed across dll boundaries? But still why it crashed with VS6 and not VS2005??
baffling!!
I can send you the code if you are willing to look at it. Thanks!
devy
|
|
|
|
|
The computer I am using havn't been installed MSDN.I want to know that how to use CreatePolygonRgn(CONST POINT*,int,int).Could somebody send the information about the function in MSDN?Thank you.
And is the function PtInRgn exist?I want to use the both function to judge if a point in a polygon region.
Thanks for your help.
|
|
|
|
|
If you can access the Internet, you can go to http://msdn.microsoft.com
|
|
|
|
|
|
Strangely enough if you google createpolygonrgn the first listed linkage is TADA[^]
|
|
|
|
|
Did you ever realize that if you want to find help for a function on MSDN, it is much more efficient to use google than the MSDN search ?
|
|
|
|
|
hey, MSDN site has been refactored, and i find it very very much powerful by now !
|
|
|
|
|
I only have the modem connection and google is quicker, MSDN takes at least a minute to load, the same again to return the list of linkages.
|
|
|
|
|