신입 개발자가 작성한 연구일지입니다. 이때 오해하고 있던 잘못된 정보가 포함되어 있습니다.
이번에는 채팅 서버 구현을 위해 프로토콜을 추가해보도록 하겠습니다.
프로토콜은 두 프로그램(서버, 클라이언트)가 통신하기 위해 약속한 말의 형식입니다.
데이터를 보냈을 때, 받는 측과 보내는 측은 서로 '뭘 하려는 데이터'인지와 '그 작업을 하기 위해 어떤 데이터를 보냈는지'와 기타 보낼 데이터에 대한 약속을 해 두어야 합니다.
프로토콜을 지정함으로써 어떤 데이터를 주고받는지 명확하게 분류할 수 있습니다.
저는 Request 프로토콜과 Response 프로토콜을 따로 만들도록 했습니다.
각 프로토콜을 만들어 상속받고, 프로토콜의 ID 를 열거체로 선언했습니다.
public abstract class ProtocolRequest
{
public ProtocolId ProtocolId { get; set; }
protected ProtocolRequest(ProtocolId protocolId)
{
this.ProtocolId = protocolId;
}
}
public abstract class ProtocolResponse
{
public ProtocolId ProtocolId { get; set; }
public Result Result { get; set; }
protected ProtocolResponse(ProtocolId protocolId)
{
this.ProtocolId = protocolId;
}
}
public enum ProtocolId : int
{
Mesasge = 100,
None = 999,
Error =1000,
}
public class MessageRequest : ProtocolRequest
{
public string Message { get; set; }
public MessageRequest() : base(ProtocolId.Mesasge) { }
}
public class MessageResponse : ProtocolResponse
{
public string Message { get; set; }
public MessageResponse() : base(ProtocolId.Mesasge) { }
}
그리고 클라이언트와 서버에 해당 프로젝트를 추가했습니다.
이로써 프로토콜을 작성하여 두 프로그램이 공유하도록 설정을 완료했습니다 !
그리고 이렇게만 하면 using 으로 다른 namespace 를 사용할 수 없습니다.
dependencies 에서 설정을 마쳐 줍니다.
그리고 클라이언트에서 데이터를 보내는 송신부를 변경했습니다.
클래스는 바이트 버퍼에 담을 수 없습니다.
클래스 데이터를 바이트 배열에 싣기 위해 json으로 직렬화했습니다.
이 상태에서 데이터를 전송하고, 출력해 보았습니다.
클래스가 json 형태로 직렬화되어 전송된 것을 확인할 수 있습니다
서버에서 클라이언트로 데이터를 보내는 과정도 위처럼 프로토콜을 제작하여 보내도록 수정해 보겠습니다.
using System.Net.Sockets;
using System.Text.Json;
using Protocol;
namespace TCPServer;
public partial class Program
{
static async Task RunAsync(Remote remote)
{
while (true)
{
var (isSuccess, response)= await ReceiveAsync(remote);
if (isSuccess) Send(remote, (ProtocolResponse)response);
else break;
}
Close(remote);
}
static async Task<(bool, object)> ReceiveAsync(Remote remote)
{
int length = await remote.socket.ReceiveAsync(remote.receiveBuffer, SocketFlags.None);
string receiveMessage = System.Text.Encoding.UTF8.GetString(remote.receiveBuffer, 0, length);
if (receiveMessage == "")
return (false, null);
if(remote.socket.Connected == false)
return (false, null);
// remote.count++;
Console.WriteLine($"수신 : {receiveMessage}");
var response = new MessageResponse();
response.Message = "response message";
response.Result = Result.Success;
return (true, response);
}
static void Send(Remote remote, ProtocolResponse response)
{
string json = JsonSerializer.Serialize(response);
remote.sendBuffer = System.Text.Encoding.UTF8.GetBytes(json);
remote.socket.Send(remote.sendBuffer, 0, json.Length, SocketFlags.None);
}
static void Close(Remote remote)
{
remote.socket.Shutdown(SocketShutdown.Both);
remote.socket.Close();
remote.socket = null;
// [순서 중요] 메모리를 해제한 후 socket을 제거해야 합니다.
RemotePool.RemoveConnection(remote);
}
}
다음에는 이 프로토콜을 다시 클래스로 역직렬화해보도록 하겠습니다!
목표
30000명이 동시에 접속할 수 있는 TCP 서버 만들기
30000명의 클라이언트는 전송 - 수신 - 전송 - 수신 을 반복한다.
30000명의 클라이언트를 켜 놓고, 다음날 서버가 에러 없이 살아 있는 것을 목표한다.
목표를 성취한 후에는 평균 응답 시간을 줄여보도록 하겠다.
프로젝트 Git Hub Repository 링크
https://github.com/MatorMirne/SocketCommunicate-TCP
이전 포스트
- 1일차 : 2023.06.26 - [일지/C#] - [프로젝트 예수 - 1일차] 대규모 동시접속 TCP 서버
- 2일차 : 2023.06.27 - [일지/C#] - [프로젝트 예수 - 2일차] 대규모 동시접속 TCP 서버 제작기
- 3일차 : 2023.06.28 - [일지/C#] - [프로젝트 김필여 - 3일차] 대규모 동시접속 TCP C# 서버 제작기
- 4일차 : 2023.06.29 - [일지/미니프로젝트] - [프로젝트 김필여 - 4일차] 대규모 동시접속 TCP C# 서버 제작기
- 5일차 : 2023.07.05 - [일지/미니프로젝트] - [프로젝트 김필여 - 5일차] 대규모 동시접속 TCP C# 서버 제작기
- 6일차 : 2023.07.24 - [일지/미니프로젝트] - [프로젝트 김필여 - 6일차] 대규모 동시접속 TCP C# 서버 제작기
- 7일차 : 2023.07.25 - [일지/미니프로젝트] - [프로젝트 김필여 - 7일차] 대규모 동시접속 TCP C# 서버 제작기
- 8일차 : 2023.10.11 - [일지/미니프로젝트] - [프로젝트 김필여 - 8일차] 대규모 동시접속 TCP C# 서버 제작기
- 9일차 : 2023.10.11 - [일지/미니프로젝트] - [프로젝트 김필여 - 9일차] 대규모 동시접속 TCP C# 서버 제작기
'Side Project > 안양시장 프로젝트 - TCP 서버개발' 카테고리의 다른 글
[프로젝트 김필여 - 12일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.11.02 |
---|---|
[프로젝트 김필여 - 11일차] 대규모 동시접속 TCP C# 서버 제작기 (1) | 2023.10.30 |
[프로젝트 김필여 - 9일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.10.11 |
[프로젝트 김필여 - 8일차] 대규모 동시접속 TCP C# 서버 제작기 (2) | 2023.10.11 |
[프로젝트 김필여 - 7일차] 대규모 동시접속 TCP C# 서버 제작기 (0) | 2023.07.25 |