예제 #1
0
        public async Task ServerMainAction()
        {
            while (stream == null)
            {
                await Task.Delay(200);
            }
            client.ReceiveTimeout = Timeout.Infinite;

            int bufferSize  = 0;
            int messageSize = 0;

            Methods.DataKind currentKind = 0;
            int current = 0;

            byte[] headBuffer    = new byte[4];
            byte[] messageBuffer = new byte[1024];

            CancellationToken cancelToken = Canceller.Token;

            while (true)
            {
                try
                {
                    while (true)
                    {
                        bufferSize = await stream.ReadAsync(headBuffer, 0, 4, cancelToken);

                        if (Canceller.IsCancellationRequested)
                        {
                            return;
                        }
                        if (bufferSize == 4)
                        {
                            messageSize = BitConverter.ToInt32(headBuffer, 0); // little endian
                            current     = 0;
                            goto data_kind_read_start;
                        }
                    }
data_kind_read_start:
                    while (true)
                    {
                        bufferSize = await stream.ReadAsync(headBuffer, 0, 4, cancelToken);

                        if (Canceller.IsCancellationRequested)
                        {
                            return;
                        }
                        if (bufferSize == 4)
                        {
                            currentKind = (Methods.DataKind)BitConverter.ToInt32(headBuffer, 0); // little endian
                            goto message_read_start;
                        }
                    }
message_read_start:

                    byte[] currentBuffer = messageBuffer.Length < messageSize ? new byte[messageSize] : messageBuffer;
                    while (current < messageSize)
                    {
                        bufferSize = await stream.ReadAsync(currentBuffer, current, messageSize, cancelToken);

                        current += bufferSize;
                        if (Canceller.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                    if (isClient)
                    {
                        switch (currentKind)
                        {
                        case Methods.DataKind.GameInit:
                            clientReader.OnGameInit(MessagePackSerializer.Deserialize <Methods.GameInit>(currentBuffer));
                            break;

                        case Methods.DataKind.TurnStart:
                            clientReader.OnTurnStart(MessagePackSerializer.Deserialize <Methods.TurnStart>(currentBuffer));
                            break;

                        case Methods.DataKind.TurnEnd:
                            clientReader.OnTurnEnd(MessagePackSerializer.Deserialize <Methods.TurnEnd>(currentBuffer));
                            break;

                        case Methods.DataKind.GameEnd:
                            clientReader.OnGameEnd(MessagePackSerializer.Deserialize <Methods.GameEnd>(currentBuffer));
                            break;

                        case Methods.DataKind.Pause:
                            clientReader.OnPause(MessagePackSerializer.Deserialize <Methods.Pause>(currentBuffer));
                            break;

                        case Methods.DataKind.Interrupt:
                            clientReader.OnInterrupt(MessagePackSerializer.Deserialize <Methods.Interrupt>(currentBuffer));
                            break;

                        case Methods.DataKind.RebaseByUser:
                            clientReader.OnRebaseByUser(MessagePackSerializer.Deserialize <Methods.RebaseByUser>(currentBuffer));
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                    else
                    {
                        switch (currentKind)
                        {
                        case Methods.DataKind.Connect:
                            var Data = MessagePackSerializer.Deserialize <Methods.Connect>(currentBuffer);
                            AIProcess = Process.GetProcessById(Data.ProcessId);
                            AIProcess.EnableRaisingEvents = true;
                            AIProcess.Exited += __onAIProcessExited;
                            serverReader.OnConnect(Data);
                            break;

                        case Methods.DataKind.Decided:
                            serverReader.OnDecided(MessagePackSerializer.Deserialize <Methods.Decided>(currentBuffer));
                            break;

                        case Methods.DataKind.DecidedEx:
                            serverReader.OnDecidedEx(MessagePackSerializer.Deserialize <Methods.DecidedEx>(currentBuffer));
                            break;

                        case Methods.DataKind.Interrupt:
                            serverReader.OnInterrupt(MessagePackSerializer.Deserialize <Methods.Interrupt>(currentBuffer));
                            break;

                        default:
                            throw new FormatException();
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (ex is TimeoutException)
                    {
                        continue;
                    }
                    if (ex is ObjectDisposedException)
                    {
                        return;
                    }
                    if (ex.InnerException is SocketException && ((SocketException)(ex.InnerException)).ErrorCode == 10060)
                    {
                        continue;
                    }
                    OnExceptionThrown?.Invoke(ex);
                    if (ex is IOException)
                    {
                        return;
                    }
                }
            }
        }