I have an asynchronous server installed, it works fine, connecting, receiving and sending a message to the communication client.
The server itself is a Game-World-Server (mmorpg style). When a user sends his location to where he is, I need to click this for all clients using PlayerPositionNotice. I know that the basic material is missing here, but when I try to save the StateObject that was created in the accept method and use this socket to send information to the player at any given time, it fails because the socket is closed. = / I donโt know why this is happening, and I would look for a couple of engines, but returned empty.
This is how I created my server:
First we have global stuff:
public StateManager _stateManager = new StateManager(); public bool IsClosing = false; private const int _port = 1025; private IPHostEntry _localhost; private IPEndPoint _endpoint; private Socket _serverSocket; private Thread _serverThread;
Secondly, we initialize the material:
public void Start() { _serverThread = new Thread(Initialize); _serverThread.Start(); }
So far so good, I expect .. And now for the rest of the server class.
private void acceptCallback(IAsyncResult result) { Console.WriteLine("Connection Accepted"); StateObject state = null; try { state = new StateObject { workSocket = ((Socket)result.AsyncState).EndAccept(result) }; _stateManager.AddConnection(state); state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), state); _serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket); } catch (SocketException) { _stateManager.RemoveConnection(state); _serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket); } catch (Exception) { _stateManager.RemoveConnection(state); _serverSocket.BeginAccept(new AsyncCallback(acceptCallback), _serverSocket); } } private void receiveCallback(IAsyncResult result) { var state = (StateObject)result.AsyncState; try { // Buffer and count bytes read int bytesRead = state.workSocket.EndReceive(result); if (!state.workSocket.Connected) _stateManager.RemoveConnection(state); if (bytesRead > 0) { // Parse the message to the protocol manager and return a reply var replyingData = ProtocolManager.Parse(state.buffer); if (replyingData != null) Send(replyingData, state); //Queue the next receive state.workSocket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), state); } else { _stateManager.RemoveConnection(state); } } catch (SocketException e) { _stateManager.RemoveConnection(state); } } public bool Send(byte[] message, StateObject state) { Console.WriteLine("Sending " + message.Length + " bytes"); if (state != null && state.workSocket.Connected) { lock (state.workSocket) { //we use a blocking mode send, no async on the outgoing //since this is primarily a multithreaded application, shouldn't cause problems to send in blocking mode state.workSocket.Send(message, message.Length, SocketFlags.None); } } else return false; return true; }
StateManager contains a list of StateObjects. Below you can see how I create them.
STATE MANAGER:
public class StateManager { private List<StateObject> _connections = new List<StateObject>(); public void AddConnection(StateObject so) { lock (_connections) { _connections.Add(so); } } public void RemoveConnection(StateObject so) { if (so.workSocket != null) { so.workSocket.Close(); lock (_connections) { _connections.Remove(so); } } } }
STATE OBJECT
public class StateObject { public Socket workSocket = null; public const int BufferSize = 1024; public byte[] buffer = new byte[BufferSize]; public StringBuilder sb = new StringBuilder(); }
My problem is that whenever someone from this list sends something, I want to send a notification about all other clients. How and where can I implement this? Can anyone hit me in the right direction? =)