인프런 커뮤니티 질문&답변

jiw720님의 프로필 이미지

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

Session #1

listener, session 간의 차이

23.02.28 22:20 작성

·

529

0

안녕하세요, listener, session 코드간 차이점에 대해서 질문이 있습니다.

1, listener에서는 OnRecvCompleted()와같은 메서드에서 socketerror가 발생했을 때, disconnect를 하지 않았는데, session에서는 왜 disconnect를 하는 건가요?

2.listener 에서는 registerRecv() 와같은 함수를 OnRecvCompleted의 if, else와 상관없이 실행한거같은데, 왜 session에서는 if(args.Bytes.Transferred > 0 && ~~~) 을 만족해야 OnRecvCompleted를 실행하는건가요?

 

 

 

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;

namespace ServerCore
{
    class Session
    {
        Socket _socket;
        public void init(Socket socket)
        {
            _socket = socket;

            SocketAsyncEventArgs recvArgs = new SocketAsyncEventArgs();
            recvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnRecvCompleted);
            //userTocken으로 추가적인 정보를 아무거나넘겨줄 수 있다(object를 받기 때문)
            recvArgs.SetBuffer(new byte[1024],0,1024);
            RegisterRecv(recvArgs);
        }

        void RegisterRecv(SocketAsyncEventArgs args)
        {
            args.AcceptSocket = null;

            bool pending = _socket.ReceiveAsync(args);

            //바로 성공했으면
            if(pending == false)
            {
                OnRecvCompleted(null, args);
            }
        }

        void OnRecvCompleted(object obj, SocketAsyncEventArgs args)
        {

            //BytesTransferred == 몇바이트 받았는지
            if (args.BytesTransferred>0 && args.SocketError == SocketError.Success)
            {

                try
                {
                    string recvData = Encoding.UTF8.GetString(args.Buffer, args.Offset, args.BytesTransferred);
                    Console.WriteLine($"[from client] : {recvData}");
                    RegisterRecv(args);
                }
                catch(Exception e)
                {
                    Console.WriteLine($"onrecvcompleted failed {e}");
                }
                
                
                
            }
            else
            {
                //TODO Disconnect 
            }
            
        }
    }
}

답변 3

0

jiw720님의 프로필 이미지
jiw720
질문자

2023. 03. 04. 14:45

감사합니다. 그런데,

listener는 accept를 실패했더라도 다른 client들을 계속 기다려야 하니까 if, else절 상관없이 받는 것이라고 이해했긴 했는데, (맞는진 모르겠습니다)

session은 recv를 한번의 stream들만 받는거니까 계속해서 args.BytesTransferred > 0 인 경우에만 계속해서

RegisterRecv(args); 로 낚싯대를 놓는걸로 이해했는데 맞을까요?

 

Rookiss님의 프로필 이미지
Rookiss
지식공유자

2023. 03. 04. 14:54

네 그렇습니다.

accept는 딱히 실패할 이유가 없고, 찰나의 순간 연결이 끊긴다면
어차피 Recv 0로 감지가 가능합니다.

Recv했는데 0 바이트를 수신했다는 것은,
(처음 수신 버퍼 사이즈를 0바이트로 일부러 세팅하는 0byte Recv 등의 기법이 아니라면)
무조건 상대방 연결이 끊길 때 발생합니다.

0

jiw720님의 프로필 이미지
jiw720
질문자

2023. 03. 04. 14:21

2번질문에 대한 답변은 어떻게 이해하면될까요?

Rookiss님의 프로필 이미지
Rookiss
지식공유자

2023. 03. 04. 14:25

Register 즉 등록 단계는 우리 마음이지만
그것에 대한 성공 여부는 상대방과 통신 성공 여부에 따라 다르기 때문입니다.

낚시대를 던진다 = Register
낚시대를 끌어올려서 확인한다 = OnRecvCompleted (근데 낚시대가 끊어졌다면? FAIL)

0

Rookiss님의 프로필 이미지
Rookiss
지식공유자

2023. 03. 02. 00:05

Listener는 문지기의 역할이고,
Session은 들어온 다음에 상대방 클라를 대표하는 일종의 대리인입니다.
따라서 세션이 끊기면 킥해주는 것이지만
Listener는 서버에서 문지기 역할을 담당하기에
우리가 내보낼 일이 없습니다.

jiw720님의 프로필 이미지

작성한 질문수

질문하기