|
제가 하는 순서가 이렇습니다.
1. 최초 고정화된 사이즈의 헤더를 받고요.. (안에 명령을 구분하는 변수라든가 패킷 사이즈라든가 그런게 있습니다.)
2. 헤더에서 정의된 만큼의 패킷을 받습니다.
3. 해당 패킷을 실행합니다.. (유저 생성, DB처리 등이 있겠죠..)
처음 접속하면 3번 부분에서 유저 정보를 받아서 서버내에 유저구조체에 값을 기록합니다.
struct
{
char UserID[20];
int Score;
.....
} SPlayer;
SPlayer stPlayer[MAX_PLAYER];
이런 식의 유저 정보가 있지요..
제가 애매한게 이런 공용의 유저 정보 갱신을 할때 어디서 동기화를 해줘야 하느냐하는 부분인데요..
그런데, 둘리님께서 써주신 글을 보면 Read가 끝나면 쓰레드에서 탈출하니까 쓰레드 상태가 아니라는 말이 되는데요.. 그러니, 유저 정보 갱신을 위해 동기화가 따로 필요없다는 말이 되지 않나요?
인디에서 쓰레드가 쓰이는 부분이 Read,Write같은 부분에 한정된다는 말씀인지요..
제가 생각해왔던 개념은 OnExecute자체가 인디 내부 쓰레드에 포함되어 있는 함수이기 때문에 DB에다 Synchronize를 걸기도 하고, 패킷에 동기화도 걸고 그런 것이라 생각을 했었거든요..
그러니, Read류 에만 쓰레드가 적용되는거라면 굳이 패킷도 그렇고, DB에다 Synchronize나 그런걸 걸 필요가 있나하는 부분입니다..
ADO 같은 경우도 명령을 걸어놓으면 백그라운드로 실행되는게 아니고, 처리가 완전 종료될때까지 블럭되는걸로 알고 있거든요..
그리고, 1소켓을 써서 공용 데이타를 갱신하는거랑 3소켓을 써서 갱신하는거랑 처리방식에 어떤 차이가 발생하는 지도 애매합니다.
결국 한 마디로 요약한다면 인디의 쓰레드 처리가 어디부터 어디까지를 커버하고 있는지가 애매하다는 거네요..
으흑.. 제가 잘못 알고 있는 부분에 대해서 조언을 해주세요..ㅠㅠ
둘리.CSIEDA 님이 쓰신 글 :
: Socket 에서 데이터를 읽어오는 부분이 어디 있나요?
: 설마 ProcessPacket() 에서 하시는것은 아니겠죠?
: 짐작컨데 ProcessPacket() 에서 하는듯 하군요. ServerExecute 에 Socket에서 데이터를 읽는 부분이 없으니까요.
:
: CriticalSection 이나 Synchronize 에 대하여 정확히 아셔야 합니다. 또한 Indy의 Thread 가 어떻게 도는지 아셔야 합니다.
:
: 일단 Server (Client도 마찬가지 입니다만) ServerExecute 에 인디 프로세스가 옵니다. 물론 AThread 를 인수로하여
: 이 안에 socket 정보를 가지고 옵니다.
:
: ServerExecute 에 와서
:
: Socket 에서 데이터를 읽으러 들어가야죠.. AThread->Connection->Socket->Read 정도 되는 함수들일 것 입니다.
: 이렇게 읽으러 들어가면 프로세스가 그 안에서 멈추어 있습니다.
: 흔히 client socket은 마냥 기다리지 않고 timeout 을 설정하여 해당 timeout 이 지나면 해당 동작을 무시하고 read 에서 나옵니다. 그러나 server socket은 데이터가 올때까지 기다립니다.
:
: 기다리다가 원하는 데이터가 오면 해당 함수를 탈출하여 나옵니다. 즉 다음 라인으로 진행하죠.
: 또한 비정상적인 client 연결 종료도 있을수 있는데,, 이경우도 thread를 빠져 나옵니다. 그러나 에러가 걸려 나오기 때문에 try ... catch... 로 묶어 주셔서 정상적으로 나온건지(원하는 데이터가 옴) , 아니면 기타 다른요인으로 에러가 난것인지를 판단해야 합니다.
:
: 아래의 소스에서 보면 무조건 critical section으로 들어갑니다.
: 그러면 다음 소켓은 해당 critical section으로 들어갈 수가 없습니다.
:
: 즉 소켓 하나만 돌겠죠.. 나며지는 기다리고 ,, 데이터 수신도 못하고요..
:
: 앞선 socket이 데이터를 받아서 나온후 critical section을 빠져 나와야 다음 소켓이 들어가겠죠.
:
: critical section이든 synchronize 든 오랜시간을 머무르시면 않됩니다.
: 아래의 경우 먼저 들어간 socket이 데이터를 마냥 기다리고 있으면 다른 소켓들은 그냥 앞선 socket 끝나기만
: 기다려야 겠죠.
:
: 데이터가 가끔 오면, 그리고 각 socket들이 서로 다르게 오면 프로세스가 돌 수도 있습니다만.
:
: 아마 연결하는 client쪽에서 time out 아 자주 발생할 수 있을 듯 합니다.
:
: Thread , CriticalSection, Synchronize 등등 좀 어려운 분야의 코딩입니다. 그러므로 좀더 정확한 코딩이 있어야만
: 문제가 없을듯 합니다.
:
: 소켓에서 데이터 읽은후 DB QUEUE 에 넣는 부분만 critical section으로 묶으세요..
:
:
: 수고하세요...
:
: 용맨소녀 님이 쓰신 글 :
: : 예전에 Indy9의 OnExecute에서 ADO쓸때 동기화에 관한 질문을 했었습니다. ADO호출시 Synchronize를 해야한다는 것이었는데요.. (전 OnExecute이벤트가 하나씩 순차 호출되는걸로 잘못 알고..ㅡ.ㅡ)
: :
: : 그럼... 패킷쪽도 같은 식으로 처리해야 하는거란 뜻인데요.. 그런거라면 Synchronize같은거 안쓰고 아예 패킷처리부를 크리티컬 섹션으로 덮어야하는게 깔끔하지 않나 생각됩니다. DB는 큐를 쓰면 될거고요..
: :
: : 예를 들어서.. 이렇게 한다면 대충 무난할까요? 지금 만드는건 패킷이 띄엄띄엄오는 거라 성능은 신경안쓰고 만들고 있지만.....
: :
: : 암튼, 아래 방식으로 한다면 크레이지아케이드류같은 게임에서 1000명은 커버할려나요? ^^
: :
: : 경험많으신 고수님들 답변 부탁드립니다..
: :
: : void __fastcall TWin_Main::ServerExecute(TIdPeerThread *AThread)
: : {
: : EnterCriticalSection(&Cs);
: : ProcessPacket(AThread); // 이 안에서 DB 관련은 큐로 처리..
: : LeaveCriticalSection(&Cs);
: : }
|