Receive Buffer를 제작하여 하드 코딩식이 아닌, 패킷 처리가 됐을 때도 적용 가능하도록 틀을 구성하였다.
기존 Send는 Encoding 하여 byte타입으로 넘겨주고, SendQueue에 저장하며 처리하는 방식이었다. 이번에는 이 부분을 개선 해줄 것이다.
하지만 Receive와 가장 큰 다른점은 Recv는 Session 마다 하나씩을 가지고 있어 사용 및 관리가 용이했다면, Send는 내부에서 적용하게 될 경우 성능 이슈가 발생한다.
Ex) 실시간 게임에서는 1명이 움직이면 나머지에게 이동 패킷을 전송을 해주게 되는데, Receive 같이 하나 씩 생성하면 100명이 동시에 움직일 경우 100*100으로 거의 10,000번 가까이 새로 생성해야하지만, 외부에서 선언 해줄 경우 생성한걸 loop로 넘겨주기만 하면 되기에 생성을 하는 것 보다는 훨씬 성능적으로 이득을 볼 수 있다.
보내 줄 때 마다 몇 바이트를 사용할 것인지 결정해서 보내주면 좋지만, String 값 같은 경우는 변경될 수 있기에 고정으로 보내기에는 어렵다.
그렇기에 큰 값을 선언해두고, 그 중 일부를(ArraySegment) 사용하는 방식으로 구성할 예정이다.
buffer로 활용해줄 byte 배열과, RecvBuffer에서 writepos와 같이 현재 사용한 영역을 표기할 usedSize, 그리고 남은 공간의 크기를 나타내는 FreeSize를 선언해준다.
사용하고자 하는 공간 만큼의 버퍼를 요청하고, 가능하면 뱉어주고, 아니면 넘겨주지 않는 구조로 구성한다.
Open이후 사용한 사이즈 만큼을 받아와서, 지정해준 뒤에 다시 뱉어주어 정확한 사용량을 체크하여 _usedSize에 대입한다.
Sendbuffer는 클린이라는 개념이 없다. send를 여러명에게 보내기에 다른 누군가가 sendQueue에 담아두고 참조하고 있을 수 있기에 재사용 구조를 만들기는 어렵다.(1회용)
SendBuffer의 내부 함수는 건들지 않고 사용하기 위해 SendBufferHelper라는 새로운 Class를 만들고, 사용하기 쉬우면서 고유의 영역을 가질 수 있는 TLS(ThreadLocalStorage)를 만들어준다.
ChunkSize(덩어리)
라는 큰 덩어리를 생성하여 다 사용할 때 까지 쭉 사용할 공간을 만든다.
이 부분에서도 Open, Close 를 활용할 수 있도록 제작하고, Open 시에는 TLS의 Value 값 체크로 아직 생성하지 않았다면, 새로운 공간을 만들어주고
남은 공간(FreeSize)가 새로 요청한 공간 보다 작을 경우. 즉, 여유 공간이 없을 경우에도 새로운 buffer를 만들어서 날려준다.
물론 두 조건에 걸리지 않고, 여유공간이 있을 때는 TLS의 Value의 Open을 해주며 전에 만든 곳에 사이즈를 넘겨준다.
사용 후에는 크게 제약사항이 없기에 바로 넘겨준다.
이제 아래와 같이 직접 SendBuff를 만들어 넘겨주는 영역을 수정 할 것이다.
byte[] sendBuff = Encoding.UTF8.GetBytes("Welcome to Justin Server")
예시를 위해서 새로운 Class의 hp, attack 데미지 등을 추가하고, 값을 넣어준다.
SendBufferHelper.Open(4096)
을 사용하여 Chunk 사이즈의 ArraySegment를 생성하고
BitConverter.GetBytes()
를 사용하여 hp, attack에 담아준 100과 10이라는 값을 byte[] 타입으로 변환한다.(둘은 각 4bytes를 할당한다)
Array.Copy()로 큰 공간을 만들어둔 openSegment에 복사해서 넣어준다. offset 값은 잘 맞춰주어야 하나 들어가고 그 다음 부터 들어간다.
그 뒤 사용한 만큼(buffer1, 2의 Length)을 알려준 뒤 Close를 해주고, 그 배열을 Send 해주면 8바이트가 넘어온 걸 알 수 있다.