@ kaedroho
This is probably an issue with project settings again. Included in the MikeNet zip folder are full working projects for VS 2008. If you are unable to open this in VS 2005, you could attach your project and I could have a look at the settings.
@ Alfa x
I'll do my best to answer your questions, let me know if I misunderstood any of them.
Quote: "1) When i use mnstart I set the number of cores the application is using. Is there a way to specify which core to use?, is there a way to know wich core is using Darkbasic to use the other core (or cores) for mike net?"
Not currently. I believe if for example if you have a duel core processor and you create two threads, the first thread will use the first core and the second thread will use the second core. I may add an option to set affinity of threads in the next version. You can however set the affinity for the entire application using windows task manager; this can be done on XP by right clicking the process and selecting set affinity.
Quote: "2) How i could minimize the communication with the server to minimize overhead?, is there a way to admin connections and then to let all the communication details to the clients (FOr example in a RTS game)?. This is to minimize server overhead."
Am I right in thinking your question is: Is it possible for clients to communicate directly with each other without going through the server? The answer is yes, but not easily.
I have not attempted this before, but off the top of my head I would achieve this by giving each client three or more instances. 1. mnConnect to main server, 2. mnStartServer to receive data from other clients, 3+. mnConnects to other clients. Upon connection to the main server, the server sends the client's information to all other clients so that they can connect to the new client.
Quote: "3) How I could use the same port for all clients, for example in starcraft when you connect yourself to the battle.net,you use the same port to connect to the server independently of how many computers connect. As far as i know, if you open to many ports you can have a security problem. Is there a way to do it with MikeNet? if yes, can you please explain me how?, it could get congested?
When i try to use the same port i get the following errors(atached as a image at the end of this post). The errors are put in order of appearance from up to down. It asks me if I want to exit and i say "no", although it still works with various cubes (clients) and i don't know if it is safe.
I put in the cube world example the values of the port with "mn set local"."
The errors should cause data transfer on that instance to be impossible, since the sockets were not set up correctly.
It is not currently possible to setup an mnConnect or mnStartServer that have the same local port. It may be possible for me to make this possible in the future though; however, if they are both on the same local port they would both receive the same data which is probably not desirable.
Quote: "4) Do you know how I end the Darkbasic application in c++, when doing a dll for darkbasic if an error is triggered?. "
Yes, the below thread should answer the question:
http://forum.thegamecreators.com/?m=forum_view&t=127872&b=22
Basically, you can use PostQuitMessage or exit, MikeNet uses exit.
@ All
Work on the .Net version of MikeNet is coming along nicely, here is some sample server and client cube world code for C#. Note that it may change before release. I will also be converting the demos into VB.Net:
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using DarkGDK;
using DarkGDK.IO;
using DarkGDK.Camera;
using DarkGDK.Basic3D;
namespace DarkGDKApplication1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Start DarkGDK
Engine.InitializeGDK();
// Below used to identify what each packet is supposed to be for
// Tcp
const int OP_NEWPLAYER = 0;
const int OP_LEFTPLAYER = 1;
// Udp
const int OP_POSITIONPLAYER = 0;
// Array that holds player's cubes
Cube[] PlayerCube = new Cube[0];
// Variables
// Set velocity and turn speed for player movement
const float Velocity = 5, TurnSpeed = 5;
// To be filled during connection
int MaximumClients = 0;
int MaximumOperations = 0;
// Set UDP and TCP port of the server, which is 6789
ushort ConnectPort = 6789;
// Set timeout value which is the length of time
// in seconds that the command will wait for the
// connection to complete until giving up
int Timeout = 10;
// Set the number of threads that will be created
// to deal with incoming data. In most cases this
// should be set to the number of processors on your
// computer. MikeNet can determine this for you
// automatically if you set it to 0
int NoThreads = 0;
// Set the number of MikeNet instances to create.
// Each instance can use either mnStartServer or
// mnConnect
int NoInstances = 1;
// Create packets to store send/recv data
long RecvPacket = mn.CreatePacket();
long SendPacket = mn.CreatePacket();
mn.SetMemorySize(SendPacket,1024);
// Start MikeNet
int Result = mn.Start(NoInstances,NoThreads);
// If an error occurred starting MikeNet
if(Result == -1)
{
Core.Print("Error starting MikeNet");
Core.SuspendForKey();
return;
}
// Get IP address to connect to via UDP and TCP
string ConnectIP = Core.Input("Enter the IP that you would like to connect to: ");
// Try to connect
int Connect = mn.Connect(0,ConnectIP,ConnectPort,ConnectIP,ConnectPort,Timeout,true);
// If the connection was successful
if(Connect == 1)
{
Core.Print("Connection was successful!");
// Find maximum number of clients and operations
// necassary for udp receiving
MaximumClients = mn.GetMaxClients(0);
MaximumOperations = mn.GetMaxOperations(0);
// Create cubes that will represent our players
PlayerCube = new Cube[MaximumClients+1];
// Print our local IP, port and udp mode
Core.Print("The local TCP IP is: " + mn.GetLocalIPTCP(0));
Core.Print("The local TCP port is: " + mn.GetLocalPortTCP(0).ToString());
Core.Print("The local UDP IP is: " + mn.GetLocalIPUDP(0));
Core.Print("The local UDP port is: " + mn.GetLocalPortUDP(0).ToString());
Core.Print("Your client ID is: " + mn.GetClientID(0).ToString());
Core.Print("Press any key to continue");
Core.SuspendForKey();
}
// If the connection timed out
if(Connect == 0)
{
Core.Print("Connection timed out! Check that the server is switched on");
Core.SuspendForKey();
return;
}
// If an error occurred during connection
if(Connect == -1)
{
Core.Print("An error occurred whilst trying to connect");
Core.SuspendForKey();
return;
}
// Setup the world for us to run around in
Core.SyncOn();
Core.SyncRate(40);
DefaultCamera.AutoCamOff();
Matrix maFloor = new Matrix(5000,5000,50,50);
maFloor.Position(DefaultCamera.CurrentPositionX, DefaultCamera.CurrentPositionY - 20, DefaultCamera.CurrentPositionZ);
// Once connected, we loop until we become disconnected or darkgdk tells us to exit
while( (mn.ClientConnected(0,0) == 1) && (Engine.LoopGDK == true) )
{
// Refresh screen
Core.Sync();
// Player movement
if(Keyboard.Up == true){DefaultCamera.MoveForward(Velocity);}
if(Keyboard.Down == true) { DefaultCamera.MoveBackward(Velocity); }
if(Keyboard.Left == true) { DefaultCamera.TurnLeft(TurnSpeed); }
if(Keyboard.Right == true){ DefaultCamera.TurnRight(TurnSpeed);}
// Deal with new messages from the server
// Check for new TCP messages
int iTcpPackets = mn.RecvTCP(0,RecvPacket,0);
// If there is a new TCP message
if(iTcpPackets > 0)
{
// Get operation of new message
// and player that it applies to
int Operation = mn.GetInt(RecvPacket);
int Player = mn.GetInt(RecvPacket);
// If the server is telling us that a new player has joined
// then create a cube for that player
if(Operation == OP_NEWPLAYER)
{
if (PlayerCube[Player] == null)
{
PlayerCube[Player] = new Cube(50);
}
}
// If the server is telling us that a player has left then
// delete the cube of that player
if(Operation == OP_LEFTPLAYER)
{
if (PlayerCube[Player] != null)
{
PlayerCube[Player].Delete();
PlayerCube[Player] = null;
}
}
}
// Check for new UDP messages on a per client per operation basis
// Check each client
for(int Player = 1;Player<=MaximumClients;Player++)
{
// Check each operation for current client
for(int Operation = 0;Operation<MaximumOperations;Operation++)
{
// Check for new UDP messages
int UdpPackets = mn.RecvUDP(0,RecvPacket,Player,Operation);
if (PlayerCube[Player] != null)
{
// If there is a new UDP message
if(UdpPackets == 1)
{
// Get the player's position and angle
// and apply them to his/her cube
float PosX = mn.GetFloat(RecvPacket);
float PosY = mn.GetFloat(RecvPacket);
float PosZ = mn.GetFloat(RecvPacket);
float RotX = mn.GetFloat(RecvPacket);
float RotY = mn.GetFloat(RecvPacket);
float RotZ = mn.GetFloat(RecvPacket);
PlayerCube[Player].Position(PosX,PosY,PosZ);
PlayerCube[Player].Rotate(RotX,RotY,RotZ);
}
}
}
}
// Send our position/angle to the server via UDP
// Formulate packet
mn.AddInt(SendPacket,OP_POSITIONPLAYER);
mn.AddFloat(SendPacket,DefaultCamera.CurrentPositionX);
mn.AddFloat(SendPacket,DefaultCamera.CurrentPositionY);
mn.AddFloat(SendPacket,DefaultCamera.CurrentPositionZ);
mn.AddFloat(SendPacket,DefaultCamera.CurrentAngleX);
mn.AddFloat(SendPacket,DefaultCamera.CurrentAngleY);
mn.AddFloat(SendPacket,DefaultCamera.CurrentAngleZ);
// Send packet
mn.SendUDP(0,SendPacket,0,false,true);
}
// If we have become disconnected from the server
Core.Print("Lost connection to server!");
Core.Sync();
Core.SuspendForKey();
// Close all ports and deallocate all memory
mn.Finish(-1);
mn.DeletePacket(RecvPacket);
mn.DeletePacket(SendPacket);
return;
}
}
}
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using DarkGDK;
namespace DarkGDKApplication1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Start DarkGDK
Engine.InitializeGDK();
// Below used to identify what each packet is supposed to be for
// Tcp
const int OP_NEWPLAYER = 0;
const int OP_LEFTPLAYER = 1;
// Udp
const int OP_POSITIONPLAYER = 0;
// Set the local port of the server, this is the port
// that the server will use for both TCP and UDP
ushort LocalPort = 6789;
// Set the local IP of the server, this is the local IP
// that the server will use for both TCP and UDP
string LocalIP = "";
// Set the maximum number of clients that can be
// connected at any one time
int MaxClients = 50;
// Set the maximum number of UDP operations that will
// be used. We have one, which is OP_POSITIONPLAYER
// so we will set this to one
int MaxOperations = 1;
// Set the UDP mode which decides how UDP packets
// are dealt with; on a per client basis or on a
// per client/per operation basis
sbyte UdpMode = 2;
// Set the number of threads that will be created
// to deal with incoming data. In most cases this
// should be set to the number of processors on your
// computer. MikeNet can determine this for you
// automatically if you set it to 0
int NoThreads = 0;
// Set the number of MikeNet instances to create.
// Each instance can use either mnStartServer or
// mnConnect
int NoInstances = 1;
// Variable to hold the result of a MikeNet command
int Result;
// Create packets to store send/recv data
long RecvPacket = mn.CreatePacket();
long SendPacket = mn.CreatePacket();
mn.SetMemorySize(SendPacket, 1024);
// Start MikeNet
Result = mn.Start(NoInstances, NoThreads);
// If an error occurred starting MikeNet
if (Result == -1)
{
Core.Print("Error starting MikeNet");
Core.SuspendForKey();
return;
}
// Set the local IP and port of the server
// Note: if we did not use this command then MikeNet
// would find a local IP and port to use automatically
Result = mn.SetLocal(0, LocalIP, LocalPort, LocalIP, LocalPort);
// Attempt to start the server
Result = mn.StartServer(0, MaxClients, MaxOperations, UdpMode);
// If started successfully
if (Result == 0)
{
Core.Print("Server started");
Core.Print("");
Core.Print("Server local TCP port: " + mn.GetLocalPortTCP(0).ToString());
Core.Print("Server local UDP port: " + mn.GetLocalPortUDP(0).ToString());
}
// If failed to start
else
{
Core.Print("Server failed to start");
Core.SuspendForKey();
return;
}
// Now that the server is started we will loop checking for new connections
while (Engine.LoopGDK == true)
{
// Use less CPU
Core.Wait(1);
// Check to see if a new client has joined
int Joined = mn.ClientJoined(0);
// If a new client has joined
if (Joined > 0)
{
// Print the client id of the new client
Core.Print("A new client has joined. Client ID is: " + Joined.ToString());
Core.Print("Client TCP IP is: " + mn.GetClientIPTCP(0, Joined));
Core.Print("Client TCP port is: " + mn.GetClientPortTCP(0, Joined).ToString());
Core.Print("Client UDP IP is: " + mn.GetClientIPUDP(0, Joined));
Core.Print("Client UDP port is: " + mn.GetClientPortUDP(0, Joined).ToString());
Core.Print("");
// Tell the new client what clients are currently connected
for (int Client = 1; Client <= MaxClients; Client++)
{
if (mn.ClientConnected(0, Client) == 1)
{
if (Client != Joined)
{
mn.AddInt(SendPacket, OP_NEWPLAYER);
mn.AddInt(SendPacket, Client);
mn.SendTCP(0, SendPacket, Joined, false, false);
}
}
}
// Tell clients that a new client has joined
mn.AddInt(SendPacket, OP_NEWPLAYER);
mn.AddInt(SendPacket, Joined);
mn.SendTCPAll(0, SendPacket, false, false, Joined);
}
// Check to see if any clients have left recently
int Left = mn.ClientLeft(0);
// If a client has left recently
if (Left > 0)
{
// Print the client id of the client who left
Core.Print("Client " + Left.ToString() + " has disconnected");
// Tell clients that a client has left
mn.AddInt(SendPacket, OP_LEFTPLAYER);
mn.AddInt(SendPacket, Left);
mn.SendTCPAll(0, SendPacket, false, false, Left);
}
// Deal with new packets from all clients
for (int Client = 1; Client <= MaxClients; Client++)
{
// Check to see if any new TCP packets have been received
int TcpPackets = mn.RecvTCP(0, RecvPacket, Client);
// If any have been received then do nothing
// since we don't want tcp packets from clients
if (TcpPackets > 0)
{
}
for (int Operation = 0; Operation < MaxOperations; Operation++)
{
// Check to see if any new UDP packets have been received
int UdpPackets = mn.RecvUDP(0, RecvPacket, Client, Operation);
// If any have been received
if (UdpPackets > 0)
{
// Get data from packet
float PosX = mn.GetFloat(RecvPacket);
float PosY = mn.GetFloat(RecvPacket);
float PosZ = mn.GetFloat(RecvPacket);
float RotX = mn.GetFloat(RecvPacket);
float RotY = mn.GetFloat(RecvPacket);
float RotZ = mn.GetFloat(RecvPacket);
// Relay data to clients
// Formulate packet
mn.AddInt(SendPacket, Client);
mn.AddInt(SendPacket, OP_POSITIONPLAYER);
mn.AddFloat(SendPacket, PosX);
mn.AddFloat(SendPacket, PosY);
mn.AddFloat(SendPacket, PosZ);
mn.AddFloat(SendPacket, RotX);
mn.AddFloat(SendPacket, RotY);
mn.AddFloat(SendPacket, RotZ);
// Send packet to all clients
mn.SendUDPAll(0, SendPacket, false, false, Client);
}
}
}
}
// Close all sockets and shutdown MikeNet before exiting
mn.Finish(-1);
mn.DeletePacket(SendPacket);
mn.DeletePacket(RecvPacket);
}
}
}