private void ReleaseSocket(AsyncSocket socket)
        {
            //TODO 구현이 좀 이상한듯
            lock (this)
            {
                int iocount = socket.ExitIO();

                if (0 == iocount)
                {
                    // 이 경우에는 Dispose()를 위해 Close()할 필요는 없다?
                    //socket.tcpclient.GetStream().Close();
                    //socket.tcpclient.Close();
                    //socket.sendlist.Clear();
                    // 객체파괴가 어떻게 일어날지 모르니, desc는 값을 복사해서 사용하자.
                    Sockets.Remove(socket.Description.ManagedID);
                    AsyncSocketContext desc = new AsyncSocketContext();
                    desc.UniqueId  = socket.Description.UniqueId;
                    desc.ManagedID = socket.Description.ManagedID;
                    desc.NetSender = socket.Description.NetSender;

                    // socket에 대해 메모리 풀링이 필요하다면, clone()과 아래 함수가 풀링에 대해 어떻게 처리할지 담당하면된다.
                    //  socket이 구체적으로 어떤 타입인지에 따라 풀링매니저가 달라져야 하기 때문에, asio계층에선 담당하지 않는다.
                    NetReceiver.OnReleaseSocket(desc, socket);
                }
            }
        }
        public int DisconnectSocket(AsyncSocketContext sockdesc)
        {
            lock (this)
            {
                // 단순히 Close하면되는것인가?
                // bugfix 찾지못한경우 널이 반환되는게 아니라 예외가 던져진다.
                // theSockets만 쓰레드컨트롤하면된다.
                AsyncSocket aSocket;
                try
                {
                    aSocket = Sockets[sockdesc.ManagedID];
                }
                catch (Exception /*ex*/)
                {
                    return((int)MyErrorCode.NoSuchSocket);
                }

                if (aSocket.Description.UniqueId != sockdesc.UniqueId)
                {
                    return((int)MyErrorCode.NoSuchSocket);
                }

                aSocket.TCPClient.GetStream().Close();
                aSocket.TCPClient.Close();
            }
            return(0);
        }
 public AsyncSocket()
 {
     IOCount               = 0;
     Description           = new AsyncSocketContext();
     Description.NetSender = null;
     Description.ManagedID = AsyncSocket.RetrieveUID();
     Description.UniqueId  = AsyncSocket.GenerateUniqueSequenceId();
 }
        // 받은 내용을 어떻게 처리할지는 이 함수를 재정의해서 처리하시오!
        public virtual void HandleReceived(int length, byte[] data, int offset, INetworkReceiver receiver)
        {
            //TODO 구현이 좀 이상한듯
            // 보통 아래 receiver.notifyMessage 함수에서 프로토콜에 맞는 객체를 생성하면 될것이다.
            //  생성은 쓰레드제어없이 가능하게하고, enqueuing을 쓰레드제어하면 된다.
            // 객체파괴가 어떻게 일어날지 모르니, desc는 값을 복사해서 사용하자.
            AsyncSocketContext desc = new AsyncSocketContext();

            desc.UniqueId  = Description.UniqueId;
            desc.ManagedID = Description.ManagedID;
            desc.NetSender = Description.NetSender;
            receiver.OnReceiveData(desc, length, data, offset);
        }
        // c#에선 TcpListener.AcceptTcpClient가 반환하는 TcpClient객체레퍼런스를 넘겨줘야한다.
        //  즉 c++에선 int 값을 넘겨줬지만, c#에선 TcpClient 이 객체를 기본 베이스로 사용해야 한다.
        public int RegisterSocket(TcpClient acceptedclient)
        {
            lock (this)
            {
                var aSocket = new AsyncSocket();
                aSocket.SetTcpClient(acceptedclient);
                aSocket.Description.NetSender = this;

                // 관리리스트에 등록 - need lock
                Sockets.Add(aSocket.Description.ManagedID, aSocket);

                //TODO 구현이 좀 이상한듯
                // 리시버에게 객체파괴가 어떻게 일어날지 모르니, desc는 값을 복사해서 사용하자.
                AsyncSocketContext desc = new AsyncSocketContext();
                desc.UniqueId  = aSocket.Description.UniqueId;
                desc.ManagedID = aSocket.Description.ManagedID;
                desc.NetSender = aSocket.Description.NetSender;
                NetReceiver.OnRegisterSocket(desc, aSocket.RemoteAddress);

                aSocket.EnterIO();

                // key saea얻어오기 실패하면 메모리부족이기 때문에, 프로세스를 죽여야한다.
                SocketAsyncEventArgs readEventArgs = IOManager.RetreiveEventArgs();// new SocketAsyncEventArgs();//= saeaPool.pop(); // saeaPool from the ASIOManager

                try
                {
                    readEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed);
                    readEventArgs.UserToken  = aSocket;
                    bool willRaiseEvent = aSocket.TCPClient.Client.ReceiveAsync(readEventArgs);
                    if (!willRaiseEvent)
                    {
                        ProcessReceive(readEventArgs);
                        // 위에서 releaseSocket이 되면, 아래 예외처리는 수행되지 않는다.
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(DateTime.Now.ToString() + " - registerSocket " + ex.Message);
                    // releasesocket을 수정하지 말고 각 문맥에서 releaseSAEA를 호출하자
                    if (null != readEventArgs)
                    {
                        readEventArgs.Completed -= IO_Completed;
                        IOManager.ReleaseSAEA(readEventArgs);
                    }
                    ReleaseSocket(aSocket);
                }
            }

            return(0);
        }
        private void ResultConnect(IAsyncResult ar)
        {
            ConnectFrame       connectFrame = (ar.AsyncState as ConnectFrame);
            AsyncSocketContext desc         = new AsyncSocketContext();

            desc.UniqueId  = connectFrame.Socket.Description.UniqueId;
            desc.ManagedID = connectFrame.Socket.Description.ManagedID;
            desc.NetSender = connectFrame.Socket.Description.NetSender;

            try
            {
                connectFrame.Socket.TCPClient.EndConnect(ar);
                NetReceiver.OnConnectingResult(connectFrame.ReqID, desc, true, null);

                connectFrame.Socket.EnterIO();

                SocketAsyncEventArgs readEventArgs = IOManager.RetreiveEventArgs();// new SocketAsyncEventArgs();//= saeaPool.pop(); // saeaPool from the ASIOManager
                try
                {
                    readEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed);
                    readEventArgs.UserToken  = connectFrame.Socket;
                    bool willRaiseEvent = connectFrame.Socket.TCPClient.Client.ReceiveAsync(readEventArgs);
                    if (!willRaiseEvent)
                    {
                        ProcessReceive(readEventArgs);
                        // 위에서 releaseSocket이 되면, 아래 예외처리는 수행되지 않는다.
                    }
                }
                catch (Exception /*ex*/)
                {
                    // releasesocket을 수정하지 말고 각 문맥에서 releaseSAEA를 호출하자
                    if (null != readEventArgs)
                    {
                        readEventArgs.Completed -= IO_Completed;
                        IOManager.ReleaseSAEA(readEventArgs);
                    }
                    ReleaseSocket(connectFrame.Socket);
                }
            }
            catch (Exception ex)
            {
                lock (this)
                {
                    Sockets.Remove(desc.ManagedID);
                }
                NetReceiver.OnConnectingResult(connectFrame.ReqID, desc, false, ex);
                connectFrame.Socket.TCPClient = null;
            }
        }
        public int PostingSend(AsyncSocketContext sockdesc, int length, byte[] data)
        {
            //TODO 최대한 lock을 안 잡도록 해보자
            // postingSend, ReleaseSocket(다른 워커쓰레드에서 ResultRead, ResultWrite에서 을 쓰레드락걸지 않으면,
            //  aSocket.sendlist를 위해서라도 락을 걸어야한다.
            lock (this)
            {
                // bugfix 찾지못한경우 널이 반환되는게 아니라 예외가 던져진다.
                AsyncSocket aSocket;
                try
                {
                    aSocket = Sockets[sockdesc.ManagedID];
                }
                catch (Exception /*ex*/)
                {
                    return((int)MyErrorCode.NoSuchSocket);
                }

                if (aSocket.Description.UniqueId != sockdesc.UniqueId)
                {
                    return((int)MyErrorCode.NoSuchSocket);
                }

                // asiomanager 생성시 io 크기보다 큰 센드 요청은 할수 없다.
                if (IOManager.IOMAXSIZE < length || 0 >= length)
                {
                    return((int)MyErrorCode.SizeError);
                }


                // sendlist쓰지말고 곧바로 보내버리자!!!
                SocketAsyncEventArgs writeEventArgs = IOManager.RetreiveEventArgs();
                if (null == writeEventArgs)
                {
                    // temp code critical outofmemory
                    return((int)MyErrorCode.OutOfMemory);
                }

                aSocket.EnterIO();

                try
                {
                    // send의 경우 setbuffer 자체가 보낼 버퍼를 지정하는것이다... setbuffer를 다시한번해서 하는게 안전할까?
                    writeEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed);
                    writeEventArgs.SetBuffer(writeEventArgs.Buffer, writeEventArgs.Offset, length);
                    Array.Copy(data, 0, writeEventArgs.Buffer, writeEventArgs.Offset, length);
                    writeEventArgs.UserToken = aSocket;

                    bool willRaiseEvent = aSocket.TCPClient.Client.SendAsync(writeEventArgs);

                    if (!willRaiseEvent)
                    {
                        ProcessSend(writeEventArgs);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(DateTime.Now.ToString() + " - postingSend " + ex.Message);

                    if (null != writeEventArgs)
                    {
                        writeEventArgs.Completed -= IO_Completed;
                        IOManager.ReleaseSAEA(writeEventArgs);
                    }

                    ReleaseSocket(aSocket);
                }
            }
            return(0);
        }
 public int ReleaseAsyncSocketContext(AsyncSocketContext sockdesc)
 {
     AsyncSocket.ReleaseUID(sockdesc.ManagedID);
     return(0);
 }