비동기
더미 클라이언트
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
/// <summary>
/// 유니티 대신해서 테스트 하기위한 클라이언트
/// 테스팅 환경 구축용
/// </summary>
///
namespace DummyClient
{
class Program
{
static void Main(string[] args)
{
/// DNS (Domain Name System)
/// 172.1.2.3(실제로 넣으면 문제가됨!) 하드코딩 X!
/// 하지만 도메인 등록이라면 문제가 없다
/// www.rookiss.com -> 123.123.123.12
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
while (true)
{
///휴대폰 설정
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 sendBytes = socket.Send(sendBuff);
///받는다
byte[] recvBuff = new byte[1024];
int recvBytes = socket.Receive(recvBuff);
string receiveData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
Console.WriteLine($"From server{receiveData }");
///나간다
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Thread.Sleep(100);
}
}
}
}
비동기 서버 Listener
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace ServerCore
{
class Listener
{
Socket _listenSocket;
/// Accept가 완료되면 어떻게 처리할건지
Action<Socket> _onAcceptHandler;
public void Init(IPEndPoint endPoint,Action<Socket> onAcceptHandler)
{
///문지기 만들기(핸드폰만들기)
_listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_onAcceptHandler += onAcceptHandler;
///문지기 교육
_listenSocket.Bind(endPoint);
///영업 시작
///backlog : 최대 대기수
/// 문지기가 안내하기 전까지 대기하는 수
/// 만약 이 수가 넘어가는 사람이 문의하면 바로 fail이 뜬다
_listenSocket.Listen(10);
/// 한번만 만들어주면 계속 재활용 할수있는 어마어마한 장점이 있음
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);///나중에라도 완료되면 여기 이벤트로 연락오게하기!
RegisterAccept(args);///최초로 낚시대를 강물에 던짐!
}
void RegisterAccept(SocketAsyncEventArgs args)
{
///중요!
///다시 돌아올때 비어있는 args여야한다!!!
args.AcceptSocket = null;
/// 비동기! 동시에 처리안되고 나중에 처리될수있음!!!
///성공하든 아니든 상관없이 바로 리턴을 하고 본다(문제가 될수있음)
///로그인에 실패했는데 리턴때릴수있음
///비동기 계열을 사용하면 대화를 해야함(결과에 대해서)
///
///당장 완료한다는 보장은 없고 요청을 하긴 할꺼다
///말그대로 등록을 한거라고 보면됨
bool pending = _listenSocket.AcceptAsync(args);
if (pending == false)
{
///비동기로 실행했지만 운좋게 완료된 케이스
///낚시대를 강물에 던지자마자 물고기가 잡힌 케이스
OnAcceptCompleted(null,args);
}
else
{
///pending true
/// 나중에 args로 Completed 로 연락이 올것이다.
}
}
void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
{
if (args.SocketError == SocketError.Success)
{
///에러 없이 잘 처리 됫다(실제로 accept를 했다)
/// 유저가 커넥트 연결이 와서 실제로 accept까지 했다면
///TODO
_onAcceptHandler.Invoke(args.AcceptSocket);///완료됬으면 _onAccepHandler 실행!
}
else
{
Console.WriteLine( args.SocketError.ToString());
}
///모두 완료됬으니 다음 아이를 위해서 다시 등록!!
///다음 낚시대 던지기
RegisterAccept(args);
}
}
}
비동기 서버 Main
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// 소켓 프로그래밍 기초
///
/// 메모장 코드를 메인안에 때려박아넣으면 안됨!
///어짜피 커질꺼니까 처음부터 분리하는 습관을 들여야함!
///
///
/// </summary>
namespace ServerCore
{
class Program
{
static Listener _listener = new Listener();
static void OnAcceptHandler(Socket clientSocket)
{
try
{
byte[] recvBuff = new byte[1024];
int recvBytes = clientSocket.Receive(recvBuff);
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();
/// 받는다
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
static void Main(string[] args)
{
/// DNS (Domain Name System)
/// 172.1.2.3(실제로 넣으면 문제가됨!) 하드코딩 X!
/// 하지만 도메인 등록이라면 문제가 없다
/// www.rookiss.com -> 123.123.123.12
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
///혹시나 누가 들어오면 OnAcceptHandler에 전달해줘
_listener.Init(endPoint, OnAcceptHandler);
Console.WriteLine("Listening...");
while (true)
{
}
}
}
}
댓글 없음:
댓글 쓰기