2012-09-03 13 views
0

지난 며칠 동안 나는 직면하고있는 내 문제 중 하나를 해결하는 방법에 대해 생각해 봤지만 주제를 연구하려고 시도했지만 실제로 무엇을 할 수 있는지 알지 못했습니다. .동일한 컨테이너에있는 IOCP 다중 소켓 완성 포트

동일한 소켓에 동일한 소켓을 가진 두 개의 소켓이 있습니다. 문제는 둘 다 서로 다른 프로토콜을 사용한다는 것입니다. 어떤 소켓이 트리거되는지 알 수있는 방법이 있습니까? 그들의라는 game_socket 및 client_socket

예제 코드는 ...

while (true) { 
error = GetQueuedCompletionStatus(CompletionPort, &BytesTransfered, (PULONG_PTR)&Key, &lpOverlapped, 0); 
srvc = CONTAINING_RECORD (lpOverlapped, client , ol); 
if (error == TRUE) { 
cout << endl << "SOCKET: [" << srvc->client_socket << "] TRIGGERED - WORKER THREAD" << endl; 
cout << endl << "BytesTransfered: [" << BytesTransfered << "]" << endl; 

if (srvc->game_client triggered) { 
// .. this code 
} else { 

// .. this code 
} 

어떤 아이디어 뭔가 같은 것 또는 도움을 주시면 감사하겠습니다 :) 당신이 사용하고 중첩 된 확장 구조가 이상적으로 적합하다

답변

2

특정 연결 인스턴스입니다. 예를 들어,이 구조체는 작업이 수행되는 소켓뿐만 아니라 작업도 포함해야합니다. 예를 들어, 읽기 또는 쓰기가 가능한 소켓의 IO 완료는 IO 요청이 시작된 시점의 상태를 반영해야합니다. IOCP 기반 클라이언트/서버 코드의 대부분은이 일반적인 이데올로기를 증명합니다.

귀하의 경우 두 개의 서로 다른 소켓에 두 개의 독립적 인 동작이있는 동일한 OVERLAPPED 구조를 사용하지 않아야합니다. 소켓이 어떤 의미에서 '관련'있다면 그것은 당신의 OVERLAPPED 구조체 밖에서 추적되고 관리되어야합니다. 각각은 고유 한 IO 완료를 위해 고유 한 구조를 가져야합니다. 다른 것은 정직하게 두통을 요구하고 있습니다.

내가 말하는 바를 수용하기 위해 현재 구성표를 변형하는 것과는 거리가 멀다. 나는 항상 자신이 듣는 것을 싫어하기 때문에 "그렇게해서는 안된다"고 대답하는 것을 꺼려하지만,이 경우에는 보증할만한 것이 아닙니다.

모두 최고입니다.

+0

난 그 두려워했다. WSAEnumNetworkEvents를 사용하여 WSAEventSelect와 같은 여러 가지 작업을 시도했지만 아무 것도 작동하지 않았습니다. : – User

+0

당신이 생각하는 것만 큼 나쁘지 않을 수도 있습니다. 여러 소켓에 동일한 IOCP를 문제없이 사용할 수 있습니다. 각 IO 요청이 하나의 OVERLAPPED 구조와 연결되어 있는지 확인하십시오. 소켓은 어떤 객체 인스턴스에서 관리되고 있으며 둘 다 IOCP에서 잠재적으로 기다리고있는 경우 각 객체는 객체에 링크 된 확장 된 OVERLAPPED 구조를 가질 것입니다 * 및 * 어떤 소켓이 해당 OVERLAPPED 데이터로 표시되는 IO 요청에 참여하고 있는지 식별해야합니다 나는 그것을 이해할 수 있기를 바란다. 당신은 이것을 할 수있다, 조금 더 생각해라. – WhozCraig

+0

나는 그런 것들을해야만 할 것이라고 생각했다! 답장을 보내 주셔서 감사 드리며, 나는 몇몇 작은 테스트 서버 . :) – User

3

IOCP를 사용할 때 비동기 작업마다 사용할 수있는 두 가지 사용자 데이터 항목이 있습니다.

