Jump to content
  • Advertisement
Sign in to follow this  
NLScotty

Server + threading

This topic is 2122 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

I'm coding a small game which connects to my server. I do use this class for it, i'll show you pars of the code.

[/C[code]
public Session Connect(IPAddress[] ip, int port)
{
_socket.Connect(ip, port);
return CreateSession();
}
/// <summary>
/// Connects to a listener
/// </summary>
/// <param name="ip">IPAdress of listener</param>
/// <param name="port">Port of listener</param>
/// <returns>Session connecting to</returns>
public Session Connect(string ip, int port)
{
_socket.Connect(ip, port);
return CreateSession();
}
/// <summary>
/// Creates the session after connecting
/// </summary>
/// <returns>Session created with listener</returns>
private Session CreateSession()
{
Session session = new Session(_socket, SessionType.CLIENT_TO_SERVER);
if (OnClientConnected != null)
OnClientConnected(session);
session.WaitForDataNoEncryption();
return session;
}


/// <summary>
/// Waits for more data to arrive
/// </summary>
public void WaitForData()
{
WaitForData(new SocketInfo(_socket, 4));
}
public void WaitForDataNoEncryption()
{
WaitForData(new SocketInfo(_socket, 2, true));
}
/// <summary>
/// Waits for more data to arrive
/// </summary>
/// <param name="socketInfo">Info about data to be received</param>
private void WaitForData(SocketInfo socketInfo)
{
try
{
_socket.BeginReceive(socketInfo.DataBuffer,
socketInfo.Index,
socketInfo.DataBuffer.Length - socketInfo.Index,
SocketFlags.None,
new AsyncCallback(OnDataReceived),
socketInfo);
}
catch (Exception se)
{
Console.WriteLine("[Error] Session.WaitForData: " + se);
}
}
/// <summary>
/// Data received event handler
/// </summary>
/// <param name="iar">IAsyncResult of the data received event</param>
private void OnDataReceived(IAsyncResult iar)
{
SocketInfo socketInfo = (SocketInfo)iar.AsyncState;
try
{
int received = socketInfo.Socket.EndReceive(iar);
if (received == 0)
{
if (OnClientDisconnected != null)
{
OnClientDisconnected(this);
}
return;
}
socketInfo.Index += received;
if (socketInfo.Index == socketInfo.DataBuffer.Length)
{
switch (socketInfo.State)
{
case SocketInfo.StateEnum.Header:
if (socketInfo.NoEncryption)
{
PacketReader headerReader = new PacketReader(socketInfo.DataBuffer);
short packetHeader = headerReader.ReadShort();
socketInfo.State = SocketInfo.StateEnum.Content;
socketInfo.DataBuffer = new byte[packetHeader];
socketInfo.Index = 0;
WaitForData(socketInfo);
}
else
{
PacketReader headerReader = new PacketReader(socketInfo.DataBuffer);
byte[] packetHeaderB = headerReader.ToArray();
int packetHeader = headerReader.ReadInt();
short packetLength = (short)MapleCrypto.getPacketLength(packetHeader);
if (_type == SessionType.SERVER_TO_CLIENT && !_RIV.checkPacketToServer(BitConverter.GetBytes(packetHeader)))
{
Console.WriteLine("[Error] Packet check failed. Disconnecting client.");
//this.Socket.Close();
}
socketInfo.State = SocketInfo.StateEnum.Content;
socketInfo.DataBuffer = new byte[packetLength];
socketInfo.Index = 0;
WaitForData(socketInfo);
}
break;
case SocketInfo.StateEnum.Content:
byte[] data = socketInfo.DataBuffer;
if (socketInfo.NoEncryption)
{
socketInfo.NoEncryption = false;
PacketReader reader = new PacketReader(data);
short version = reader.ReadShort();
string unknown = reader.ReadMapleString();
_SIV = new MapleCrypto(reader.ReadBytes(4), version);
_RIV = new MapleCrypto(reader.ReadBytes(4), version);
byte serverType = reader.ReadByte();
if (_type == SessionType.CLIENT_TO_SERVER)
{
OnInitPacketReceived(version, serverType);
}
OnPacketReceived(new PacketReader(data));
WaitForData();
}
else
{
_RIV.crypt(data);
MapleCustomEncryption.Decrypt(data);
if (data.Length != 0 && OnPacketReceived != null)
{
OnPacketReceived(new PacketReader(data));
}
WaitForData();
}
break;
}
}
else
{
Console.WriteLine("[Warning] Not enough data");
WaitForData(socketInfo);
}
}
catch (ObjectDisposedException)
{
Console.WriteLine("[Error] Session.OnDataReceived: Socket has been closed");
}

[/code]

In OnDataRecveied I call my own function again which does this

[code]
private void Session_OnPacketReceived(PacketReader packet)
{
GameMessage message = new GameMessage();
message.ID = MESSAGE_ID.RECV_PACKET;
message.pr = packet;

Game.AddMessage(message);
}


I've got a GameLogic class which handles all the 'have to be done' things like this:


public void AddMessage(GameMessage message)
{
lock(m_messages)
m_messages.Enqueue(message);
}

public void CallBack()
{
lock (m_messages)
if (m_messages.Count > 0)
{
GameMessage currentMessage = m_messages.Dequeue();
switch (currentMessage.ID)
{
case MESSAGE_ID.UI_ADD_TO_MESSAGE_VIEW:
m_Instance.instTab.AddMessageToListView(currentMessage.text);
break;
case MESSAGE_ID.RECV_PACKET:
PacketHandler(currentMessage.pr);
break;
case MESSAGE_ID.SEND_PACKET:
m_connection.SendPacket(currentMessage.pw);
break;
case MESSAGE_ID.START_LOGIN:
m_login.InitOne();
break;
case MESSAGE_ID.CONNECT_TO_LOGIN_SERVER:
ConnectToLoginServer();
break;
case MESSAGE_ID.CONNET_TO_CHANNEL:
ConnectToChannel(currentMessage.channel);
break;
}
}
}


This is running in my main thread


private void MainForm_Load(object sender, System.EventArgs e)
{
mainTimer = new Timer();
mainTimer.Interval = 100;
mainTimer.Enabled = true;
mainTimer.Tick += new System.EventHandler(OnTimerEvent);
System.Threading.Thread.CurrentThread.Name = "MainThread";
}
private void OnTimerEvent(object sender, EventArgs e)
{
lock (thisLock)
{
foreach (Instance i in allInstances)
i.maplestory.CallBack();
}
}


My problem is now that, the first time I connect it works fine and i'm connecting to my server, but if I reconnect to a new server, so when I call connection.Connect(new ip, new port); It freezes on _Socket.Connect(); Someone has any idea why this is happening? I believe that my listener is using a new thread, so that's why I use an AddMessage() method, so it can listene fast again. Stil sometimes I random crahses and the socket closes with an error "A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll". [Error] Session.OnDataReceived: Socket has been closed , in the session.private void OnDataReceived(IAsyncResult iar). I hope someone can help me:)

GRz

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!