public void Init(IPEndPoint endPoint, Func<Session> sessionFactory)
{
_listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_sessionFactory += sessionFactory;
_listenSocket.Bind(endPoint);
_listenSocket.Listen(10);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
RegisterAccept(args);
}
세션을 상속받아 컨텐츠 세션을 만들어 사용하는 경우
어떤 세션을 만들지 정하는 함수를 받아 클라이언트가 접속 시 해당 함수로 생성한다.
SocketAsyncEventArgs는 async 이벤트 시 인자로 넘겨지며 계속 사용됨
args.Completed에 accept 시 발생시킬 콜백 함수를 등록
RegisterAccept 함수로 accept 진행
void RegisterAccept(SocketAsyncEventArgs args)
{
args.AcceptSocket = null;
bool pending = _listenSocket.AcceptAsync(args);
if (pending == false) // 대기 없이 바로 실행된 경우
{
OnAcceptCompleted(null, args);
}
}
args가 이전에 발생한 소켓을 들고 있을 수도 있기 때문에 AcceptSocket을 초기화
_listenSocket.AcceptAsync(args) 함수를 통해 accept를 비동기적으로 실행시킴
pending을 통해 해당 함수가 즉각적으로 실행됐는지 알 수 있는데,
즉각적으로 실행됐으면 Completed에 등록했던 이벤트가 발생하지 않기 때문에
콜백 함수를 직접 호출해야 함
void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
{
if (args.SocketError == SocketError.Success)
{
Session session = _sessionFactory.Invoke();
session.Start(args.AcceptSocket);
session.OnConnected(args.AcceptSocket.RemoteEndPoint);
}
else
{
Console.WriteLine(args.SocketError);
}
RegisterAccept(args);
}
세션을 생성하고 클라이언트 소켓을 전달
그 후 다른 클라이언트를 받기 위해서는
register를 다시 불러 AcceptAsync를 또 실행해야 함