서론

매우매우매우 간단한 소켓프로그래밍 맛보기를 해보겠다.

이론 내용을 다시 복습해보자면

클라이언트

  1. 핸드폰 준비 (클라이언트 소켓 설정)
  2. 문지기한테 입장문의 (Connect)
  3. 대리자를 보냄
  4. 데이터 주고 받고 (send , receive)

서버

  1. 문지기 고용 (리스너 소켓)
  2. 문지기 교육(Bind 식당 주소와 정문인지 후문인지)
  3. 영업시작 (Listen)
  4. 안내 (Receive, Send)

이걸 토대로 코딩을 한다


소켓의 기본 역할 설명

단계서버클라이언트설명
1Bind()서버가 자신의 IP:Port를 지정
2Listen()클라이언트의 연결 요청을 대기
3Accept()Connect()실제 연결이 성립
4Send()Send()데이터 송신
5Receive()Receive()데이터 수신
6Close()Close()연결 종료

서버

먼저 Local Dns에서 도메인을 가져와서 IP를 가져온다 그걸 토대로 문지기를 고용한다

DNS (Domain Name System)

IP를 하드코딩한채로 서버를 만듬
근대 게임이 출시되고 다른대로 이전을 했는데 IP주소를 바꾼다고하면 일일이 하나하나 다바꿔야하는데
123.123.123.12 www.rungminth.com 으로 바꾸면 관리가 쉬워진다는거임
즉 c++의 typedef이라생각 해보자

string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);

AddressList가 배열인 이유

ip를 여러개 관리 할 수도있다 트래픽이 어마어마하게 많은경우
어떤사람 한테는 1번주소 다른사람 한테는 2번주소로 알려주면서
부하분산을 하는 경우도 있다
DNS로 어떻게 IP를 찾았는지에 대한건 따로 공부해보자
간단하게 말하자면 DNS서버가 우리 네트워크 망 안에 하나가 더 있다고 한다

IPAddress ipAddr = ipHost.AddressList[0];

최종 ip주소

ipAddr = 식당주소, 7777 = 식당 정문인지 후문인지 나타내는 번호 (port번호)

IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);

문지기 휴대폰 만들자

  1. IPv4, IPv6넣어줄지 정하는것 (자동으로 DNS에서 만들어줬기에 그냥 넣는다)
  2. TCP UDP해줄지 정하는것
  3. tcp udp해줄지 정하는 것
Socket ListenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

문지기 교육 (Bind) (식당 주소와 후문인지 정문인지 포트번호알려줌)

ListenSocket.Bind(endPoint);

영업시작

backlog : 최대 손님 대기수

ListenSocket.Listen(10);

손님 안내 Receive Send

//손님을 한번만 받고 끝나는게아니라 계속 받을꺼니깐 무한루프
while (true)
{
    Console.WriteLine("Listening...");
 
    //손님이 들어오고싶다 그러면 입장시킴
 
    //Accept함수를 호출하면 Socket을 Return시킴
    //왜? 문지기가 손님한테 전화받으면 해당 휴대폰번호를 알고있게 되는것과 같다
    //이제 손님하고 통화하고싶으면 clientSocket하고 통화를 하면 된다
    Socket clientSocket = ListenSocket.Accept();
 
    // 손님이 바로 하고싶은 말이있는데 들어보는 함수가 Recive
 
    // buffer 보내준 데이터를 받는 용도
    byte[] recvBuff = new byte[1024];
 
    // 리턴타입 몇바이트 받았는지 뱉어줌
    int recvBytes = clientSocket.Receive(recvBuff);
 
    //byte로 받은 데이터를 문자열을 인코딩함
    //1. 버퍼
    //2. 시작인덱스
    //3. 버퍼 갯수
    string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
    Console.WriteLine($"[From Client] {recvData}");
 
 
    // 데이터를 클라측으로 보낸다
    // 일단 임시로 우리가 얼마나 보낼지 알고있으니 바로 인코딩해서 넘겨준다
    byte[] sendBuff = Encoding.UTF8.GetBytes("Welcome to MMORPG Server !");
    clientSocket.Send(sendBuff);
 
    // 볼일봤으니 쫓아냄
    clientSocket.Shutdown(SocketShutdown.Both);
    clientSocket.Close();

클라이언트

서버와 소켓셋팅은 비슷하면서
Connect와 서버의 데이터를 먼저 보내는 방식

string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
 
// 휴대폰 설정
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
 
try
{
    // 문지기한테 입장 문의
    socket.Connect(endPoint);
 
    //연결이 됐으면 서버의 엔드포인트를 불러와봄
    Console.WriteLine($"Connected To {socket.RemoteEndPoint.ToString()}");
 
    // 보낸다
    byte[] sendBuff = Encoding.UTF8.GetBytes("Hello World!");
    int sendByte = socket.Send(sendBuff);
 
    // 받는다
    byte[] recvBuff = new byte[1024];
    int recvByte = socket.Receive(recvBuff);
 
    string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvByte);
 
    Console.WriteLine($"[From Server] {recvData}");
 
    // 나간다
    socket.Shutdown(SocketShutdown.Both);
    socket.Close();
}
catch(Exception ex)
{
    Console.WriteLine(ex.ToString());
}