|
cartoon_online wrote:
When it was accepted ,AddUser(pSocket) was executed.I mean we should DeleteUser(lUserId) somewhere
Cartoon,
I have made a modification to the hack preventing non MFC clients from sending data through the server. The modifications have also been submitted to Sébastien for review; he has shown interest in including it in the article source code. Its really to bad, more information isn’t transmitted on connect; it would make it so much easier to authenticate a user then.
Sorry it’s taken so long for me to get back to this. I am no longer developing an app of this type but am still very interested in client server technology.
If you need the source code with mods send me an email again, I will push it to you.
-------------------------------
DEBUGGING : Removing the needles from the haystack.
|
|
|
|
|
I have created a server App (Dialog App) derived from CNDKServer and a Regular DLL whose App class derived from CNDKClient. This regular DLL is statically linked to MFC and it is used by one MFC Application(SDI) and one Win 32 Application. These two applications uses the exported functions in the Regular DLL which inturn uses the NDK Client functions to connect and send message to the server(Dialgo App) . Both of these applications uses the worker thread.
I managed to connect and send data to the server using the DLL exported functions from the threads of the MFC and Win 32 client applicatons without any problem.
But the problem is, when the server(Dialog App) sends some message to the client (MFC SDI App or Win 32 App) then the OnReceive of the CNDKClientSocket class is not invoked. But when the client tries to send message to server after some time, now the client is able to receive the message from the server which was sent sometime ago.
I assume that the messge somewhere resides in the queue. When the client tries to send message to server, this queue is invoked and the message is depatched to the client.
Is there any way to solve the problem? The DLL's OnMessage function of CNDKClient should be automatically notified whenever there is a message waiting.
For your Information:
1. I use the following code after each SendMessageToServer function in the Regular DLL(client)
MSG dispatch;
while (::PeekMessage( &dispatch, NULL, 0, 0, PM_NOREMOVE))
{
if (!AfxGetThread()->PumpMessage()) {};
}
If I dont use this code , the message is not despatched to the server.
2. Server (Dialog App) is a single threaded application
3. Clients(MFC SDI App and Win 32 App) are having worker threads besides their main thread. These two clients are linked to the Regular DLL whose App class is derived from CWinApp and CNDKClient classes.
AbuFahima
|
|
|
|
|
question1:should the verification of the username&password be added after the ProcessPendingAccept function?
how should I do to let the onconnect to wait to get the username/password message to have a verification?if username/password is right then ok,else colse the socket.
question2:how can i know the messages received are from the other clients (not my client&non-mfc).i know some alternation should be done in CNDKMessage::Serialize,And my Csocket server just only wanna communicate with my client correctly.Don't wanna get messed by hacker who knows my ip&port.
any answer would be welcome.
|
|
|
|
|
Hello Sebastien Lachance:
First,Thanks to your great work on Network Development Kit 2.0.
I found there seems some problem when I use it create a Server/Client project.
In my project, Client will send a message to Server about every 5 seconds, each
message is the same size, which contains several typies of date, such as UINT,
CString, PVOID data, and so on. A message is about 180,000byte. Most of these
message will be sent and received correctly, but sometimes the function
SendMessageToServer() will block, and the Client program is no response. For this
problem is very stochastic, I can not use the step by step debug mode, but I
also found a interesting thing,that is: when the client is blocked, if I
disconnected the client from the server, the client program will jump to the
CATCH(CFileExecption *e) of the function SendMessageToServer(), and then the
client are not been blocked anymore and the button in the client has response.
I don't know whether I express my problem clearly, sorry to my poor English.
And I found someone also ask the similar problem in codeproject.com, He said
the message package should not be bigger than 64K, and I don't know where I
can find the 2 threads in your answer.
Sorry to bother you so much, I appreciate very much if you can answer my
question or give me some advice to solve this problem.Thank you very much!
|
|
|
|
|
I don't have the time to explain everything but here is a solution that will work for you.
1- The client sends a message to the server
2- When the server receives the message from the client, the server can send
a message to the client to say: "I'm ready to receive another message"
In this scenario, the server will not be overloading.
|
|
|
|
|
hello,
as per msdn KB and some posts here about not to send big data over 64K+ or something, and it was advised to packet the big data sent over the network my question is how do i break the big packet into small messages? should i call t he Add method of single message object multiple times ? or do i create a message object allocate it 60 K bufer and send it and create a new message object with next 60 K ?
Thanks
|
|
|
|
|
Please read the following 2 threads:
- How to send files using this project
- Hot to get the progress when receiving file
They contain information about sending files.
|
|
|
|
|
This program can only send message. I want to send voice over my LAN, how should I do?
|
|
|
|
|
There is a problem with the destruction of ur CNDKClient. I was creating a client and whenever i closed my client there was a sound (BOOOM :P ) from the windows ( the sound that comes when there is some criticle error) but there was no messsage box. and it screwed me to find out where is it occuring either in server or client.
Then i tested ur demo project. the test case is
1- run demo server
2- run demo client
3- start listening with the server on any port
4- connect the client
5- close the client ( without disconnecting it )
there is a sound. if u disconnect it and then close it there is no prblem.
*********************************
Now where the problem actually lies. i feel like its a C++ polymorphisim conceptual mistake of urs. it took me 30 40 mins to find it out. the problem is the call to pure virtual function onDisconnect through CloseConnection in the destructor of ur CNDKClient class.
what actually happens is i derive my class from CNDKClient. when i click close button of dialog my dialog class object is destroyed and then virtual destructor calls the destrcutor of (base class) CNDKClient.. which ultimiately tries to call a pure virtual method OnDisconnect from within CloseConnection. where as the OnDisconnect doesn't really exists and so an invalid function pointer raises this boom.
i hope u'll look into ur library implementaion again once again thanks for the article.
|
|
|
|
|
This problem may be avoided by modifying the CNDKClient destructor:
CNDKClient::~CNDKClient()
{
SendMessageToServer(CNDKMessage(NDKClientDisconnect));
CleanUp();
}
Program work is the same but OnDisconnect is not called when the class is destroyed
Thank You
Regards
|
|
|
|
|
well author its a marvelous article and library to create client server applications. I was coding a very simple server with this library and i found my application crashing. the test case is
1- create a very simple server that does nothing just listens on some port 4000
2- open telnet to the same port
3- send data to server by typing into telnet and at one state (after 10 11 characters on my machine) the server crashes. I debugged it to lookinto the problem the problem exists in the serialization of elements. when the following line executes
m_elements.SetSize(nNbElements); ( line 489 NDKMessage.cpp)
the CArray Asserts at this line
ASSERT(nNewSize <= SIZE_T_MAX/sizeof(TYPE)); // no overflow (afxtempl.h line 328)
the parameter of nNbElements was something a reall big. if you fix it it'll be a reall usefull library. but unless somebody can crash the server by ending some packets u know it'll screw everything.
Thanks for great article.
|
|
|
|
|
This problem will arise with any program that use CSocket and CArchive. I did not find the solution yet.
|
|
|
|
|
hello,
i've seen that the 2 precompiled programs work only on Windows 9x/ME. trying running and/or compiling them with Visual C++ 2003 the client logs in to the server but the server doesnt receive the custom chat message. the server doesnt add the user name to the list in the dialog, it doesnt receive any messages from the client. only sending the "disconnect all" message or disconnecting the server, the clients receive the disconnection message.
It's a known problem? there's a way to fix it?
Thanks
|
|
|
|
|
Hi, first thanks for your great job.
I am a beginner on Windows Socket programming, and my application must deal with multithreading, and i want to use NDK to simplify my programming, is it suitable for that?
Thanks.
|
|
|
|
|
this development kit need a error reporting system. calls of GetLastError() not work correctly.
to many other calls (inside on dev kit) resets the error flag.
please insert a GetError() function to get an error string/code if a function fails.
THX for this great work!
greets CodeFlatter
|
|
|
|
|
Hello again,
i have made a server in a regular DLL, where the NDK2 derived server inserts received data into a buffer. In a worker thread i read the buffer works with the data and sends a responce back to the client.
When the server tries to send the responds back i get the following error:
The instruction at "0x00a39103" referenced memmory at "0x00000004". The memmory could not be "read"
The debug shows me that a ZERO pointer has sneaked into CAsyncSocket, and that the socket cannot be validated. Can anybody help me with this problem?
in advace thanks
Michael Olsen
|
|
|
|
|
I am not familiar with CSockets, so just looking at the source code of the NDK I cannot tell in advance what behaviour to expect. Additionally I cannot setup a realistic environment for testing. I will try to describe a scenario that hopefully describes my question.
Let's suppose that the server has to call SendMessageToAllUsers multiple times in a short time period. Looking at the source code, the user.SendMessage(message) will be called for each client. Suppose now, that a client is connected with a slow or busy connection. Is the next client "blocked" by this slow client??? Has the client to acknowledge that the message was received and everything is OK for the server to continue with the next client/message?? Please note that this does not have to be only a SendMessageToAllUsers example. This question also applies to multiple SendMessageToUser calls.
By the way is there a way to implement a time-out ??? (provided that is makes sense)
Thank you in advance for any input.
Warm regards
Pothitos M. Baikas
|
|
|
|
|
i dont know the answer for the first question (the one that takes 6 lines), but you dont have to worry about that.
there is a way to implement a timeout, and usually the timeout is 100 milliseconds (well, thats what the msdn says...)
i think the answer for the first question is yes, but not for a long time (1 second is quite fast)
its very simple to implement a timeout, just set a timer and send your message (dont forget to create a random number for your message and add that number to your message)
if timer has finished its job and you still didnt get that number from the server, it means the message wasn't sent or server couldn't send a message to you
if you got the number before the timer finished its job, you can kill it (the timer!).
simple, isn't it
Amir.
|
|
|
|
|
Hi, I have some problems while auto sending message from server to client,pleas see the following:
class CServer : public CNDKServer
{......
CMainFrame* m_pMainFrame;
CWinThread* m_pWinThread;
bool m_bIsThreadRun;
bool StartThread(void);
UINT SendDataToClient(void);
static UINT ControllingFunction(LPVOID pParam);
void GetAllData(void);
void GetOneData(void);
......
}
When Client requests auto send data, I create a thread to do this:
bool CServer::StartThread()
{
m_pWinThread = AfxBeginThread(ControllingFunction, this, THREAD_PRIORITY_NORMAL, 0 , CREATE_SUSPENDED, NULL);
if(m_pWinThread)
{
m_bIsThreadRun = true;
m_pWinThread->ResumeThread();
}
else
{
m_bIsThreadRun = false;
m_pMainFrame->m_Log.Log(LOG_ERROR, _T("Fail to start thread!"));
}
return m_bIsThreadRun;
}
UINT CServer::ControllingFunction(LPVOID pParam)
{
UINT nExitCode = ((CServer*)pParam)->SendDataToClient();
return nExitCode;
}
UINT CServer::SendDataToClient()
{
while(m_bIsThreadRun)
{
if(m_pMainFrame->m_Config.m_bIsAutoSendAll)
GetAllData();
else if(m_pMainFrame->m_Config.m_bIsAutoSendOne)
GetOneData();
Sleep(m_pMainFrame->m_Config.m_lSamplePeriod * 1000);
}
return 0;
}
And, GetAllData() GetOneData() calls SendMessageToUser(message).
Now, when sending a message, socket will get asserted:
#ifdef _DEBUG
void CAsyncSocket::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_hSocket == INVALID_SOCKET || CAsyncSocket::FromHandle(m_hSocket) != NULL);
}
However, if CServer doesn't send message to client from multithread, it will OK.My app is based on MFC FormView, and CMainFrame class contains a CServer object, like this: CServer m_Server;
Also , I have patched the following code in the OnReceive() of CNDKServerSocket:
VERIFY(AsyncSelect(/*FD_READ | */FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE)); // CHANGE 1
...
CString strSockName = _T("");
UINT uiSockPort;
if(GetSockName(strSockName, uiSockPort) !=0)
VERIFY(AsyncSelect()); // CHANGE 2
(About this code: When I used WinCE & eVC, CCeSocket doesn't support AsyncSelect function, so I don't add the code. However, it works well in WinCE & eVC, I don't know why.)
I don't know the internal implenmention of the CSocket class, Can anyone help me? Thanks a lot!
|
|
|
|
|
Hello,
sorry for my bad english, i comes from germany and i have no train
yao_xuejun wrote:
#ifdef _DEBUG
void CAsyncSocket::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_hSocket == INVALID_SOCKET || CAsyncSocket::FromHandle(m_hSocket) != NULL);
}
However, if CServer doesn't send message to client from multithread, it will OK.My app is based on MFC FormView, and CMainFrame class contains a CServer object, like this: CServer m_Server;
assertion refers to which the object internal structures for thread are invalid.
the problem is: all mfc-objects (like CSocket) was only thread-save on class-base, NOT on object-base. i mean, no objects can be used on a thread if the thread this object NOT have createt.
a solution is using the Detach() method from primary thread after Create, pass the handle from object to the thread and Attach() the handle to a new object. dont forget Detach() if the object no longer used in the secondary thread.
sample:
<br />
m_pWinThread = AfxBeginThread(ControllingFunction, this, THREAD_PRIORITY_NORMAL, 0 , CREATE_SUSPENDED, NULL);<br />
<br />
m_pWinThread->hSocket = m_Socket.Detach();<br />
<br />
if(m_pWinThread)<br />
{<br />
m_bIsThreadRun = true;<br />
m_pWinThread->ResumeThread();<br />
}<br />
... <br />
<br />
<br />
CSocket sock;<br />
sock.Attach( hSocket );<br />
this problem has many more objects from MFC on using with threads.
1) Detach() the object and forward the handle of this to the thread
2) create a new object and bind the handle (on 3) with a new object inside the thread
3a) use FromHandle() or
3b) use Attach() inside of the new thread thats using this object
use Attach() only if is guaranteed the fact that the corresponding object exists so long the thread works.
I hope this helps and you understand the problem
|
|
|
|
|
Thank you very much for your reply, I understand your means. But How to fix this when used in NDK2.0? "SOCKET" is inside the class, Anyway to correct this? Thanks a lot!
|
|
|
|
|
I modified the example of the server a little bit just to test a couple of things. What I did was to add some code to send messages to all connected clients in a rather rapid way using a timer event. The server and clients behaved as expected. The only problem appeared when a client decided to disconnect while the server kept sending messages. At this point the server crashed at the CNDKMessage::Serialize(CArchive& archive) because of a not valid archive (at least that's is how it looks to me). I am trying to find a way to overcome this problem by checking archive before proceeding. Is this the correct approach??? And if so can you please help ???
Warm regards
Pothitos
|
|
|
|
|
Unfortunately, I don't have the time to help you more using the NDK.
Did you overide the OnDisconnectUser in the chat server?
|
|
|
|
|
What I did was to add a
if (&archive == NULL)
{
ResetCurrentIndex();
return;
}
before proceeding. Seems to be working, although I am not sure if this the best approach.
Just hope that you will be able to look into this issue at a later time.
Warm regards and thanks for the excellent class.
|
|
|
|
|
I do not have the means to check it right now, so I would appreciate the author's opinion. If the client is behind a proxy, will it be able to communicate with the server (the server on a internet machine)
Warm regards
Pothitos M. Baikas
|
|
|
|