예제 #1
0
        private void Close(bool socketDisposed)
        {
            if (beginClosing)
            {
                return;
            }

            lock (interLocker)
            {
                if (status == TCPClient.ClientStatus.Closed)
                {
                    return;
                }

                if (status == TCPClient.ClientStatus.Connecting)
                {
                    requireClose = true;

                    if (connectingCanBeCannelled)
                    {
                        CannelConnecting();
                    }

                    return;
                }

                status       = TCPClient.ClientStatus.Closed;
                beginClosing = true;
            }

            InternalClose(true, false, socketDisposed, false);
        }
예제 #2
0
        private void InternalClose(bool callCloseEvent, bool causedByError, bool socketDisposed, bool checkReClosing)
        {
            if (checkReClosing)
            {
                lock (interLocker)
                {
                    if (status == TCPClient.ClientStatus.Closed)
                    {
                        return;
                    }

                    status = TCPClient.ClientStatus.Closed;
                }
            }

            CleanForClose(callCloseEvent, causedByError);

            if (socketDisposed)
            {
                socket.Close();
                return;
            }

            SocketAsyncEventArgs closeAsyncEventArgs = new SocketAsyncEventArgs {
                RemoteEndPoint = endpoint
            };

            closeAsyncEventArgs.Completed += IO_Completed;

            try
            {
                if (!socket.DisconnectAsync(closeAsyncEventArgs))
                {
                    FinallyShutdownClose();
                }

                return;
            }
            catch (SocketException e)
            {
                if (errorRecorder != null)
                {
                    errorRecorder.RecordError("Internal closing failed. SocketException means accessing socket is failed.", e);
                }

                socket.Close();
            }
            catch (ObjectDisposedException)
            {
                socket.Close();
            }
        }
예제 #3
0
        //----------------[ Constructor ]-----------------------//

        public TCPConnection(EndPoint endpoint)
        {
            interLocker              = new object();
            this.endpoint            = endpoint;
            status                   = TCPClient.ClientStatus.Closed;
            beginClosing             = false;
            requireClose             = false;
            connectingCanBeCannelled = false;

            socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
            receiveAsyncEventArgs = new SocketAsyncEventArgs {
                RemoteEndPoint = endpoint
            };
            receiveAsyncEventArgs.Completed += IO_Completed;

            currSendOffset     = 0;
            currSendBuffer     = null;
            sendQueue          = new Queue <byte[]>();
            callbackTimeoutMap = new Dictionary <Int64, HashSet <AnswerCallbackUnit> >();
            callbackSeqNumMap  = new Dictionary <UInt32, AnswerCallbackUnit>();
        }
예제 #4
0
        private void CloseWhenConnectingError()
        {
            ClientEngine.UnregisterConnection(this);

            lock (interLocker)
            {
                if (status == TCPClient.ClientStatus.Closed)
                {
                    return;
                }

                status       = TCPClient.ClientStatus.Closed;
                beginClosing = true;
            }

            CallConnectionConnectedDelegate(0, false, "Connecting failed event exception. Remote endpoint: " + endpoint + ".");
            connectionCloseDelegate = null;

            ClearAllCallback(ErrorCode.FPNN_EC_CORE_INVALID_CONNECTION);

            socket.Close();
        }
예제 #5
0
        private void ConnectCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError != SocketError.Success)
            {
                if (errorRecorder != null && !requireClose)
                {
                    errorRecorder.RecordError("Connect to " + endpoint + " failed. Due to SocketError: " + e.SocketError);
                }

                CloseWhenConnectingError();
                return;
            }

            if (requireClose)
            {
                CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + ".");
                connectionCloseDelegate = null;
                Close();
                return;
            }

            receiveAsyncEventArgs.SetBuffer(receiver.buffer, receiver.offset, receiver.requireLength - receiver.offset);
            connectionId = socket.Handle.ToInt64();

            CallConnectionConnectedDelegate(connectionId, true, "Connected event exception. Remote endpoint: " + endpoint + ".");

            lock (interLocker)
            {
                status = TCPClient.ClientStatus.Connected;
            }

            if (requireClose)
            {
                Close();
                return;
            }

            if (ClientEngine.RegisterConnectedConnection(this) == false)
            {
                Close();
                return;
            }

            CheckSending();

            try
            {
                if (!socket.ReceiveAsync(receiveAsyncEventArgs))
                {
                    ReceiveCompleted(socket, receiveAsyncEventArgs);
                }
            }
            catch (ObjectDisposedException ex)
            {
                CloseByException("Receive data from " + endpoint + " exception. Connection is broken.", ex, true);
            }
            catch (SocketException ex)
            {
                CloseByException("Receive data from " + endpoint + " exception. Access socket is error.", ex, false);
            }
        }
