C#으로 MMORPG서버를 만드는 첫번째 과정입니다. Socket을 생성하고 간단한 연결을 하겠습니다.
서버의 Socket 제작 순서는 아래와 같습니다.
1. Socket 선언
2. Socket 설정(endpoint, socket type, protocol type)
3. Socket 열기(endpoint)
4. Client한테 받는 과정
5. Client한테 보내는 과정
6. 상호 합의하에(?) 연결 끊는 과정
Client의 제작 순서는 아래와 같습니다.
1. Socket 선언
2. Socket 연결(end point)
3. Server한테 보내는 과정
4. Server한테 받는 과정
5. 상호 합의하에(?) 연결 끊는 과정
서버
1. Socket 선언
// dns
string hostName = Dns.GetHostName();
IPHostEntry entry = Dns.GetHostEntry(hostName);
IPAddress ipAddr = entry.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 8081);
// socket
Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Socket을 선언합니다.
서버의 Socket은 항상 Client의 요청을 기다려야 하므로 listenSocket이라는 변수명을 붙였습니다.
Socket 객체를 만드려면 end point, socket type, protocal type을 알아야합니다.
end point는 서버의 주소입니다. ip주소와 port로 이루어져있습니다.
// dns에서 부분에 end point를 설정하는 과정이 있습니다.
그 중 entry.AddressList[0];는 google, naver처럼 클라이언트의 요청이 많은 서버는 entry address를 여러개 두는 경우가 있습니다(부하 방지) 그렇기 때문에 list로 받아옵니다. 저는 우선 0번째 주소를 받아오겠습니다.
IPEndPoint클래스를 통해 end point를 만들어주고 listenSocket객체를 생성해줍니다.
2. Socket 설정(endpoint, socket type, protocol type)
// socket setting
listenSocket.Bind(endPoint);
Bind메서드로 Socket을 설정해줍니다.
3. Socket 열기(endpoint)
// start
listenSocket.Listen(10);
while(true)
{
// client의 connection 요청 허가
Socket clientSocket = listenSocket.Accept();
}
그리고 Socket을 시작(?)합니다.
Listen(int num);에서 num의 의미는 몇개의 대기열을 받을지 설정하는 것입니다.
놀이공원이라고 생각하면, 이미 놀이기구가 운행되는 중에 총 10명의 대기손님만 받겠다는 의미입니다.
서버는 계속해서 Socket을 받아야 하니까 while(true)로 무한반복을 겁니다.
Accept();메서드로 클라이언트의 요청이 들어오면 해당 클라이언트의 Socket을 client socket 변수에 담아줍니다.
4. Client한테 받는 과정
// recive
byte[] buffer = new byte[1024];
int recvBytes = clientSocket.Receive(buffer);
string recvData = Encoding.UTF8.GetString(buffer, 0, recvBytes);
Console.WriteLine($"recv data : {recvData}");
buffer를 생성하여 클라이언트의 요청을 받고.
요청을 인코딩하여 우리가 볼 수 있는 형식으로 변경 후 Console에 출력합니다.
5. Client한테 보내는 과정
// send
byte[] buffer2 = Encoding.UTF8.GetBytes("Welcome to dongsik server!");
clientSocket.Send(buffer2);
위와 동일합니다.
6. 상호 합의하에(?) 연결 끊는 과정
// get out!
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
두 Socket이 모두 Shutdown되면 연결을 끊겠다는 의미입니다.
그렇게 만들어진 서버의 전체 코드는 아래와 같습니다.
class Program
{
static void Main(string[] args)
{
// dns
string hostName = Dns.GetHostName();
IPHostEntry entry = Dns.GetHostEntry(hostName);
IPAddress ipAddr = entry.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 8081);
// socket
Socket listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
// socket setting
listenSocket.Bind(endPoint);
// start
listenSocket.Listen(10);
while (true)
{
Console.WriteLine("Listening...");
// client의 connection 요청 허가
Socket clientSocket = listenSocket.Accept();
// ========== client socket이 생겼으니 서로 대화(?)가능 ==========
// recive
byte[] buffer = new byte[1024];
int recvBytes = clientSocket.Receive(buffer);
string recvData = Encoding.UTF8.GetString(buffer, 0, recvBytes);
Console.WriteLine($"recv data : {recvData}");
// send
byte[] buffer2 = Encoding.UTF8.GetBytes("Welcome to dongsik server!");
clientSocket.Send(buffer2);
// get out!
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
클라이언트
1. Socket 선언
2. Socket 연결(end point)
3. Server한테 보내는 과정
4. Server한테 받는 과정
5. 상호 합의하에(?) 연결 끊는 과정
서버와 동일하기 때문에 상세한 설명 없이 전체 코드를 삽입 하겠습니다.
class Program
{
static void Main(string[] args)
{
// dns
string hostName = Dns.GetHostName();
IPHostEntry entry = Dns.GetHostEntry(hostName);
IPAddress ipAddr = entry.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 8081);
// socket
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
// connection
socket.Connect(endPoint);
Console.WriteLine($"Connected to {socket.RemoteEndPoint.ToString()}");
// send
byte[] buffer = Encoding.UTF8.GetBytes("Can I visite your server?");
int bufferSize = socket.Send(buffer);
// recive
byte[] buffer2 = new byte[1024];
int bufferSize2 = socket.Receive(buffer2);
string recvData = Encoding.UTF8.GetString(buffer2, 0, bufferSize2);
Console.WriteLine($"from server : {recvData}");
// out
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
결과 확인
유니티를 실행시키면 위와같은 콘솔창이 보입니다.
좌측이 클라이언트, 우측이 서버입니다.
서버는 계속 Listening상태를 유지하고 있으며
클라이언트는 서버에게 1회 요청을 완료했습니다.