// DummyClient
// Program.cs
namespace DummyClient
{
class Program
{
static void Main(string[] args)
{
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777/* Port */);
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
// Connect는 무한 대기하기에 여기를 Connector로 만들어 비동기화 해보자
socket.Connect(endPoint);
Console.WriteLine($"Connected To {socket.RemoteEndPoint.ToString()}...");
// ...
ServerCore에 Connector 클래스 생성
// ServerCore
// Connector.cs
namespace ServerCore
{
class Connector
{
public void Connect(IPEndPoint endPoint)
{
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += OnConnectComplete;
args.RemoteEndPoint = endPoint;
// UserToken를 이용해서 원하는 데이터를 넘길 수 있음
args.UserToken = socket;
RegisterConnect(args);
}
void RegisterConnect(SocketAsyncEventArgs args)
{
Socket socket = args.UserToken as Socket;
if (socket == null)
return;
bool pending = socket.ConnectAsync(args);
if (pending == false)
OnConnectComplete(null, args);
}
void OnConnectComplete(object sender, SocketAsyncEventArgs args)
{
if(args.SocketError == SocketError.Success)
{
// Connect후 동작을 정의해야함
// Session을 받아서 처리하게 할 예정(아래 참고)
}
else
{
Console.WriteLine($"OnConnect Completed Fail : {args.SocketError}");
}
}
}
}
class Connector
{
// sessionFactory를 통해서 생성된 session을 전달 받을 예정
Func<Session> _sessionFactory;
public void Connect(IPEndPoint endPoint, Func<Session> sessionFactory)
{
Socket socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += OnConnectComplete;
args.RemoteEndPoint = endPoint;
_sessionFactory += sessionFactory;
// ...
void OnConnectComplete(object sender, SocketAsyncEventArgs args)
{
if(args.SocketError == SocketError.Success)
{
Session session = _sessionFactory.Invoke();
session.Start(args.ConnectSocket);
session.OnConnected(args.RemoteEndPoint);
}
//...
이제 DummyClient에서 ServerCore의 Connect 클래스를 사용하면 되는데
그냥 using을 써서 사용이 안된다.
아래처럼 사용하자
- ServerCore 우클릭 -> 속성
- 출력 형식 -> 클래스 라이브러리로 변경
- Server, DummyClient 우클릭 -> 추가 -> 참조
- ServerCore 클릭 후 확인
여기까지하면 ServerCore를 외부에서 사용이 가능
// DummyClient
// Program.cs
namespace DummyClient
{
class GameSession : Session
{
public override void OnConnected(EndPoint endPoint)
{
Console.WriteLine($"[OnConnected] {endPoint}");
// 보내는 부분
byte[] sendBuff = Encoding.UTF8.GetBytes("Hello World!");
Send(sendBuff);
}
public override void OnRecv(ArraySegment<byte> buffer)
{
string recvData = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count);
Console.WriteLine($"[From Server] {recvData}");
}
public override void OnSend(int numOfBytes)
{
Console.WriteLine($"[OnSend] {numOfBytes}");
}
public override void OnDisconnected(EndPoint endPoint)
{
Console.WriteLine($"[OnDisconnected] {endPoint}");
}
}
class Program
{
static void Main(string[] args)
{
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777/* Port */);
Connector connector = new Connector();
connector.Connect(endPoint, () => { return new GameSession(); });