public GameUser(CustomUserToken token) { m_token = token; m_token.SetPeer(this); m_packetHandler = new PacketHandler(token); }
private void OnProcessReceive(SocketAsyncEventArgs e) { CustomUserToken token = e.UserToken as CustomUserToken; if (e.BytesTransferred > 0 && SocketError.Success == e.SocketError) { // e.Buffer == 클라이언트로부터 수신한 데이터 원본 바이트 배열 // e.Offset == 버퍼 포지션. 즉, 데이터의 시작위치를 나타내는 정수값 // e.BytesTransferred == 수신된 바이트 사이즈 정수 token.OnReceive(e.Buffer, e.Offset, e.BytesTransferred); // 수신한 뒤 ReceiveAsync 재호출 // 한번의 ReceiveAsync로는 모든 데이터를 다 받기 힘들다. 클라이언트 송신이 한번 쉬어지거나, // 통신 환경 등에 의해 잘개 쪼개어져 여러번 송신할 수 있기 때문. bool pending = token.m_sock.ReceiveAsync(e); if (!pending) { OnProcessReceive(e); } } else { Console.WriteLine($"error {e.SocketError}, transferred {e.BytesTransferred}"); OnCloseClientSocket(token); } }
static void OnSessionCreated(CustomUserToken token) { GameUser user = new GameUser(token); lock (m_lock) { m_userList.Add(user); } }
public async Task AddUserTokenAsync(CustomUserToken userToken) { if (!_configuration.Value.AllowMultipleLoginsFromTheSameUser) { await InvalidateUserTokensAsync(userToken.UserId); } await DeleteTokensWithSameRefreshTokenSourceAsync(userToken.RefreshTokenIdHashSource); _tokens.Add(userToken); }
private void OnCloseClientSocket(CustomUserToken token) { token.OnRemove(); // EventArgs를 풀에 반환한다. // 버퍼는 반환하지 않는다. 어짜피 다음에 재사용할때 물고있던 버퍼를 그대로 사용할 수 있기 때문 if (null != m_receiveEventArgsPool) { m_receiveEventArgsPool.Push(token.m_receiveArgs); } if (null != m_sendEventArgsPool) { m_sendEventArgsPool.Push(token.m_sendArgs); } }
public async Task AddUserTokenAsync(User user, string refreshTokenSerial, string accessToken, string refreshTokenSourceSerial) { var now = DateTimeOffset.UtcNow; var token = new CustomUserToken { UserId = user.Id, // Refresh token handles should be treated as secrets and should be stored hashed RefreshTokenIdHash = _securityService.GetSha256Hash(refreshTokenSerial), RefreshTokenIdHashSource = string.IsNullOrWhiteSpace(refreshTokenSourceSerial) ? null : _securityService.GetSha256Hash(refreshTokenSourceSerial), AccessTokenHash = _securityService.GetSha256Hash(accessToken), RefreshTokenExpiresDateTime = now.AddMinutes(_configuration.Value.RefreshTokenExpirationMinutes), AccessTokenExpiresDateTime = now.AddMinutes(_configuration.Value.AccessTokenExpirationMinutes) }; await AddUserTokenAsync(token); }
public void Init() { m_maxConnection = 10000; m_bufferSize = 1024; // 동시커넥션 할 클라이언트 갯수 * 클라이언트별 패킷 버퍼의 사이즈 * 미리 잡아놓을 풀 사이즈 // 풀 사이즈는 read, write 총 2개 m_bufferManager = new BufferManager(m_maxConnection * m_bufferSize * m_preAllocCount, m_bufferSize); m_receiveEventArgsPool = new SocketAsyncEventArgsPool(m_maxConnection); m_sendEventArgsPool = new SocketAsyncEventArgsPool(m_maxConnection); m_bufferManager.InitBuffer(); SocketAsyncEventArgs args; for (int i = 0; i < m_maxConnection; i++) { // 동일한 소켓에 send 및 receive // 유저 토큰은 클라이언트 세션 당 한개 생성 후 // 각 eventArgs에서 동일한 토큰을 가지게 한 후 참조하도록 함 CustomUserToken token = new CustomUserToken(); { // receive pool args = new SocketAsyncEventArgs(); args.Completed += new EventHandler <SocketAsyncEventArgs>(OnReceiveCompleted); args.UserToken = token; m_bufferManager.SetBuffer(args); m_receiveEventArgsPool.Push(args); } { // send pool args = new SocketAsyncEventArgs(); args.Completed += new EventHandler <SocketAsyncEventArgs>(OnSendCompleted); args.UserToken = token; m_bufferManager.SetBuffer(args); m_sendEventArgsPool.Push(args); } } }
public void OnConnectCompleted(Socket sock, CustomUserToken token) { // Send, Receive때와 달리, 풀을 사용하지 않고 바로 할당해준다. // 풀링은 서버 -> 클라 통신에 사용하기 위해 만든 것이고, // 클라이언트 -> 서버는 EventArgs가 2개밖에 필요하지 않기 때문에 그냥 할당해서 써준다. // 이는 서버간 연결시에도 동일 (분산 프로세스 서버 기준) SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs(); receiveArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnReceiveCompleted); receiveArgs.UserToken = token; receiveArgs.SetBuffer(new byte[1024], 0, 1024); SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs(); sendArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnSendCompleted); sendArgs.UserToken = token; sendArgs.SetBuffer(new byte[1024], 0, 1024); OnBeginReceive(sock, receiveArgs, sendArgs); }
private void OnBeginReceive(Socket cliSock, SocketAsyncEventArgs receiveArgs, SocketAsyncEventArgs sendArgs) { // 전체적인 구조는 Aceept와 유사함 // receive, send 둘 중 아무거나 선택해도 됨. 어짜피 userToken은 같은 것 CustomUserToken token = receiveArgs.UserToken as CustomUserToken; token.SetEventArgs(receiveArgs, sendArgs); // 생성된 클라이언트 소켓을 보관, 통신 시 사용 token.m_sock = cliSock; // 데이터 수신용 메서드 호출 // 비동기 수신 시 스레드 대기 중에 있다가 Completed에 더해준 메서드가 호출 // 동기 완료 시 직접 호출 bool pending = cliSock.ReceiveAsync(receiveArgs); if (!pending) { OnProcessReceive(receiveArgs); } }
private void OnNewClient(Socket cliSock, object token) { Interlocked.Increment(ref m_connectedCount); Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] A client connected. handle : {cliSock.Handle}, count : {m_connectedCount}"); // 이벤트 풀에서 꺼내와 사용 SocketAsyncEventArgs receiveArgs = m_receiveEventArgsPool.Pop(); SocketAsyncEventArgs sendArgs = m_sendEventArgsPool.Pop(); // SocketAsyncEventArgs를 생성할 때 만들어두었던 UserToken를 콜백 메서드의 패러미터로 넣어줌. CustomUserToken userToken = null; if (m_sessionCreateCallback != null) { userToken = receiveArgs.UserToken as CustomUserToken; m_sessionCreateCallback(userToken); } // 클라이언트로부터 데이터를 수신 대기 OnBeginReceive(cliSock, receiveArgs, sendArgs); }
private void OnSendCompleted(object sender, SocketAsyncEventArgs e) { CustomUserToken token = e.UserToken as CustomUserToken; token.OnProcessSend(e); }
public void AddUserToken(CustomUserToken userToken) { _tokens.Add(userToken); _uow.SaveChanges(); }
public PacketHandler(CustomUserToken token) { m_token = token; }