|
NDK Standard
NDK in an Extension DLL
Introduction
With the success of NDK 1.0, I decided to improve the functionality. NDK represents Network Development Kit. The NDK is a set of classes that implements a client/server architecture. The NDK hides all the complexity of the connection, sending, and receiving of data over a network. You only have to deal with three classes: CNDKServer, CNDKClient, and CNDKMessage. With just a few methods to override, you obtain a complete robust client/server application. The NDK is based on the class CSocket from MFC, so you can run your application on a local network or on the Internet without any change. To easily understand the integration of the NDK in an application, you'll find at the end of this article a complete chat application.
Classes
CNDKServer: Server side of the client/server architecture
Attributes:
BOOL IsStarted() const;
long GetPort() const;
long GetNbUsers() const;
void GetUserIds(CLongArray& alIds) const;
Operations:
BOOL StartListening(long lPort);
void Stop();
BOOL SendMessageToUser(long lUserId, CNDKMessage& message);
BOOL SendMessageToAllUsers(CNDKMessage& message);
BOOL SendMessageToSomeUsers(const CLongArray& alUserIds, CNDKMessage& message);
BOOL SendMessageToAllUsersExceptFor(long lUserId, CNDKMessage& message);
BOOL SendMessageToAllUsersExceptFor(const CLongArray& alUserIds, CNDKMessage& message);
BOOL DisconnectUser(long lUserId);
void DisconnectAllUsers();
BOOL PingUser(long lUserId);
void PingAllUsers();
Callbacks:
virtual BOOL OnIsConnectionAccepted() = 0;
virtual void OnConnect(long lUserId) = 0;
virtual void OnMessage(long lUserId, CNDKMessage& message) = 0;
virtual void OnDisconnect(long lUserId, NDKServerDisconnection disconnectionType) = 0;
virtual void OnPing(long lUserId, long lNbMilliseconds);
CNDKClient: Client side of the client/server architecture
Attributes:
BOOL IsConnected() const;
BOOL GetIpAndPort(CString& strIp, long& lPort) const;
Operations:
BOOL OpenConnection(const CString& strServerIp, long lPort);
void CloseConnection();
BOOL SendMessageToServer(CNDKMessage& message);
BOOL PingServer();
Callbacks:
virtual void OnMessage(CNDKMessage& message) = 0;
virtual void OnDisconnect(NDKClientDisconnection disconnectionType) = 0;
virtual void OnPing(long lNbMilliseconds);
CNDKMessage: Encapsulation of the data that is sent and received by CNDKServer and CNDKClient
Attributes:
void SetId(long lId);
long GetId() const;
int GetNbElements() const;
Operations:
void Add(TYPE typeData);
void SetAt(long lIndex, TYPE typeData);
void GetAt(long lIndex, TYPE& typeData) const;
void GetNext(TYPE& typeData);
Where TYPE can be a UCHAR, char, USHORT, short, UINT, int, long, float, double, CString, or LPVOID data.
What's new in 2.0
- Hungarian notation is used everywhere
CNDKServer notifies automatically CNDKClient when it disconnects and vice-versa
CNDKServer has new methods to send a message to a group of users
CNDKMessage is easier to use and more robust
- New methods to ping the server or the client
- NDK prefix added to all classes to make sure that all class names are unique in your project
- NDK is standalone or encapsulated in an extension DLL
Client/Server chat
Here are two screenshots of the chat application. Most features of the NDK are shown in both programs.


Sample code from the chat clientvoid CChatClientDlg::OnButtonSend()
{
if (UpdateData(TRUE))
{
CNDKMessage message(ChatText);
message.Add(m_strChatInput);
SendMessageToServer(message);
AddText(m_strChatInput);
m_strChatInput.Empty();
UpdateData(FALSE);
}
}
Sample code from the chat servervoid CChatServerDlg::OnMessage(long lUserId, CNDKMessage& message)
{
switch (message.GetId())
{
case ChatText:
{
CString strNickname;
m_mapIdsNicknames.Lookup(lUserId, strNickname);
CString strText;
message.GetAt(0, strText);
AddText(strNickname + _T(": ") + strText);
message.SetAt(0, strNickname);
message.SetAt(1, strText);
SendMessageToAllUsersExceptFor(lUserId, message);
}
break;
}
}
History
- 17 December 2006
- Fixed a bug in
NDKMessage concerning the length parameter of the GetAt and GetNext methods.
- 14 October 2005
- Telnet connections are now disconnected when a connection sends data to the server. Thanks to Stephan Douglas for the solution.
- Fixed a bug that resolves socket notification since the NDK uses Visual C++ .NET. After a short time, socket notifications were not send anymore.
- A verification is now made in the serialization of a
CNDKMessage to make sure that the message is really a CNDKMessage.
- Fixed a bug in the method
SendMessageToSomeUsers in the NDKServer.cpp.
- The project is now converted for Visual C++ .NET.
Fact
In 2002, the NDK was used in two NASA experiments for the Endeavor mission.
Conclusion
You don't have to be a guru of networking to create a client/server application, you only need to understand the above classes.
If you use the NDK in your project, I would really appreciate to receive an E-mail from you. I plan to make a web page of all programs using the NDK.
I would like to thank Yannick Létourneau who helped me in NDK 1.0.
Good Programming!
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 527 (Total in Forum: 527) (Refresh) | FirstPrevNext |
|
 |
