본문 바로가기
프로그래밍

SuperSocket Custome 프로토콜 정의

by bantomak 2024. 1. 5.

Custome 프로토콜 정의

SuperSocket 예제를 보면 대부분 string 기반의 프로토콜을 사용하고 있으나 binary 기반의 프로토콜을 정의해서 사용할 수 있다.

 

Packet은 보통 messageId + size + body의 구조를 가진다.

 

BinaryRequestInfo 클래스와 FixedHeaderReceiveFilter 클래스를 재정의 한다.

// 헤더는 4 바이트 정수값으로 key, 그 다음 body byte[]의 크기를 가리키는 4 바이트 정수값
public class EFBinaryRequestInfo : BinaryRequestInfo
{
    public int nKey;
    {
        get;
        private set;
    }
    
    public EFBinaryRequestInfo(int nKey, byte[] body)
    	: base(null, body)
    {
        this.nKey = key;
    }
}

 

class ReceiveFilter : FixedHeaderReceiveFilter<EFBinaryREquestInfo>
{
    public ReceiveFilter()
    	: base(8)
    {
    }
    
    protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)
    {
    	if (!BitConverter.IsLitterEndian)
        {
            Array.Reverse(header, offset + 4, 4);
        }
        
        var nBodySize = BitConverter.ToInt32(header, offset + 4);
        return nBodySize;
    }
    
    protected override EFBinaryRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)
    {
    	if (!BitConverter.IsLitterEndian)
        {
            Array.Reverse(header.Array, 0, 4);
        }
        
        return new EFBinaryRequestInfo(BitConverter.ToInt32(header.Array, 0), bodyBuffer.CloneRange(offset, length));
    }
}

 

패킷 핸들러 정의

public class PK_LOGIN
{
    public string ID;
    public string Password;
}

public class PK_CHAT
{
    public string sender;
    public string msg;
}
public enum PACKETID : int
{
    REQ_DUMMY_CHAT = 1,
    REQ_LOGIN = 11,
}

public class CommonHandler
{
    public void RequestLogin(NetworkSession session, EFBinaryRequestInfo requestInfo)
    {}
    
    public void RequestDummyChat(NetworkSession session, EFBinaryRequestInfo requestinfo)
    {
    	string jsonstring = System.Text.Encoding.GetEncoding("utf-8").GetString(requestInfo.Body);
        var deserializedProduct = JsonConvert.DeserializeObject<PK_CHAT>(jsonstring);
        session.Send(deserializedProduct.sender + ":" + deserializedProduct.msg);
    }
}

 

var HandlerMap = new Dictionary<int, Action<NetworkSession, EFBinaryRequestInfo>>();
CommonHandler CommonHan = new CommonHandler();

public BoardSeverNet()
	: base(new DefaultReceiveFilterFactory<ReceiveFilter, EFBinaryRequestInfo>())
{
    NewSessionConnected += new SessionHandler<NetworkSession>(OnConnected);
    SessionClosed += new SessionHandler<NetworkSession, CloseReason>(OnClosed);
    NewRequestReceived += new RequestHandler<NetworkSession, EFBinaryREquestInfo>(RequestReceived);
}

public void RegistHandler()
{
    HandlerMap.Add((int)PACKETID.REQ_LOGIN, CommonHan.RequestLogin);
    HandlerMap.Add((int)PACKETID.REQ_DUMMY_CHAT, CommonHan.RequestDummyChat);
}

public void StartPacketThread()
{
    IsRunningPacketThread = true;
    PacketThread = new System.Threading.Thread(this.ProcessPacket);
    PacketThread.Start();
}

public void ProcessPacket()
{
    while(IsRunningPacketThread)
    {
        if (PacketQueue.TryDequeue(out var packet))
        {
            var PacketId = packet.reqInfo.nKey;
            
            if (HandlerMap.ContainsKey(PacketId))
            {
            	HandlerMap[PacketId].Invoke(packet.session, packet.reqInfo);
            }
        }
        
        System.Threading.Thread.Sleep(1);
    }
}

 

출처

 

오픈소스 네트워크 엔진 SuperSocket 사용하기 - ppt download

C++ & IOCP Windows 플랫폼에서 고성능 네트워크 프로그램을 만들 때 가장 자주 사용하는 기술은 ... PC 온라인 게임 시대 때...

slidesplayer.org

댓글