|
Also, a randomly generated User ID wasn't practical for my application so I used the following to change it to the hostname, which may or may not be conflicting:
LPTSTR lpszSystemInfo;
DWORD cchBuff = 256;
lpszSystemInfo = _T("");
::GetComputerName(lpszSystemInfo,&cchBuff);
m_strNickname = lpszSystemInfo;
I set a timer event in the server to ping all users every 60 seconds. Some of the clients will lose their connection within the first two or three minutes. Even though the UserId's are still listed in the list box, they're no longer sending replies to the server's ping or receiving data. It doesn't appear that a ping from a client to the server produces any results.
I also set a timer event in the client to test for IsConnected() and even though they're not recieving data and their UserId is still displayed in the server's list box, IsConnected() is still returning TRUE apparantly, which makes it difficult to attempt a method of reconnecting.
I set up a "HeartBeat" message that sets a variable, sends the message, and then tests the variable again after a sleep(). The server responds by resetting and sending the variable back to the client. If the server responds, nothing happens. Otherwise, the client will attempt to reconnect. This doesn't seem to be working for some reason, and seems a bit redundant anyway since this is TCP/IP and there should be a natural keepalive method already in place?
|
|
|
|
|
Client Stop receiving packets.
I send huge file ~ 500 MB by 100kb packets and client freqently stop receiving.
Server block in winsock send and gives error WSAEWOULDBLOCK, so buffer is full and client don't accept any data.
Maybe analyzing with sniffer transfer packet will show real problem, maybe packets don't reach client.
|
|
|
|
|
I have the same problem where the client stops recieving messages but I am using win2k-sp3 and vc6.
Some things i noticed:
I think it started happening after I started sending larger packets. (>300 but < 600 bytes)
It fails less often on win xp pro.
It doesn't happen all the time. 75% of the time it fails. In other words, repeating the exact same step with the exact same data doesn't always fail. (bleh)
Closing and reopening connection and then rejoining the server seems to fix the problem. (bleh,bleh)
Some Questions:
Could it have anything to do with 'reusing' the message instead of instaniating a new CNDKMessage to reply? I noticed I have done both.
I have been leaving open the connection so either the server or the client can start a transaction. Is this not recomended?
I have a timed (1 sec interval) server status message going out to the clients. Can u see any problem with this?
Thanks in advance.
|
|
|
|
|
More info:
Just before the client made the offending request. The server was sending two small packets. If I removed the first packet the problem dissapeared.
The sequence was this.
A-Client: Sends ~400 byte packet. Server places data in database (MySQL) and generates a transaction ID.
B-Server: Sends CString that was poped up for the user to see that the previous transaction was completed. Client used AfxMessageBox to display this CString. BTW: It doesn't matter if I call AfxMessageBox or not.
C-Server: Sends Ack code for 400 byte packet. This Ack packet contains the id for the transaction.
D-Client: Sends request for the server to lookup the transaction using the ID returned in the Ack packet. (Yes the client is requesting the info it just sent. I did this as a check and to reuse existing code)
F-Server: Sends requested info. <- This is the packet that doesn't arrive, although debuging shows it was sent.
If I remove B, F arrives. I consider this very ugly, especially since it only failed 75% of the time. Makes you wonder what else is out there ready to bite you in the butt.
Offending Server code:
CNDKMessage message(ChatText);
CString strText;
strText.Format("Transaction %011d added",id);
message.SetAt(0, strNickname);
message.SetAt(1, strText);
SendMessageToUser(lUserId, message); <- REMOVING THIS LINE FIXED THE PROBLEM
message.SetAt(0, ChatNewTransaction);
message.SetAt(1, id);
message.SetId(ChatAck);
SendMessageToUser(lUserId, message);
Question:
Why did this fix the problem? Seems like it should have been a legal opperation.
FYI: Other than this one problem the NDK has been outstanding. It is easy to use and understand. Thank you for sharing!
|
|
|
|
|
Hi,
Could you try the following code:
CNDKMessage message(ChatText);
CString strText;
strText.Format("Transaction %011d added",id);
message.Add(strNickname);
message.Add(strText);
SendMessageToUser(lUserId, message); <- REMOVING THIS LINE FIXED THE PROBLEM
CNDKMessage message2(ChatAck);
message.Add(ChatNewTransaction);
message.Add(id);
SendMessageToUser(lUserId, message2);
|
|
|
|
|
It did not work. Same problem.
Typos:
message2.Add(ChatNewTransaction);
message2.Add(id);
Thanks for the quick reply. This is a weird one.
|
|
|
|
|
I hope that this will give you a futher clue as to what the problem is. I added a Sleep(1000) between the 2 packets and it fixed the problem.
CNDKMessage message(ChatText);
CString strText;
strText.Format("Transaction %011d added",id);
message.SetAt(0, strNickname);
message.SetAt(1, strText);
SendMessageToUser(lUserId, message);
Sleep(1000); <- ADDING THIS LINE FIXED THE PROBLEM
message.SetAt(0, ChatNewTransaction);
message.SetAt(1, id);
message.SetId(ChatAck);
SendMessageToUser(lUserId, message);
|
|
|
|
|
I made the changes sugested by djof and happily they have fixed the problem in win 2000 using vc6. I was able to get rid of all the unhappy 'Sleep(1000)' statemants in my code except for one. I made the following changes to the client side:
void CNDKClientSocket::OnReceive(int nErrorCode)
{
VERIFY(AsyncSelect(/*FD_READ | */FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE)); // CHANGE 1
CSocket::OnReceive(nErrorCode);
ASSERT(m_pClient != NULL);
if (m_pClient != NULL)
m_pClient->ProcessPendingRead(nErrorCode);
VERIFY(AsyncSelect()); // CHANGE 2
}
Similarly to the server side:
void CNDKServerSocket::OnReceive(int nErrorCode)
{
VERIFY(AsyncSelect(/*FD_READ | */FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE)); // CHANGE 3
CSocket::OnReceive(nErrorCode);
ASSERT(m_pServer != NULL);
if (m_pServer != NULL)
m_pServer->ProcessPendingRead(this, nErrorCode);
VERIFY(AsyncSelect()); // CHANGE 4
}
As I said this HAS fixed the problem with the client stalling. Everything works smoothly until the client closes. This is the client side code that handles the WM_CLOSE message:
void CMyClient::OnClose()
{
KillTimer(ID_HEARTBEAT);
Sleep(1000); // Bleh
g_LogMgr.CloseLogFile();
CloseConnection();
}
If I remove the Sleep(1000) here, the SERVER asserts in line labled 'CHANGE 4' above.
Since the program is closing this is not a big problem. I guess it has something to do with the order stuff is being closed. The important thing is the nasty client stalls are fixed. Hooray!
|
|
|
|
|
I need to know how to detect when a message sent to my server is invalid. I am able to easily crash my server program if I connect to it using something such as telnet. All I do is send a few characters and the server will crash, because it's not receiving an NDK message. What is the best way to prevent this?
|
|
|
|
|
I also need to know how to do this asap...
Any help would be greatly appreaciated.
|
|
|
|
|
Hi,
This is what I found in the MSDN library:
If you are writing an MFC client program to communicate with established (non-MFC) servers, do not send C++ objects through the archive. Unless the server is an MFC application that understands the kinds of objects you want to send, it will not be able to receive and deserialize your objects. For related material on the subject of communicating with non-MFC applications, also see the article Windows Sockets: Byte Ordering.
So, take a look at Windows Sockets: Byte Ordering maybe it could solve your problem
|
|
|
|
|
hi,
does anyone know how the server can keep an open connection with every client??
the server doesn't use any threads??
plz, can anyone tell how this is done in NDK?
thanx
|
|
|
|
|
I am using the NDK under VC7 on an XP machine to do a client/server program. My problem is, that after awhile, my Client stops receiving messages from the server.
The client will send some sort of request, and then the server will respond with the requested data. When the server sends fairly small messages, it will usually work fine (but not always), but the "lost messages" effect happens very regularly when the server sends a number of larger messages back (around 2000bytes).
The Server is still getting the requests from the client, but the client simply doesnt get the message from the Server after awhile. And I can't figure out how to detect that the messages aren't getting there, besides having my client timeout after awhile, which seems like a bad solution. I must disconnect and then reconnect, and then it will work fine (until it stops working).
Even stranger, when I run my programs on my Windows2000 machine, the messages start to get lost even faster, and sometimes the Server stops receiving my Clients messages!
I am very frustrated with this, as I need to have this working within the next few weeks and would hate to have to switch to some other method.. could the problem be with the Serializing method of sending messages??
Please help!
-Jeff
|
|
|
|
|
|
Did you try with VC.NET 2003?
The NDK is only an encapsulation of the MFC class CSocket. The problem reside in CSocket or CArchive.
|
|
|
|
|
I figured it was a CSocket problem. I am using VC.NET 2002, and will probably upgrade shortly.
For now, it works good enough. I will probably have it detect a lost connection and have it disconnect then reconnect as a temporary solution.
I really like the Message class! So easy to use..
Thanks
-Jeff
|
|
|
|
|
I've had the exact same problem... I'm on VS02 as well...but I don't see how that would have anything to do with it.
Anyone have any solutions? It'd be much appreciated.
Shutter
|
|
|
|
|
VS02 is soo buggy. As an example, the IMPLEMENT_SERIAL macro contains a bug.
|
|
|
|
|
I havent found any solutions. I have my program time out and reconnect and resubmit the last command, but it's not the nicest solution.
I haven't upgraded to the new VS yet, however I am finding that I require Async socket communication, so I've started writing my own classes, which are similar to NDK (as far as the message construction). Also I needed it to be a bit more stable as far as unwanted users connecting sending incorrectly formatted messages.
Kind of sucks because I like NDK, but I'm really requiring non-blocking communication. However, NDK certainly has given me some great idea's for my own classes!
-Jeff
|
|
|
|
|
Did Anybody try to use VC.NET 2003?
BR
Maurizio Caltabiano
|
|
|
|
|
On some systems I have seen Win2k PCs lose connections to a NT4 server after a period of time. It is then necassary to make several attempts and give it about 30 seconds in one case before the connection is reestablished.
This was with non M$ software so I would suspect some signalling problem between Win2k and NT4 server, possibly a 'keep alive' indication form the Win2k PC is needed.
Elaine
The tigress is here
|
|
|
|
|
I have a client that has the exact same problem, using CSocket and CArchive.
I checked with a packet sniffer than the data is sent from the server to be sure it was. My uneducated guess is that it is is most likely a buffer problem with the CArchive. The CSocket::OnReceive() callback isn't called anymore, most probably as they explain on MSDN, it won't be called unless the buffer was previously emptied. Then all you have to do is check if it's empty? Right! But it doesn't work. CArchive::IsBufferEmpty() is broken or something, and always tell empty. That's why
while (!ar.IsBufferEmpty())<br />
{<br />
...<br />
}
doesn't work and you have to use
do<br />
{<br />
...<br />
} while (!ar.IsBufferEmpty())
But even there, it won't EVER loop, because IsBufferEmpty() ALWAYS returns 1.
Here is my experience with this bug, still haven't found a fix with VC++ 2002:
http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_20545841.html#8592117
If anyone finds out ANYTHING about this bug, please post it here! Please!
Djof
"Je me souviens"
|
|
|
|
|
Quote from Microsoft Knowledge Base Article - 185728:
----------
In Windows Sockets, you should not make multiple recv calls within an FD_READ notification unless you are willing to disable FD_READ notifications prior to calling recv. However, CSocket and CAsyncSocket make no provision for doing so. Therefore, you should make only one Receive call per OnReceive function. Under high data transmission rate, if you make more than one Receive call in the OnReceive function, the application might lose FD_READ, have fake FD_READ, or have no FD_READ (hanging).
You can use CSocket with CArchive and CSocketFile to directly receive and send MFC CObject-derived objects. However, under high data transmission rates, you should not use CSocket with CArchive and CSocketFile within the OnReceive function because they might internally generate multiple Receive calls.
----------
So a simple fix is to disable FD_READ notifications during the span of the On Receive callback.
void CMySocket::OnReceive(int nErrorCode)<br />
{<br />
VERIFY(AsyncSelect(FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE));<br />
<br />
<br />
VERIFY(AsyncSelect());<br />
}
Note that if you disconnect and delete the socket during the your reception code, make sure you do not call AsyncSelect(), or you will assert.
Djof
"Je me souviens"
|
|
|
|
|
Thanks a bunch!
When I originally had this problem, I was using CSockets. After inquiring several other developers who despised CSocket, I rewrote my project, centering around CAsyncSocket.
So, after testing, I concluded that the result was 200% better than before...but the clients still stopped receiving after about 1000 messages.
I added the lines of code described by Djof, and voila! No problems at all! I haven't lost a message in the flow since.
Thanks!
Shutter
----------------------------
Help the environment--
Empty your recycling bin.
|
|
|
|
|
This is not solution, cause we lose speed. I tried such solution and i lost about 60-90% of data trasmision speed.
|
|
|
|