|
Environment: Windows 7, Visual Studio 2008, C++ MFC
Question:
How does class AsyncSocket for the server side detect and notify the application when the client closes the connection?
Details:
I wrote the async article found here: Asynchronous TCP Part 1 as a learning tool. Now that I am using that knowledge in a working project I find that when the client closes the socket, I don’t see any results on the server side. I was expecting that OnClose() would be called, but that does not happen. On the client side, after closing, no data can be received until it is Initialized and connected again.
The problem is that in the real application, when the client closes and re-connects the interface protocol for the client requires that the server send some specific information. I am not seeing a way to detect that closure.
Edit: OnClose is declared public. That was an answer in another thread.
And again: I do not have the client code and have no control over the client side behavior.
and again: continued searching yielded something about the read() method getting a result or error. This server application never receives any data from the client and uses no reads. Do I still need to post a read to get a close status?
POSSIBLE ANSWER
My application uses C_Server, decended from CAsyncSocket, to post the Listen and call Accept(). In the call to Accept it creates an object from C_Server_Send to communicate with the client. When I add code to post a receive from C_Server_Send, and then close the client, OnClose() from C_Server_Send gets called. So, empirically, I conclude that Yes, I must post a receive to enable detection of client disconnect. Is that correct?
NEW PROBLEM:
How is C_Server_Send to be deleted.
First: C_Server_Send was newed from C_Server, but that object can create an indefiniate number of C_Server_Send objects as multiple clients connect. Must it keep track of each one.
Second: How does C_Server know that its time to delete an arbitrary instance of C_Server_Send?
Thanks for your time
modified 6-Nov-12 12:54pm.
|
|
|
|
|
Visual Studio, MFC, C++, Windows 7
I need to create some GUIs that I consider to be intermediate level, definatly more than the standard tutorial presents. Included is the ability to divide the screen into multiple areas and to dynamically draw some simple block diagrams with lines between the blocks with colors and labels.
Does someone have a link to some good articles or good books to suggest?
Thanks for your time
|
|
|
|
|
You probably need to look into Splitter Windows[^] and GDI+[^] for creating graphics. There are also some articles on GDI+ here[^].
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
char buffer[50]
int offset =3;
char Buffer[250];
sprintf_s(&buffer[offset],offset,"%s",Buffer);
When we use the above funcation and application crashed with the folloing message
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
Program: xyz.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\vsprintf.c Line: 244 Expression: ("Buffer too small", 0)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------
OS used : Windows 7 32bit OS
Microsoft Visual Studio 2008 (VC++)
Version 9.0.30729.1SP
|
|
|
|
|
It looks like you are trying to store a 250 character string into a 50 character buffer, and you have told the formatter that the buffer is only 3 characters long. But ultimately your code makes little sense.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
A description I read had GetLastError where I expected WSAGetLastError and my searches did not return those pages. Thanks for the links.
Thanks for your time
|
|
|
|
|
I think you meant to reply on the message thread below.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Even if make 50 char sting into a 50 char buffer, I am getting the same error.
Is there any other way to do this?
The same code works fine in VS6.0 and not in VS2008.
|
|
|
|
|
As I said before, you are specifying a buffer size of 3, so any number of characters greater than that will cause the error. Check the documentation[^] for specific details of the parameters and their values.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Member 9353776 wrote: char buffer[50]
int offset =3;
char Buffer[250];
sprintf_s(&buffer[offset],offset,"%s",Buffer);
I am trying to guess what your code is supposed to do here but this might be closer to what you want:
char buffer[50]
int offset =3;
char Buffer[250];
sprintf_s(&buffer[offset], sizeof(buffer) - offset, "%s", Buffer);
The second parameter of sprintf_s as used here is the maximum allowed length of the output buffer. If the buffer is of size 50 and you want to write starting in element 3 then the obvious size remaining is 'sizeof(buffer) - offset' and not 'offset'.
HTH
--
Harvey
|
|
|
|
|
Visual Studio 2008, MFC, C++
What is the difference between WSAGetLastError() and GetLastError()?
Thanks for your time
|
|
|
|
|
You can check by looking here[^] and here[^].
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Dear Friend,
I wrote one code working fine in VC6 BUT throwing ASSERTIONS in VS2010 (NOT SP1). [Debug Mode only]
#include
typedef map<cstring, int=""> MapString2Int;
int main()
{
MapString2Int mapString2Int;
mapString2Int[_T("ABC")] = 20; /// Throw error
mapString2Int[_T("XYZ")] = 40; /// Throw Error
}
It saying "map/set insert iterator outside range"
Thanks,
Subhash
|
|
|
|
|
You have not defined the types in your map template; the above code does not even compile.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
im trying to copy a cimage dib to the clipboard. the second
memcpy fails with a read access violation. can anyone help?
CImage tmpImage = pDoc->m_imageArray[0];
int w = tmpImage.GetWidth();
int h = tmpImage.GetHeight();
int Bpp = tmpImage.GetBPP();
BITMAPINFOHEADER bmInfohdr;
bmInfohdr.biSize = sizeof(BITMAPINFOHEADER);
bmInfohdr.biWidth = w;
bmInfohdr.biHeight = -h;
bmInfohdr.biPlanes = 1;
bmInfohdr.biBitCount = Bpp;
bmInfohdr.biCompression = BI_RGB;
bmInfohdr.biSizeImage = w*h*Bpp;
bmInfohdr.biXPelsPerMeter = 0;
bmInfohdr.biYPelsPerMeter = 0;
bmInfohdr.biClrUsed = 0;
bmInfohdr.biClrImportant = 0;
BITMAPINFO bmInfo;
bmInfo.bmiHeader = bmInfohdr;
bmInfo.bmiColors[0].rgbBlue=255;
void* pBits = tmpImage.GetBits();
HANDLE hData = ::GlobalAlloc (GMEM_MOVEABLE, sizeof(BITMAPINFO) + w * h * 3);
LPVOID pData = (LPVOID) ::GlobalLock (hData);
LPBYTE p_imagebits;
p_imagebits = (LPBYTE)pData + sizeof(BITMAPINFO);
memcpy(pData,&bmInfo,sizeof(BITMAPINFO));
DWORD dwBytes = ((DWORD) w * Bpp) / 32;
if(((DWORD) w * Bpp) % 32) {
dwBytes++;
}
dwBytes *= 4;
unsigned long m_dwSizeImage = dwBytes * h;
memcpy (p_imagebits, pBits, m_dwSizeImage);
::GlobalUnlock (hData);
COleDataSource* pods = new COleDataSource;
pods->CacheGlobalData (CF_DIB, hData);
pods->SetClipboard ();
|
|
|
|
|
It fails because the memory allocated by GlobalAlloc is not enough. See, how you use sizeof(BITMAPINFO) + w * h * 3 value to allocate memory, and then you are trying to calculate the m_dwSizeImage value, which is much greater then requested.
You have got two options:
Either move this chunk of code after you have calculated the image size, so that your code becomes:
DWORD dwBytes = ((DWORD) w * Bpp) / 32;
if(((DWORD) w * Bpp) % 32) {
dwBytes++;
}
dwBytes *= 4;
unsigned long m_dwSizeImage = dwBytes * h;
void* pBits = tmpImage.GetBits();
HANDLE hData = ::GlobalAlloc (GMEM_MOVEABLE, sizeof(BITMAPINFO) + m_dwSizeImage);
LPVOID pData = (LPVOID) ::GlobalLock (hData);
LPBYTE p_imagebits;
p_imagebits = (LPBYTE)pData + sizeof(BITMAPINFO);
memcpy(pData,&bmInfo,sizeof(BITMAPINFO));
memcpy (p_imagebits, pBits, m_dwSizeImage);
Or, just use a solution[^] from Codeguru
BTW, it looks like you have calculated the m_dwImageSize incorrectly anyway
|
|
|
|
|
Code snippet below. The SeekToBegin fails because the CFile object has an invalid file handle. But the open returns true, so the code proceeds to die an ugly death. The code is called within a tight loop passing through a couple of hundred files. It feels like I'm overrunning the hard drive or file system, but I have no idea how I might do that... any thoughts are greatly appreciated.
FilePath = (CString)directoryBuf;
FilePath += (CString)"\\uncompressed.unc";
CFileException fe;
if(UncompFile.Open(FilePath, CFile::shareExclusive | CFile::modeCreate | CFile::modeReadWrite), &fe)
{
UncompFile.SeekToBegin();
UncompFile.Write(outBuf, c_stream.total_out);
UncompFile.SeekToBegin();
UncompFile.Write(outBuf, c_stream.total_out);
UncompFile.Close();
cmpCRC = helper.ComputeFileCRC( FilePath );
UncompFile.Remove((LPCTSTR)FilePath);
if(uncCRC != cmpCRC)
{
ErrorString = (CString)infoStruct->sourceFileName + "\n failed CRC test.";
return ErrorString;
}
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
modified 10-Oct-12 13:11pm.
|
|
|
|
|
Okay, I made one change. Just prior to the .Close, I now invoke .Flush().
The main difference between my environment and the old environment is that my laptop is much faster with a solid state disk. Is it possible that there is a race condition inside of CFile? Seems like I'm grasping at straws.
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
|
|
|
|
|
Why is this code duplicated?
UncompFile.SeekToBegin();
UncompFile.Write(outBuf, c_stream.total_out);
FYI, Remove() is a static method. It will be correct to call it like this:
CFile::Remove((LPCTSTR)FilePath)
The method Remove() can throw an exception
Example here[^]
|
|
|
|
|
Duplicated code: I don't know. I didn't write this code . Not ducking the question, and it did occur to me that if I was creating a file, the initial position would be zero. In testing, I commented out that line only to have the same exception thrown on the write method - bad file handle.
Static Remove and exceptions: noted.
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
|
|
|
|
|
FilePath = (CString)directoryBuf;
FilePath += (CString)"\\uncompressed.unc";
What is the purpose of the casts in the above statements?
In the rest of your code you are not checking the contents of fe after the open so you cannot be sure you have a valid handle at that point. It is always advisable to check the return status of every function call dealing with files, rather than assuming they all succeed.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Inherited code, probably done for no particular reason. They're gone now.
Function returns: yup, not going to argue the point.
I'm going to condense this code down to a very tight little application and hammer a hard drive. Adding the flush seemed to stabilize things, but I'm suspicious of memory corruption.
Stay tuned for the next episode of "As the Code turns..." will Charlie find happiness?
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
|
|
|
|
|
Richard - the fe content only becomes important if the open call fails. Note the weirdness, it's returning true yet with an invalid handle. In the debugger, I can see that the content of the file exception structure is "no error".
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
|
|
|
|
|
charlieg wrote: it's returning true yet with an invalid handle. I find that very hard to believe; I think you are perhaps misreading something.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
if(UncompFile.Open(FilePath, ...)
{
UncompFile.SeekToBegin(); // <--- asserts here. bad file handle...
I don't know how I could misread that. I'm all ears or eyes....
Charlie Gilley
<italic>You're going to tell me what I want to know, or I'm going to beat you to death in your own house.
"Where liberty dwells, there is my country." B. Franklin, 1783
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
|
|
|
|