List안에 기본 int와 같은 자료형이 있는 경우 string, byte넘긴거와 마찬가지 List 몇개 있는지 밀어넣고 데이터를 밀어넣으면 된다.
List안에 구조체가 있는 경우
public struct SkillInfo
{
public int id;
public short level;
public float duration;
}
public List<SkillInfo> skills = new List<SkillInfo>();
List가 몇개인지 short로 밀어 넣고 data를 밀어넣기
1. Write
01 크기 정보 기록
skills List의 요소 개수를 ushort로 변환하여 기록한다.
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), (ushort)skills.Count);
count += sizeof(ushort);
02 skills List의 각 SkillInfo 구조체를 순회하면서 데이터를 바이트 배열에 기록
foreach(SkillInfo skill in skills)
{
// skill마다 데이터를 밀어넣어주는 작업이 필요
}
03 SkillInfo의 Write 메서드
Write메서드는 각 SkillInfo구조체의 데이터를 바이트 배열에 기록하는 역할을 한다. id,level,duration 각각의 값을 바이트 배열에 기록하고 count변수를 업데이트 한다.
public bool Write(Span<byte> s, ref ushort count)
{
bool success = true;
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), id);
count += sizeof(int);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), level);
count += sizeof(short);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), duration);
count += sizeof(float);
return success;
}
04 skill마다 데이터를 밀어넣어주는 작업이 필요
skills리스트에 있는 각 SkillInfo구조체의 데이터를 바이트 배열로 변환하면서 Write메서드를 호출하여 각 SkillInfo의 데이터를 바이트 배열에 기록한다.
foreach(SkillInfo skill in skills)
{
success &= skill.Write(s, ref count);
}
sucess변수가 하나라도 false이 되면 최종 결과로 false를 반환하도록 한다. 이를 통해 SkillInfo의 데이터가 성공적으로 기록되었는지 확인할 수 있다.
2. Read
01 SkillInfo의 Read
SkillInfo의 Read메서드는 바이트 배열로부터 데이터를 읽어와 SkillInfo구조체의 필드에 저장하는 역할을 한다. 각 필드에 대한 데이터를 바이트 배열로부터 읽어와 count변수를 업데이트 한다.
public struct SkillInfo
{
public void Read(ReadOnlySpan<byte> s, ref ushort count)
{
id = BitConverter.ToInt32(s.Slice(count, s.Length - count));
count += sizeof(long);
level = BitConverter.ToInt16(s.Slice(count, s.Length - count));
count += sizeof(short);
duration = BitConverter.ToSingle(s.Slice(count, s.Length - count));
count += sizeof(float);
}
}
02 skill list parsing
Read메서드는 skills List를 파싱하며 각 SkillInfo구조체를 생성하고 읽어온 데이터를 저장한다.
public override void Read(ArraySegment<byte> openSegment)
{
ushort skillLen = BitConverter.ToUInt16(s.Slice(count, s.Length - count));
count += sizeof(ushort);
skills.Clear();
for(int i = 0; i < skillLen; i++)
{
SkillInfo skill = new SkillInfo();
skill.Read(s, ref count);
skills.Add(skill);
}
}
1) skillLen
s의 현재위치(count)에서부터 ushort형식으로 크기 정보를 읽어온다. 이는 skills리스트에 있는 SkillInfo 구조체의 개수이다.
ushort skillLen = BitConverter.ToUInt16(s.Slice(count, s.Length - count));
2) count변수 업데이트
count += sizeof(ushort);
3) skills.Clear
기존에 skills 리스트에 있는 데이터를 모두 지운다. 이는 데이터를 다시 읽어올 때 기존 데이터와 새로운 데이터를 혼동하지 않기 위해서이다.
skills.Clear();
4) skillLen의 크기만큼 반복하여 SkillInfo구조체 데이터 읽어오기
for(int i = 0; i < skillLen; i++)
{
SkillInfo skill = new SkillInfo();
// 바이트 배열 s에서 데이터를 읽어와 skill 객체에 저장
skill.Read(s, ref count);
// skill 객체를 skills 리스트에 추가
skills.Add(skill);
}
3. 결과
참고 : 본 내용은 MMORPG PART4 강의를 수강하여 작성하였습니다.
https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part4
'cs공부 > 네트워크프로그래밍' 카테고리의 다른 글
네트워크 프로그래밍 - XML문서에서 패킷 패싱 및 패킷 데이터를 자동화 방식으로 읽고 쓸 수있는 형태의 템플릿 정의 (0) | 2023.08.20 |
---|---|
네트워크프로그래밍 - XML형식으로 패킷 정의 +) XML, 마크업 설명 (0) | 2023.08.19 |
네트워크프로그래밍 - ENCODING(ASCII,UTF-8,UTF-16) (0) | 2023.08.08 |
네트워크프로그래밍 - packetId와 size에 대한 이슈(client의 거짓말, ReadOnlySpan) (0) | 2023.08.07 |
네트워크프로그래밍 - 패킷 자동화 처리 객체지향 방법으로 수행하도록 하기 (0) | 2023.08.07 |
댓글