나는 TCP/IP IOCP 서버 응용 프로그램에서 작업 해왔다.IOCP를 사용하는 TCP/IP 서버. 수신 버퍼의 가끔 데이터 손상
필자는 성능 (TCP 처리량 테스트 유틸리티와 비슷해 보입니다)을 테스트했으며 데이터 무결성을 테스트했습니다. 여기에서 "이상한 점"이 있습니다.
초기 테스트에서 테스트 클라이언트가 1MB 블록의 데이터를 반복적으로 보내고 그 블록이 순차적으로 증가하는 정수 시퀀스 인 곳으로 지정하기로 결정했습니다. 내가받은 각 데이터 버퍼가 그 버퍼의 누락 된 데이터와 일치하는지, 다른 버퍼와는 독립적으로, 즉 스레드가 완료된 수신을 처리하는 순서를 걱정할 필요가 없다는 것을 의미한다는 것을 확인할 수 있다는 아이디어입니다. (확인하려면 버퍼에서 첫 번째 정수를 추출하고 앞으로 스캔하고 클라이언트가 보내는 최대 값을 만나면 예상 값을 0으로 재설정합니다. 각 데이터가 4의 배수인지 확인하는 검사도 있습니다. (4 바이트 정수이므로)).
가끔씩 버퍼 내에서 데이터가 누락 된 무작위 블록이있는 것처럼 보이면 값이 1 씩 올라가고 한꺼번에 건너 뛰게됩니다. 코드는 꽤 단순하고 많은 부분이 아닌 것처럼 보입니다. 나는 원래 Delphi에서 테스트를 작성했지만 이러한 문제가 발생하면 Visual Studio 2010 C++에서 버전을 다시 작성하고 동일한 문제 (또는 적어도 매우 유사)를 갖는 것으로 보입니다.
실제 시스템에는 분명히 더 많은 코드가 있지만 작업 스레드에서이 코드를 거의 다룰 수 있습니다. 완료된 수신을 처리하고 버퍼의 데이터를 확인한 다음 다시 게시합니다. 처음 연결을 수락 한 후에 두 개의 겹쳐진 구조를 만들고 각각에 1MB 버퍼를 할당 한 다음 각각에 대해 WSARecv를 호출합니다. 두 번에 실수로 같은 버퍼를 공유하지 않는다고 다시 확인했습니다. 그런 다음, 다음이를 다시 실행됩니다 무엇을 꽤 많이 있습니다 : 어쩌면
DWORD numberOfBytesTransferred = 0;
ULONG_PTR completionKey = NULL;
PMyOverlapped overlapped = nullptr;
while (true)
{
auto queueResult = GetQueuedCompletionStatus(iocp, &numberOfBytesTransferred, &completionKey, (LPOVERLAPPED *)&overlapped, INFINITE);
if (queueResult)
{
switch (overlapped->operation)
{
case tsoRecv:
{
verifyReceivedData(overlapped, numberOfBytesTransferred); // Checks the data is a sequence of incremented integers 1 after the other with no gabs
overlapped->overlapped = OVERLAPPED(); // Reset the OVERLAPPED structure to defaults
DWORD flags = 0;
numberOfBytesTransferred = 0;
auto returnCode = WSARecv(socket, &(overlapped->buffer), 1, &numberOfBytesTransferred, &flags, (LPWSAOVERLAPPED) overlapped, nullptr);
break;
}
default:;
}
}
}
나는 위의 내 간단한 테스트에 오류 또는 추가 정보의 어떤 종류를 취급하고 있지 않다? 나는 원래 IOCP 클라이언트가 데이터를 보내고 있지만 Indy 블로킹 소켓을 사용하는 Delphi에서 또 하나의 매우 간단한 것을 작성했습니다. 기본적으로 연결된 코드 라인입니다.
while true do
begin
IdTCPClient.IOHandler.WriteDirect(TIdBytes(BigData), Length(BigData));
end;
는 또한 다른 비동기 소켓 구성 요소를 사용하여 다른 서버를 쓰고 나는 그것이 적어도 아직, 위의 않습니다 내 IOCP 예제로 수신 된 데이터에 문제가 감지 없었어요. 나는 더 많은 코드와 아마도 컴파일 할 버전을 게시 할 수 있지만, 내가 명백한 것을 놓친 경우를 대비해 위를 게시 할 것이라고 생각했다. 소켓 하나당 하나의 수신 및 하나의 전송을 사용하는 것이 좋다고 생각하지만 성능 향상을 위해 둘 이상을 게시하는 것이 타당하다는 것을 이해합니다.
Hmmm ... '또한 각 데이터가 4의 배수인지 확인하는 체크가 있습니다 (4 바이트 정수이기 때문에.) 어떻게 각 버퍼가 4 바이트의 정확한 배수를 포함하는지 보장합니다. TCP 스트림? 당신이 그 체크 아웃을하는 것이 좋습니다. –
당신은 맞습니다. numberOfBytesTransferred가 4의 배수인지 확인하고 그것이 발견되면 테스트를 중단하는 것이 보장됩니다. 나는 4의 배수가되는 버퍼를 일관되게 전달했다. (나는 로컬에서 테스트 중이며 클라이언트는 연속적인 청크를 보내고 있다고 가정한다.) 체크가 트리거 된 유일한 시간은 내가 디버거를 다시 시작한 후 다음 버퍼가 홀수 일 때가 있습니다. 정수가 유효한 범위를 벗어 났으므로 명확합니다. – David