Answer the question
In order to leave comments, you need to log in
How to implement a game server in c#?
Hello! Can anyone explain how to implement a game server in C#. Its task is to keep connected users, when the user sends a message to the server, the server must send the message to the connected users.
After many hours of googling and lots of examples, there are two console applications - GameServer and TestService.
The idea was this: the client connects using the TcpClient.Connect () method, respectively, on the server it is caught using TcpListener.Accept (). The client is stored on the server - data is read from its TcpClient().GetStream() stream using BeginRead(), and when read, it can be written to the NetworkStream of other clients.
Something went wrong:
TestService was able to connect and send ONE! message and receive a response from the server, after that the TcpClient.Connected property became false from the TestService side, so I can no longer use this TcpClient instance, but I need messages from the server to come to its stream. From the server side, the BeginRead method, after receiving one message, starts reading empty messages endlessly.
Server - only the start method, because only it is implemented
public void Start()
{
try
{
TcpListener tcpListener = new TcpListener(IPAddress.Parse(ipAddress), port);
tcpListener.Start();
ServerLogger.Log("Server has been started");
while(true)
{
TcpClient client = tcpListener.AcceptClient();
GameConnections.Add(new GameConnection(client, GameConnections.Count));
}
}
catch(Exception ex)
{
ServerLogger.Error(ex.Message);
}
}
class GameConnection
{
string GameID { get; set; }
string ConnectionID { get; set; }
TcpClient Client { get; set; }
byte[] acceptedData = new byte[1024];
byte[] sendData = new byte[1024];
byte[] buffer = new byte[1024];
NetworkStream stream;
static void HandleNewClient()
{
}
public GameConnection(TcpClient client, int id)
{
Client = client;
stream = client.GetStream();
ConnectionID = "connection" + id;
ServerLogger.Log(string.Format("Client connected. ConnectionID: {1}", GameID, ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, FirstReadCallback, null);
}
public void FirstReadCallback(IAsyncResult ar)
{
int bytesRead = stream.EndRead(ar);
if(bytesRead > 0)
{
Console.WriteLine(bytesRead);
GameID = Encoding.UTF8.GetString(acceptedData, 0, bytesRead);
Console.WriteLine("Game id - " + GameID);
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
ServerLogger.Log(String.Format("{0} game id is {1}", ConnectionID, GameID));
}else
{
ServerLogger.Log(String.Format("Empty first read from client({0})", ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, FirstReadCallback, null);
}
}
public void ReadCallback(IAsyncResult ar)
{
int bytesRead = stream.EndRead(ar);
if(bytesRead > 0)
{
string command = Encoding.UTF8.GetString(acceptedData, 0, bytesRead);
ServerLogger.Log(String.Format("Command from client({0}): {1}", ConnectionID, command));
string serverAnswer = "some game command";
Encoding.UTF8.GetBytes(serverAnswer, 0, serverAnswer.Length, sendData, 0);
stream.Write(sendData, 0, serverAnswer.Length);
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
}
else
{
ServerLogger.Log(String.Format("Empty read from client({0})", ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
}
}
}
class Program
{
static void Main(string[] args)
{
TcpClient client = new TcpClient();
try
{
Console.WriteLine("Connecting to server");
client.Connect(IPAddress.Parse("127.0.0.1"), 8888);
using (BinaryWriter writer = new BinaryWriter(client.GetStream()))
{
byte[] data = new byte[1024];
string gameID = "1000";
Encoding.UTF8.GetBytes(gameID, 0, gameID.Length, data, 0);
writer.Write(data, 0, gameID.Length);
Console.WriteLine(Encoding.UTF8.GetString(data, 0, gameID.Length));
}
while (true)
{
string command = Console.ReadLine();
if (command == "exit") break;
byte[] data = new byte[1024];
NetworkStream stream = client.GetStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(command);
}
using (BinaryReader reader = new BinaryReader(stream))
{
reader.Read(data, 0, 1024);
Console.WriteLine("Server answer: {0}", Encoding.UTF8.GetString(data));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
client.Close();
}
Console.ReadLine();
}
}
Answer the question
In order to leave comments, you need to log in
1. Look at the timeout on the server and client, because most likely, after the message is sent, the socket is closed by timeout;
2. It is necessary to implement a mechanism for polling the server for new messages within a certain time interval, which, of course, is less than the timeout. For example, the client sends an ASK command after 100 ms, and the server responds with Empty. If the client does not respond within a certain time, then we close it so as not to waste memory.
3. I would exchange with the server via json or byte-serializable structures, otherwise you will be tormented as the logic becomes more complicated.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question