[완료]WSAGetLastError()에 대해 질문드립니다.
글쓴이: richjaff / 작성시간: 금, 2010/05/21 - 10:52오후
IOCP 부분에서 입/출력이 끝날때마다 에러 검사를 하기 위해
WSAGetLastError()를 호출하는 부분이 필수적으로 붙게됩니다.
이 에러 검출용 코드의 경우 동기화가 필요한가요?
예를 들어서, A라는 워커쓰레드에서 발생한 에러를 멀쩡하게 IO를 잘 수행중인 B 워커쓰레드에서
A에서 일어난 에러를 받는 현상이 있을 수 있는지 궁금합니다.
두번째 궁금한점은, WSAGetLastError()코드의 경우, WSASend, WSARecv에만 반응하고
다른 네트워크 함수인 closesocket이나 accept와 같은 코드에는 반응을 안하는지 궁금합니다.
이 두가지 사항에 대해 조언 좀 부탁드립니다.
Forums:
첫번째 경우는
첫번째 경우는 다음과 같은 언급이 있습니다. WGLE는 한 쓰레드안의 모든 소켓용이고, getsockopt + SO_ERROR 은 소켓마다 지정되는 것입니다. IOCP의 워커들은 계속 변할 것이기 때문에 조금 혼동될 소지가 있어 보이는군요.
두번째는 문서의 리턴 값에 대한 설명을 보시면 됩니다.
p.s. 문서를 꼼꼼히...
답변 감사드립니다.
두번째 문제는 해결했습니다.
하지만, 첫번째가 아직도 걸리네요.
자꾸 아래의 문제가 발생합니다.
=================== 어셉트 쓰레드 부분 =================================
어셉트 완료 시점부터
if( WSARecv(cPtr->sock, &(cPtr->iworkstream->wsabuf), 1, &recvbytes,&flags, &(cPtr->iworkstream->overlapped), NULL) == SOCKET_ERROR ){
if(WSAGetLastError() != WSA_IO_PENDING){
com.PushDataString("[IOCP]Client Recv Requirment Failed.");
chmap.SetDisconnect(cPtr->charPtr); // 캐릭터 맵부분 삭제
cPtr->status = OFFLINE; // 오프라인으로 셋팅
RequirCloseConn(cPtr); // 쓰기 작업 중일때는 오프라인 상태표시만 하고 스킵함. (이후에 전송 완료 작업이 통보되고 나서 IO핸들을 모두 삭제.
continue;
}
}
위에서 소켓에 대한 입출력이 실패하고 난뒤에 실패된 소켓에 대한 완료 통보가 올 수 있나요?
현재 몇십분에 한번꼴로 나타나는 에러의 상황을 말씀드리자면,
1.어셉트 부분이 성공하고 초기 리시브 요청을 실시한다.
2.WSAGetLastError로 확인을 실시한다.
3.초기 리시브 요청에서 실패한다고 떴으므로 종료과정을 실시한뒤 continue 시킨다.
4.워커쓰레드로 분명 위에서 실패했다고 뜬 IO요청에 대해 완료통보가 온다. << (문제의 상황)
지금 나타나는 것이 이런 경우입니다.
ps.방금 WSAGetLastError 관련해서 따로 소스를 코딩해서 테스트 해봤는데 역시나 좀 이해하기 힘든 결과가 나왔습니다.
테스트한 소스 전체를 다른 글에 새로 올리겠습니다.
============= 추가 수정 =====================================
제대로 테스트 해보니 WSAGetLastError는 확실히 쓰레드에 독립적이더군요.
뭐가 문제인지 좀더 꼼꼼히 확인해봐야할것 같습니다.
답변 주셔서 감사합니다.
위의 현상이 나타나는 이유를 찾았습니다.
어셉트 쓰레드에서 다음 구문이 실행되어지는 것보다 워커쓰레드의 완료통보의 반응이 훨씬 빠를때 생기는 문제더군요;
실제로 워커쓰레드 2개만으로 동접 180명까지 받아서 원활한 게임처리를 했을 정도니 IOCP의 성능이 참 대단한것 같습니다.
그리고 비동기IO 작업 실패시에는 완료통보로 뜨지않는것이 확실하더군요.
위에서 나타난 문제는 다음처럼 코딩했기 때문이었습니다.
============ 어셉트 쓰레드 =============================
어셉트 수행
최초 WSARecv 수행;
Synchronized
{
클라이언트 리스트에 추가
}
============= 워커 쓰레드 ==============================
완료 통보
Synchronized
{
클라이언트 리스트에 존재하는지 체크함.
}
======================================================
위에서 최초 읽기작업이 요청되고 난뒤였는데 워커쓰레드에서 먼저 더 빠르게 완료통보가 내려오고
임계구역에 진입하는 바람에, 없는 클라이언트 리스트로 떴었던 것인데,
동기화 블록 배치를 바꿔서 이문제는 해결했습니다.
조언 주셔서 정말 감사드립니다.
댓글 달기