서론
매우매우매우 간단한 소켓프로그래밍 맛보기를 해보겠다.
이론 내용을 다시 복습해보자면
클라이언트
- 핸드폰 준비 (클라이언트 소켓 설정)
- 문지기한테 입장문의 (Connect)
- 대리자를 보냄
- 데이터 주고 받고 (send , receive)
서버
- 문지기 고용 (리스너 소켓)
- 문지기 교육(Bind 식당 주소와 정문인지 후문인지)
- 영업시작 (Listen)
- 안내 (Receive, Send)
이걸 토대로 코딩을 한다
소켓의 기본 역할 설명
| 단계 | 서버 | 클라이언트 | 설명 |
|---|---|---|---|
| 1 | Bind() | — | 서버가 자신의 IP:Port를 지정 |
| 2 | Listen() | — | 클라이언트의 연결 요청을 대기 |
| 3 | Accept() | Connect() | 실제 연결이 성립 |
| 4 | Send() | Send() | 데이터 송신 |
| 5 | Receive() | Receive() | 데이터 수신 |
| 6 | Close() | 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);문지기 휴대폰 만들자
- IPv4, IPv6넣어줄지 정하는것 (자동으로 DNS에서 만들어줬기에 그냥 넣는다)
- TCP UDP해줄지 정하는것
- 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());
}