// Initializes the server by preallocating reusable buffers and // context objects. These objects do not need to be preallocated // or reused, but it is done this way to illustrate how the API can // easily be used to create reusable objects to increase server performance. // public void Initialize() { // receive버퍼만 할당해 놓는다. // send버퍼는 보낼때마다 할당하든 풀에서 얻어오든 하기 때문에. int pre_alloc_count = 1; var totalBytes = ServerOpt.MaxConnectionCount * ServerOpt.ReceiveBufferSize * pre_alloc_count; BufferManager buffer_manager = new BufferManager(totalBytes, ServerOpt.ReceiveBufferSize); // Allocates one large byte buffer which all I/O operations use a piece of. This gaurds // against memory fragmentation buffer_manager.InitBuffer(); ReceiveEventArgsPool = new SocketAsyncEventArgsPool(); SendEventArgsPool = new SocketAsyncEventArgsPool(); // preallocate pool of SocketAsyncEventArgs objects SocketAsyncEventArgs arg; for (int i = 0; i < ServerOpt.MaxConnectionCount; i++) { // 더이상 UserToken을 미리 생성해 놓지 않는다. // 다수의 클라이언트에서 접속 -> 메시지 송수신 -> 접속 해제를 반복할 경우 문제가 생김. // 일단 on_new_client에서 그때 그때 생성하도록 하고, // 소켓이 종료되면 null로 세팅하여 오류 발생시 확실히 드러날 수 있도록 코드를 변경한다. // receive pool { //Pre-allocate a set of reusable SocketAsyncEventArgs arg = new SocketAsyncEventArgs(); arg.Completed += new EventHandler <SocketAsyncEventArgs>(ReceiveCompleted); arg.UserToken = null; // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object buffer_manager.SetBuffer(arg); // add SocketAsyncEventArg to the pool ReceiveEventArgsPool.Push(arg); } // send pool { //Pre-allocate a set of reusable SocketAsyncEventArgs arg = new SocketAsyncEventArgs(); arg.Completed += new EventHandler <SocketAsyncEventArgs>(SendCompleted); arg.UserToken = null; // send버퍼는 보낼때 설정한다. SetBuffer가 아닌 BufferList를 사용. arg.SetBuffer(null, 0, 0); // add SocketAsyncEventArg to the pool SendEventArgsPool.Push(arg); } } ReserveClosingProc.Start(ServerOpt.ReserveClosingWaitMilliSecond); }
public void OnSessionClosed(Session token) { SessionMgr.Remove(token); // Free the SocketAsyncEventArg so they can be reused by another client // 버퍼는 반환할 필요가 없다. SocketAsyncEventArg가 버퍼를 물고 있기 때문에 // 이것을 재사용 할 때 물고 있는 버퍼를 그대로 사용하면 되기 때문이다. if (ReceiveEventArgsPool != null) { ReceiveEventArgsPool.Push(token.ReceiveEventArgs); } if (SendEventArgsPool != null) { SendEventArgsPool.Push(token.SendEventArgs); } token.SetEventArgs(null, null); }