// This demonstrates how to perform a graceful disconnect, where data sending/receiving // is allowed to complete before the client is disconnected. // In this demo the server begins the graceful disconnect process // It is also possible for a client to initiate a graceful disconnect using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Server { class Program { static void Main(string[] args) { // mnClientConnected return value constants const int C_NOT_CONNECTED = 0; const int C_CONNECTED = 1; const int C_NO_SEND = 2; const int C_NO_RECV = 3; const int C_NO_SEND_RECV = 4; // Setup server int iReturn = 0; Console.WriteLine("DarkNet version: " + mn.GetVersion()); Int64 RecvPacket = mn.CreatePacket(); Int64 SendPacket = mn.CreatePacket(); mn.SetMemorySize(SendPacket,1024); mn.SetUsedSize(SendPacket,1024); mn.Start(1,0); mn.DisableUDP(0); mn.SetLocal(0,"127.0.0.1",6565,"",0); mn.EnableGracefulDisconnect(0); // Enable graceful disconnect mn.StartServer(0,50,0,0); Console.WriteLine("Server started on TCP port " + mn.GetLocalPortTCP(0)); // Send data to clients every SendFreq ms int SendTimer = 0; int SendFreq = 100; // Disconnect a client every DisconnectFreq ms int DisconnectTimer = 0; int DisconnectFreq = 3000; // Main loop bool bRunning = true; while(bRunning == true) { // Use less CPU Thread.Sleep(1); // Graceful close for(int cl = 1;cl<=mn.GetMaxClients(0);cl++) { int iClientStatus = mn.ClientConnected(0,cl); switch(iClientStatus) { // Shutdown client // Further send operations to this client will fail silently // mn.ClientConnected will now return 2 case(C_CONNECTED): if((System.DateTime.Now.Millisecond + (System.DateTime.Now.Second * 1000) + (System.DateTime.Now.Minute * 60 * 1000))-DisconnectTimer > DisconnectFreq) { mn.ShutdownClient(0,cl); Console.WriteLine("Shut down client " + cl); DisconnectTimer = System.DateTime.Now.Millisecond + (System.DateTime.Now.Second * 1000) + (System.DateTime.Now.Minute * 60 * 1000); } break; // Client is sending us data still // We will wait forever, but a robust server should // only wait for a set amount of time, and forcefully // disconnect clients that take too long case(C_NO_SEND): // Nothing to do while we wait break; // Client has finished sending us data // We must get it from packet queue // Once packet queue is empty, client // will be disconnected by mn.ClientConnected // and mn.ClientConnected will return 0 case(C_NO_SEND_RECV): Console.WriteLine("mn.ClientConnected (" + cl + "): " + iClientStatus); while(mn.RecvTCP(0,RecvPacket,cl) > 0) { string str = mn.GetString(RecvPacket,0,true); Console.WriteLine("Final string received from client " + cl + ": " + str); } break; } } // New clients iReturn = mn.ClientJoined(0); if(iReturn > 0) { Console.WriteLine("New client joined, ID: " + iReturn); DisconnectTimer = System.DateTime.Now.Millisecond + (System.DateTime.Now.Second * 1000) + (System.DateTime.Now.Minute * 60 * 1000); } // Leaving clients iReturn = mn.ClientLeft(0); if(iReturn > 0) { Console.WriteLine("Client left, ID: " + iReturn); } // Receive data for(int cl = 1;cl<=mn.GetMaxClients(0);cl++) { if(mn.ClientConnected(0,cl) == C_CONNECTED) { // TCP packets iReturn = mn.RecvTCP(0,RecvPacket,cl); if(iReturn > 0) { string str = mn.GetString(RecvPacket,0,true); Console.WriteLine("String received from client " + cl + ": " + str); } } } // Send data if((System.DateTime.Now.Millisecond + (System.DateTime.Now.Second * 1000) + (System.DateTime.Now.Minute * 60 * 1000)) - SendTimer > SendFreq) { for(int n = 1;n<=mn.GetMaxClients(0);n++) { if(mn.ClientConnected(0,n) == C_CONNECTED) { mn.SendTCP(0,SendPacket,n,true,true); Console.WriteLine("Packet sent"); } } SendTimer = System.DateTime.Now.Millisecond + (System.DateTime.Now.Second * 1000) + (System.DateTime.Now.Minute * 60 * 1000); } } } } }