RecvBuffer

원래벌레·2022년 8월 21일
0
post-custom-banner

🌞 패킷작업을 위한 RecvBuffer

  • 패킷 작업을 위한 초석단계이다. ( 아직 왜 쓰는지는 모르겠다.. 다음 수업들을 들어봐야알듯)

  • 기존에는 Session의 Start메소드에서 아규먼트의 SetBuffer를 통하여 RecvBuffer를 등록해주었다.

  • 이 작업을 통해 달라진 점은 RecvBuffer 클래스를 만들어서 ArraySegment로 충분히 큰 buffer를 하나 만들어서, 그 buffer 하나를 이용하여 데이터를 쓰고 읽게끔 만들어 준 것이다.

  • 눈에 들어왔던 점은 ReadSegement와 WriteSegment로 각각 RecvBuffer 클래스의 인스턴스 변수로 ArraySegment 타입인데, 각각 Offset과 Count의 값을 다르게 설정하여 쉽게 Read, Write 부분을 찾을 수 있게 한 부분이 눈에 가장 들어왔다.

using System;
using System.Collections.Generic;
using System.Text;

namespace ServerCore
{
    class RecvBuffer
    {
        ArraySegment<byte> _buffer;
        int _readPos;
        int _writePos;

        public RecvBuffer(int bufferSize)
        {
            _buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
        }

        public int DataSize { get { return _writePos - _readPos;  } }
        public int FreeSize { get { return _buffer.Count - _writePos; } }

        public ArraySegment<byte> ReadSegment
        {
            get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _readPos, DataSize); }
        }
        public ArraySegment<byte> WriteSegment
        {
            get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _writePos, FreeSize); }
        }

        public void Clean()
        {
            int dataSize = DataSize;
            if( dataSize == 0)
            {
                _readPos = _writePos = 0;
            }
            else
            {
                Array.Copy(_buffer.Array, _buffer.Offset + _readPos, _buffer.Array, _buffer.Offset, dataSize);
                _readPos = 0;
                _writePos = dataSize;
            }
        }

        public bool OnRead(int numOfBytes)
        {
            if (numOfBytes > DataSize)
                return false;

            _readPos += numOfBytes;
            return true;
        }

        public bool OnWrite(int numOfBytes)
        {
            if (numOfBytes > FreeSize)
                return false;
            _writePos += numOfBytes;
            return true;
        }
    }
}
void RegisterRecv()
        {
            _recvBuffer.Clean();
            ArraySegment<byte> segment = _recvBuffer.WriteSegment;
            _recvArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);

            bool pending = _socket.ReceiveAsync(_recvArgs);
            if (pending == false)
                OnRecvCompleted(null, _recvArgs);

        }

        void OnRecvCompleted(object obj, SocketAsyncEventArgs args)
        {
            if(args.BytesTransferred != 0 && args.SocketError==SocketError.Success)
            {
                try
                {
                    if(_recvBuffer.OnWrite(args.BytesTransferred)== false)
                    {
                        Disconnect();
                        return;
                    }


                    int processLen = OnRecv(_recvBuffer.ReadSegment);
                    if(processLen < 0 || _recvBuffer.DataSize < processLen)
                    {
                        Disconnect();
                        return;
                    }


                    if(_recvBuffer.OnRead(processLen) == false)
                    {
                        Disconnect();
                        return;
                    }

                    RegisterRecv();
                }
                catch(Exception e)
                {
                    Console.WriteLine($"OnRecvCompleted Failed {e}");
                }
            }
            else
            {
                Disconnect();
            }
        }
    }

기존에는 Start 메소드에서 SetBuffer를 해주었다면, 이제부터는 RegisterRecv 에서 SetBuffer를 해준다. 그 이유는 Start 부분에서 SetBuffer를 해주게 되면, OnSendCompleted에서 실행 되고 있는 RegisterRecv 부분에서 Read하고, Write하는 부분을 다시 재설정 해주지 못하기 때문이다.

profile
학습한 내용을 담은 블로그 입니다.
post-custom-banner

0개의 댓글