|
|
Sebastien, I have implemented the NDK 2.0 class you've developed on a small client server connection with about 10 clients connected to the server. Only 2 clients run on Windows Vista Business and the rest are still using Windows XP Professional SP2.
My problem: 1. Why does the server oftenly experiencing Runtime error? The error is something like the usual application error which then show window Send or Don't Send to Microsoft. After the error, I must restart the server application and it is OK. But after some time, the error happens again. This is very annoying because this connection is really important. And what makes it a serious problem is that the error can be happen even 2-3 times a week on 5 days office work! And I still don't know what cause it.
What should I look up to find the cause? Does the number of clients connected has any relation with this error?
2. I wonder to make this mechanism: If the server error, then all clients will surely be disconnected from the server. When I RESTART the server application, is it possible to AUTOMATICALLY re-connect all the clients WITHOUT the client has to RESTARTING their application?
I am looking forward to hear from you soon.
Thank you very much.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
First, thank you for using the NDK 2.0. Concerning your problem, the NDK is only a layer over MFC CSocket. If something bad happen, it is surely CSocket (where I suspect the crash from Microsoft). My publish game runs for year and my client did not complain.
Concerning your second point, I suggest that each client will be a server and client at the same time. So if you client disappear the other stay connect. This solution is complex but feasible.
Good luck Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Ouw I see. Okey. And Sebastien, one more thing I need to know is concerning this error, I am trying to minimize it. Is it possible for Server, if it has error and unexpectedy ended ABNORMALLY, can it send message to ALL clients which notify that "Server Error and Need To be Restarted."
I have tried it on both Client side and Server side which has OnDisconnect function. But the message always late. After clients close their application, the message will be shown up.
On which part I should handle this Unexpected Server Stop correctly?
Thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Unfortunately, if the connection on the server side has an unexpector error, it is not possible to send a "last" message.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Well that's a problem.
But Sebastien how could the condition when one of the clients has error and it suddenly ended abnormally, that client can notify the server and Server will delete that client from the list? Why does vice-versa( Server notifies Client ) is not possible?
So how can all clients be able to know if the connection is not available? Do you have any other way of handling this condition? How does your game that has been working fine without any complaints handle this condition?
I think unexpected error occured is a common problem in the computer world, isn't it?
Thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The server can send from time to time a ping to the client. He will knows when the client has an unexpected error. The same thing can be applied for the client (he can send message to the server).
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Ok I see. Now I am thinking about your idea of how to make the client side also behave like server side.
I have tried to make all clients LISTENING to the server existence and according to my mind it should have worked but I've got one big problem:
When Server has error, it needs to be restarted, after that all clients need not to restart their applications because I have make them ALSO listening like the server does. But when came to this condition, I got both Server and Client WAITING each other to send a NOTIFICATION packet.
Problem on Server side: How can Server get all clients that it need to send them the NOTIFICATION packet since there HASN'T been any clients connecting since the Server app Restarted?
Problem on Client side: It is now Listening to check if the Server is exist or not. The problem is when can clients know if the Server has been ON / ACTIVE again if the Server have not been able to SEND NOTIFICATION packet to its clients?
How to solve this problems?
I have used CNDKServer::IsStarted(), CNDKServer::StartListening() andCNDKServer::Stop() and put them on the CNDKClient to make clients also LISTENING. Is this correct?
Thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
There is nothing that you need to modify in the NDK, it is only on your app side.
Unfortunately, I do not have the time to help you on this.
Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sebastien, each time a Client dialog call the NDKClient::OpenConnection(), I tried to modify your OpenConnection() function because I need to connect to NOT a Single server but SEVERAL Servers. So I need to save all the CNDKClientSocket object to a CObList and I also remove CloseConnection() function call on the first part of OpenConnection and I move it to OnDestroy event of the application.
I do the CloseConnection() by looping the CObList data and close the CNDKClient one by one per socket object.
Problems: I cannot save the CNDKClientSocket object pointer because it always points to invalid address and of course a Runtime error occured stating that the archiveOut object points to an invalid address, I wonder how could this happen, I have saved the pointer as soon after it is created and DID NOT call any CloseConnection or CleanUp, how could this happen?
And also I am experiencing a little problem with destroying the CNDKClientSocket objects I have saved in a CObList. Sometimes it cause the app to be hung.
It is actually possible to do what I need, isn't it?
How to solve this?
Thank you very much.
modified on Thursday, December 25, 2008 1:02 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have a project that uses the Server portion as a Service on one of the computers to redistribute messages to all connected clients. It works great except if any of the computers sit idle for 30 minutes to an hour, they do not receive any messages sent by other computers. The "sleeping" computer can still send with no problem, so it appears to still be connected, it just doesn't receive. Any suggestions?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey i tried to compile everything in visual studio 2005. The dll gets copiled well but the server and the client brings an error:
Error 1 error LNK2019: unresolved external symbol "public: virtual __thiscall CNDKClient::~CNDKClient(void)" (??1CNDKClient@@UAE@XZ) referenced in function "public: virtual __thiscall CChatClientDlg::~CChatClientDlg(void)" (??1CChatClientDlg@@UAE@XZ) ChatClient.obj
Can you help there
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
As I will develop a program with a server and many clients, I should use IOCP to serve many clients at the same time, So can I modify NDK with IOCP(In/Out completion port),is it feasible?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The NDK already support many clients. Try my chat sample with 2 or more clients. I don't know about IOCP.
Good luck Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have tried NDK 2.0 in my program, but I have some trouble in the application. For instance, I send files at the same time, but the server can't capture a lot of messages at the same time, then the message is lost, and the transformation of file aborts. I think the server work as a single thread,it can't deal with multi message at the same time. Could you give some suggestions to use NDK to make server response to many clients at the same time? 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
Did you check my other article that show how to write a file transfer?
For multithreading, you should consult the CSocket MFC class because the NDK is just a layer over this class.
Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, Yes, I have readed the program of file transfer. I have a new problem: if I send a message many times at the same time(with no delay), the server will receive only one message, the others are all lost. If I send a message with a delay of about 30ms, then the server will receive all the messages.
How to make sure that a message is sent to the server successfully? Once I send a message, how long I should wait to send next message?
Is that the server send a message to client and client should always repy to the server?
Thanks very much!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have succeeded in creating server-client connection and sending message. But the problem occured when I tried to send message inter-client more than ONCE! So first attempt is always succeeded and the rest are failed.
Testing condition: I use only one local workstation to test the app. I ran 2 client apps and 1 server.
The problem is the second attempt and so on, the message shown up in the client app that send the message itself, not in the other client app.
Is it normal?
If not, how to fix this?
Thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
For this one, I do not have the time debugging it. You can use my chat sample to test how the messaging works.
Good luck Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have succeeded in using all the NDK class. But one problem I still need to encounter is on SERVER side of how to REMOVE CLIENT that has been "ABNORMALLY DISCONNECTED" maybe because their computer hang or something unexpected that make them impossible to close the application. Therefore, the disconnect message won't be sent to server.
I have tried to add OnClose function on both NDKServer and NDKClient class but the application won't go there in all conditions.
I have read on your comment that OnDisconnect will handle unexpected disconnect condition but it did not functioned.
How to handle this?
I really need this. Because this is the only thing left unsolved.
I look forward to hear from you soon.
Thank you.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi,
This is perferctly normal that you don't receive a message from the client. Suppose his computer is shutoff, the message will never be sent.
When the server will send another message to the client, this time an error message will occur.
Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
So how to handle that condition? I mean if the client suddenly shut off, I am worry about the pointer that is left unreleased on server and it will make some problem with the server.
I still don't understand how is your method( NDK ) on the Server side to release the clients socket? As far as I can understand, it only delete the user ID from the CMap variable.
Is it not necessary to handle releasing the pointers?
Thank you.
modified on Monday, September 29, 2008 9:30 PM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The server will remove the pointer. You can verify it by going in the Task Manager then kill the client process. After that send a message to this client from the server.
Sébastien
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|