첫 번째 항목은 "연결 당"데이터 인 완료 키이며 소켓 핸들러와 기존 완료 포트를 사용하여 CreateIoCompletionPort()를 호출하여 파일 핸들이나 소켓을 완료 포트에 연결할 때 설정됩니다. 이 값은 주어진 연결에 대한 GetQueuedCompletionStatus() 호출마다 반환됩니다.

두 번째는 "작업 당"데이터 인 '확장 된 중복 된'구조입니다. 각 동시 작업에는 고유 한 중복 구조가 할당되어야합니다 (MUST).

위 디자인에서 "연결 별"데이터를 사용하여 연결을 식별해야합니다. 연결되어있는 두 개의 연결 (소켓)이 있으므로 연결의 각면에 하나씩 두 개의 연결된 클래스가 있습니다. 클래스 (또는 C++ 대신 C를 사용하는 경우 struct)는 소켓의 나머지 절반에 대한 포인터와 연결 유형을 나타내는 플래그를 보유합니다. C++을 사용하는 경우이 두 클래스는 공통 기본 클래스에서 파생되므로 완료 함수가 나타내는 연결 유형을 결정하는 멤버 함수를 호출 할 수 있습니다. C를 사용하는 경우 차별화 된 공용체를 사용하십시오.

그런 다음 완료 키를 기본으로 전송 한 다음 보유하고있는 연결 유형을 확인하고 올바른 클래스/구조로 전송하십시오. 이제 조작이 수행 된 연결을 알 수 있습니다. 연결 클래스는 해당 프로토콜을 실행하는 상태 시스템의 모든 상태를 저장할 수 있습니다.

Criag에서 언급 한 것처럼 각 겹쳐진 구조는 "작업마다 고유"이며 IOCP 코드에서 이것은 작업의 데이터 버퍼에 대한 액세스를 허용하는 경향이 있으며 작업이 무엇인지 알려주는 플래그입니다 (읽기/쓰기/수락)./연결 등).

하나의 잠재적 인 복잡성은이를 사용하는 모든 처리 작업이 완료 될 때까지 작업 당 및 연결 당 데이터를 유지하는 것입니다. 개인적으로 연결 당 및 작업 데이터에 대한 참조 계산을 선호하지만 다른 방법이 있다고 확신합니다.

내가 (A '두 개의 연결'예제를 제공하지 않습니다하지만) 이러한 개념을 사용 IOCP에 대한 몇 가지 예제 코드를 가지고, 당신은 여기에서 다운로드 할 수 있습니다 : http://www.serverframework.com/products---the-free-framework.html

+0

이것은 제 의견으로는 받아 들여진 것보다 더 정확한 대답입니다. 'CompletionKey' 값은 정확히이 경우 사용할 수있는 값입니다. – Damon

+1

Damon; 작업 당 OVERLAPPED가 별도로 필요합니다. 한 번에 두 개 이상의 읽기 또는 한 번 쓰기가 보류 된 간단한 시스템에서는 소켓 당 하나의 별도 OVERLAPPED 만 있으면 충분합니다. 더 복잡한 것은 동시 작업의 고유 한 OVERLAPPED PER을 필요로합니다. 나는 심지어 간단한 트랜잭션 서버조차도 다음 recv가 현재 작성한 응답을 처리 한 후에 현재 recv 완료를 처리 할 때 문제가된다면 더 잘 작동하는 경향이 있다는 것을 발견했다. –

+0

죄송합니다. 내 말씨가 오도 된 것입니다 (또는 실제로 잘못되었습니다). 예, 당신은 발사하는 각각의 단일 요청 (예 : sendto 또는 readfile)에 대해 고유 한 'OVERLAPPED'에 대한 메모리 위치를 제공해야합니다. 그러나 이것은 OS가 필요로하는 많은 유용한 정보가없는 "불투명"블록입니다. (나는 다른 데이터를 피기 백하기 위해 그것들을 사용한다). 위의 "화장품 때문에, 그것이 필요하지 않기 때문에"나는 대기 상태가되었을 때 채워지는 쓰레기 같은 종류의 쓰레기를 생각했지만 두 번째 생각으로는 효과가 없을지라도 동시 스레드로 안정적으로. – Damon