void ProcessAccept(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.OperationAborted) { Stop(); return; } try { // create SocketAsyncEventArgs for this client SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += IO_Completed; args.UserToken = new AsyncUserToken(); // assign chunk of big buffer for max performance (see BigBuffer.cs comments) if (bigBuffer.Assign(args)) { // Get the socket for the accepted client connection and put it into the //ReadEventArg object user token AsyncUserToken userToken = (AsyncUserToken)args.UserToken; userToken.Socket = e.AcceptSocket; userToken.ConnectTime = DateTime.Now; userToken.Remote = e.AcceptSocket.RemoteEndPoint; userToken.IpAddress = ((IPEndPoint)(e.AcceptSocket.RemoteEndPoint)).Address; userToken.connectionId = NextConnectionId(); clients[userToken.connectionId] = userToken; OnClientConnected(userToken); if (!e.AcceptSocket.ReceiveAsync(args)) { ProcessReceive(args); } } else { Debug.LogError("Server.ProcessAccept: failed to assign buffer."); } } catch (Exception exception) { Debug.LogError("Server.ProcessAccept failed: " + exception); } StartAccept(e); }
void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; clients.TryRemove(token.connectionId, out AsyncUserToken temp); // close the socket associated with the client try { token?.Socket.Shutdown(SocketShutdown.Both); } catch (Exception) { } token?.Socket.Close(); // call disconnected event OnClientDisconnected(token); // free buffer chunk bigBuffer.Free(e); }
public void Stop() { foreach (KeyValuePair <int, AsyncUserToken> kvp in clients) { AsyncUserToken token = kvp.Value; try { token.Socket.Shutdown(SocketShutdown.Both); OnClientDisconnected(token); } catch (Exception) { } } try { listenSocket?.Shutdown(SocketShutdown.Both); } catch (Exception) { } listenSocket?.Close(); this.Active = false; clients.Clear(); }
void OnReceiveClientData(AsyncUserToken token, byte[] data) { messageQueue.Enqueue(new Message(token.connectionId, EventType.Data, data)); }
// This method is invoked when an asynchronous receive operation completes. // If the remote host closed the connection, then the socket is closed. protected override void ProcessReceive(SocketAsyncEventArgs e) { try { // check if the remote host closed the connection AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { ArraySegment <byte> data = new ArraySegment <byte>(e.Buffer, e.Offset, e.BytesTransferred); // write it all into our memory stream first token.buffer.Write(e.Buffer, e.Offset, e.BytesTransferred); // keep trying headers (we might need to process >1 message) while (token.buffer.Position >= 4) { // we can read a header. so read it. long bufferSize = token.buffer.Position; token.buffer.Position = 0; byte[] header = new byte[4]; // TODO cache token.buffer.Read(header, 0, header.Length); int contentSize = Utils.BytesToIntBigEndian(header); // avoid -1 attacks from hackers if (contentSize > 0) { // enough content to finish the message? if (bufferSize - token.buffer.Position >= contentSize) { // read content byte[] content = new byte[contentSize]; token.buffer.Read(content, 0, content.Length); // process message OnReceiveClientData(token, content); // read what's left in the buffer. this is valid // data that we received at some point. can't lose // it. byte[] remainder = new byte[bufferSize - token.buffer.Position]; token.buffer.Read(remainder, 0, remainder.Length); // write it to the beginning of the buffer. this // sets position to the new true end automatically. token.buffer.Position = 0; token.buffer.Write(remainder, 0, remainder.Length); } // otherwise we just need to receive more. else { break; } } else { CloseClientSocket(e); Debug.LogWarning("Server.ProcessReceive: received negative contentSize: " + contentSize + ". Maybe an attacker tries to exploit the server?"); } } // continue receiving if (!token.Socket.ReceiveAsync(e)) { ProcessReceive(e); } } else { CloseClientSocket(e); } } catch (Exception exception) { CloseClientSocket(e); Debug.LogError("Server.ProcessReceive failed: " + exception); } }
void OnClientDisconnected(AsyncUserToken token) { messageQueue.Enqueue(new Message(token.connectionId, EventType.Disconnected, null)); }