버그 해결을 위한 모든 질문을 던져
0 votes
169 views
안녕하세요. 질문 읽어주셔서 감사합니다.

C# 소켓통신에에 대한 예제를 살펴보는데

소켓통신시 송수신에 대한 버퍼를

버퍼의 크기 = 접속가능한 최대 유저수 * 2(송신용, 수신용) * 버퍼 사이즈

의 크기를 가진 버퍼를 생성하고

각 소켓마다 송수신을 처리할 버퍼를 offset으로 지정하여 사용하는 방식으로 구현되어 있었습니다.

모든 소켓의 송수신을 처리하는 하나의 버퍼를 offset을 이용하여 관리하는 것이

각 소켓별로 송수신 버퍼를 별도로 두어 사용하는 것보다 좋은점이 있는건가요?

궁금해서 질문 올려봅니다. 감사합니다.
asked (6 point) , 169 views
예제를 좀 살펴볼 수 있을까요? 어떤 방식인지 바로 이해가 잘 안되는군요
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace NetworkService
{
    internal class UserBufferManager
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////////
        // Member variables

        private int m_nNumBytes;
        private byte[] m_buffer;
        private int m_nCurrentIndex;
        private int m_nBufferSize;

        //////////////////////////////////////////////////////////////////////////////////////////////////////
        // Constructors

        public UserBufferManager(int nTotalBytes, int nBufferSize)
        {
            m_nNumBytes = nTotalBytes;
            m_nCurrentIndex = 0;
            m_nBufferSize = nBufferSize;
        }

        //////////////////////////////////////////////////////////////////////////////////////////////////////
        // Member functions

        /// <summary>
        /// 초기화 함수
        /// </summary>
        public void Initialize()
        {
            if (m_nNumBytes <= 0)
                return;

            m_buffer = new byte[m_nNumBytes];
        }

        /// <summary>
        /// 사용자 버퍼 할당 함수
        /// </summary>
        /// <param name="args">소켓비동기이벤트변수목록</param>
        /// <returns>할당에 성공 시 true 실패 시 false 반환</returns>
        public bool SetBuffer(SocketAsyncEventArgs args)
        {
            if (m_nNumBytes <= 0)
                return false;

            if ((m_nCurrentIndex + m_nBufferSize) > m_nNumBytes)
                return false;

            args.SetBuffer(m_buffer, m_nCurrentIndex, m_nBufferSize);
            m_nCurrentIndex += m_nBufferSize;

            return true;
        }
    }
}
 

해당 코드에서 비동기송수신에 사용할 버퍼를 각각 개별의 byteArray로 SetBuffer 하는게 아니라

모든 버퍼의 크기로 생성한 byteArray 하나로 Offset과 BufferSize를 통하여 SetBuffer를 호출하고있었습니다.

https://docs.microsoft.com/ko-kr/dotnet/api/system.net.sockets.socketasynceventargs.setbuffer?view=net-6.0#system-net-sockets-socketasynceventargs-setbuffer(system-byte()-system-int32-system-int32)

 

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture_series&page=1&sn1=&divpage=1&sn=on&ss=on&sc=on&keyword=%C5%C2%C7%B3%C0%C7%B1%D7%B6%F3%BF%EE%B5%E5&select_arrange=headnum&desc=asc&no=61

소켓송수신 버퍼관리 코드 참조하려고 찾아보았던 코드들입니다

SocketAsyncEventArgsPool을 구현하여 SocketAsyncEventArgs 객체에 설정된 버퍼들을 그대로 재사용하는 것이라면 SocketAsyncEventArgs 객체 하나당 개별 bufferSize크기의 byteArray를 생성하여 설정하는 것보다

totalSize 만큼의 byteArray를 생성하여 Offset을 이용하여 하나의 버퍼로 관리하는 것의 이점이 궁금해서 여쭈어 보았습니다.

링크해 주신 msdn의 설명에 따르면 

예제

다음 코드 예제에서는 분할 하 고 각 소켓 I/O 작업에 사용할 개체에 SocketAsyncEventArgs 할당할 수 있는 단일 큰 버퍼를 만듭니다. 이렇게 하면 버퍼를 쉽게 재사용하고 조각화된 힙 메모리를 방어할 수 있습니다.

원문

Examples

The following code example creates a single large buffer which can be divided up and assigned to SocketAsyncEventArgs objects for use with each socket I/O operation. This enables buffers to be easily reused and guards against fragmenting heap memory.

 라고 적혀있는거 같은데 저도 대답할 만큼 익숙한 도메인이 아니라서 잘 모르겠습니다 허허..

급하게 구현하느라 위의 내용을 못보고 지나쳤네요.

메모리 단편화의 방어 수단으로 단일 큰버퍼로 구현하면 될것같습니다.

답변 주셔서 감사합니다.

1 답변

+1 vote
우수 답변
찾아보신대로 메모리 단편화를 줄일 수 있는 장점이 있습니다.
answered (168 point)
선택됨
참고하였던 C# 게임서버 작성자이셨군요. 답변 감사합니다.

덕분에 많은 공부 되었습니다.

버그 해결을 위해 도움을 구하고, 도움을 주세요. 우리는 그렇게 발전합니다.

throw bug 는 프로그래밍에 대한 전분야를 다룹니다. 질문,논의거리,팁,정보공유 모든 것이 가능합니다. 프로그래밍과 관련이 없는 내용은 환영받지 못합니다.

620 질문
784 answers
748 댓글
118,442 users