예제 #6
0
        //----------------[ I/O Operations ]-----------------------//

        public void AsyncConnect(int connectTimeout)
        {
            lock (interLocker)
            {
                if (status != TCPClient.ClientStatus.Closed)
                {
                    return;
                }

                status = TCPClient.ClientStatus.Connecting;
            }

            if (ClientEngine.RegisterConnectingConnection(this, connectTimeout) == false)
            {
                lock (interLocker)
                {
                    status       = TCPClient.ClientStatus.Closed;
                    beginClosing = true;
                }

                CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + ".");
                connectionCloseDelegate = null;
                socket.Close();
                return;
            }

            connectionId       = 0;
            receiver           = new StandardReceiver();
            sendAsyncEventArgs = new SocketAsyncEventArgs {
                RemoteEndPoint = endpoint
            };
            sendAsyncEventArgs.Completed += IO_Completed;

            recursionDeepOfReceiveFunction = 0;
            recursionDeepOfSendFunction    = 0;

            try
            {
                if (!socket.ConnectAsync(receiveAsyncEventArgs))      //-- Synchronous
                {
                    ConnectCompleted(socket, receiveAsyncEventArgs);
                }
                else
                {
                    lock (interLocker)
                    {
                        if (requireClose)
                        {
                            CannelConnecting();
                        }
                        else
                        {
                            connectingCanBeCannelled = true;
                        }
                    }
                }
            }
            catch (SocketException e)
            {
                if (errorRecorder != null)
                {
                    errorRecorder.RecordError("Connect to " + endpoint + " failed.", e);
                }

                CloseWhenConnectingError();
            }
            catch (ObjectDisposedException e)
            {
                if (errorRecorder != null)
                {
                    errorRecorder.RecordError("Connect to " + endpoint + " failed.", e);
                }

                CloseWhenConnectingError();
            }
        }
예제 #7
0
        private void ConnectCompleted(object sender, SocketAsyncEventArgs e)
        {
            int unityDisCompliantSign = System.Threading.Interlocked.Exchange(ref connectCompletedSignForUnityIl2CPPDisCompliantImplement, 1);

            if (unityDisCompliantSign != 0)
            {
                if (e.SocketError != SocketError.Success)
                {
                    lock (interLocker)
                    {
                        if (status == TCPClient.ClientStatus.Connecting)
                        {
                            requireClose = true;
                            return;
                        }
                        else if (status == TCPClient.ClientStatus.Closed)
                        {
                            return;
                        }
                    }

                    //-- status == TCPClient.ClientStatus.Connected
                    Close();
                }

                return;
            }

            if (e.SocketError != SocketError.Success)
            {
                if (errorRecorder != null && !requireClose)
                {
                    errorRecorder.RecordError("Connect to " + endpoint + " failed. Due to SocketError: " + e.SocketError);
                }

                CloseWhenConnectingError();
                return;
            }

            if (requireClose)
            {
                CallConnectionConnectedDelegate(0, false, "Connecting cannel event exception. Remote endpoint: " + endpoint + ".");
                connectionCloseDelegate = null;
                Close();
                return;
            }

            receiveAsyncEventArgs.SetBuffer(receiver.buffer, receiver.offset, receiver.requireLength - receiver.offset);
            connectionId = socket.Handle.ToInt64();

            CallConnectionConnectedDelegate(connectionId, true, "Connected event exception. Remote endpoint: " + endpoint + ".");

            lock (interLocker)
            {
                status = TCPClient.ClientStatus.Connected;
            }

            if (requireClose)
            {
                Close();
                return;
            }

            if (ClientEngine.RegisterConnectedConnection(this) == false)
            {
                Close();
                return;
            }

            CheckSending();

            try
            {
                if (!socket.ReceiveAsync(receiveAsyncEventArgs))
                {
                    ReceiveCompleted(socket, receiveAsyncEventArgs);
                }
            }
            catch (ObjectDisposedException ex)
            {
                CloseByException("Receive data from " + endpoint + " exception. Connection is broken.", ex, true);
            }
            catch (SocketException ex)
            {
                CloseByException("Receive data from " + endpoint + " exception. Access socket is error.", ex, false);
            }
            catch (InvalidOperationException)
            {
                //-- Do nothings
            }
        }