![C# 소켓 프로그래밍-1(서버-클라이언트 통신)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsB6h0%2FbtrRyyZtJoo%2FPuWiqEUUqfCMEeBowpHI80%2Fimg.jpg)
현재 진행하고 있는 C#기반 메신저 프로젝트에서 소켓 프로그래밍을 사용할 기회가 생겨 정리하게 되었습니다.
우선 이 프로젝트의 목적은 비동기 소켓통신을 통하여 채팅중계서버를 구현하고,
같은 로컬에 있는 각각의 클라이언트에서 채팅을 주고받을 수 있도록 하는 것에 있습니다.
일단 한눈에 예제를 확인할 수 있게 콘솔앱으로 작성하였고, 아래는 서버 측 소스코드입니다.
static void Main(string[] args)
{
//서버측의 소켓을 생성, 클라이언트와 통신할 연결방식 및 프로토콜 타입을 선언
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//모든 네트워크의 클라이언트의 연결을 받을 수 있게 Any작성
IPAddress ipaddr = IPAddress.Any;
//ipendpoint = ip:port
IPEndPoint ipendp = new IPEndPoint(ipaddr, 3000);
//소켓에 ipEndPoint 결합
server.Bind(ipendp);
//최대 수신대기할 수 있는 인원수 10명으로 지정
server.Listen(10);
Console.WriteLine("Connection wait!");
//클라이언트를 특정지을 수 있는 소켓객체
Socket client = server.Accept();
Console.WriteLine("Client Conn, " + client.ToString() + "IP END POINT : " + client.RemoteEndPoint.ToString());
//수신된 데이터를 받을 수 있는 바이트 배열 선언
byte[] buff = new byte[128];
while (true)
{
//클라이언트로부터 수신받은 바이트의 길이
int numberofreceivebytes = client.Receive(buff);
Console.WriteLine("Number bytes : " + numberofreceivebytes);
//수신된 텍스트는 바이트임으로 이를 ASCII코드로 인코딩변환
string receivetext = Encoding.ASCII.GetString(buff, 0, numberofreceivebytes);
Console.WriteLine("received Text Data : " + receivetext);
//바이트배열에 담겨져있는 데이터를 클라이언트 측으로 재송신
client.Send(buff);
if(receivetext == "x")
{
break;
}
//루프를 돌기 전에 데이터 청소
Array.Clear(buff, 0, buff.Length);
numberofreceivebytes = 0;
}
}
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-> 소켓 클래스를 사용하여 서버측의 소켓을 생성하는 구문으로 해당 소켓을 통하여 클라이언트와 통신이 가능합니다.
IPAddress ipaddr = IPAddress.Any;
-> 서버에서 모든 네트워크 인터페이스의 클라이언트 동작을 수신 대기해야 함을 나타내는 IP주소를 제공합니다.
server.Listen(10);
-> 여기서부터 서버는 소켓을 수신대기 상태로 변환합니다. 매개변수는 수신대기 할 클라이언트 요청 수를 뜻합니다.
Socket client = server.Accept();
-> Listen중에 연결요청이 들어온 클라이언트를 담은 큐에서 첫번째 연결요청을 동기적으로 추출하고 새로운 소켓 연결을 만들고 반환합니다.
클라이언트의 요청을 받아들인 후 While 무한루프에 진입하게 됩니다.
int numberofreceivebytes = client.Receive(buff);
-> Receive()메서드를 통해 클라이언트로부터 데이터를 받을 수 있으며, 해당 메서드의 반환값은 받은 바이트 수입니다.
아래는 클라이언트 측 소스코드입니다.
static void Main(string[] args)
{
//소켓 객체 생성 (TCP 소켓)
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//끝점 생성
var ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);
//해당 끝점에 소켓 연결
sock.Connect(ep);
string cmd = string.Empty;
byte[] receiverBuff = new byte[8192];
Console.WriteLine("Connected... Enter Q to exit");
// Q 를 누를 때까지 계속 Echo 실행
while ((cmd = Console.ReadLine()) != "Q")
{
byte[] buff = Encoding.UTF8.GetBytes(cmd);
//서버에 데이터 전송
sock.Send(buff);
//서버로부터 온 데이터 수신
int n = sock.Receive(receiverBuff);
//바이트로 수신한 데이터를 String으로 인코딩
string data = Encoding.UTF8.GetString(receiverBuff, 0, n);
Console.WriteLine(data);
}
// (5) 소켓 닫기
sock.Close();
sock.Dispose();
}
sock.Connect(ep);
-> 서버와 달리 클라이언트 측에서는 Connect()를 통해 서버측에 연결요청을 전달하는 메서드가 있습니다. 서버측에서는 이렇게 전달된 연결요청을 Listen()메서드를 통해 수신대기 큐에 저장하게 됩니다.
sock.Close(); & sock.Dispose();
-> 서버와 연결된 소켓을 닫고 제거합니다.
이후는 서버와 동일하게 무한루프 내에서 바이트데이터를 전송 및 수신하는 과정을 진행합니다.
개발 기술 블로그, Dev
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!