#winapi #readfile #io-completion-ports
#winapi #readfile #порты завершения ввода-вывода
Вопрос:
Я хочу реализовать сервер / клиент, используя именованные каналы (для IPC).Я использую асинхронные (перекрывающиеся) соединения и порт завершения ввода-вывода (я много искал, и кажется, что это самый эффективный способ сделать это).
Сначала вот коды:
сервер: http://pastebin.com/XxeXdunC
и клиент: http://pastebin.com/fbCH2By8
Проблема в сервере (я могу улучшить клиент, но я сделаю это, когда сервер заработает).
Я использую порт завершения ввода-вывода следующим образом: по сути, я запускаю поток, в котором вызываю ReadFile(). Если он возвращает TRUE, я получаю все данные, если он возвращает FALSE, и ошибка ERROR_IO_PENDING, я жду с GetQueuedCompletionStatus().
Странно то, что, даже если я прочитал все данные, последний вызов ReadFile () завершается неудачно, и возникает ошибка ERROR_IO_PENDING
Поток, в котором я вызываю ReadFile(), начинается со строки 64 серверного кода.
Клиент отправляет 24 байта (строка «салют, c’est le client!»), а буфер ReadFile () имеет длину 5 байт (чтобы проверить, как мой сервер обрабатывает данные, размер которых превышает буфер Readfile())
Вывод:
waiting for client...
WaitForMultipleObjects : 0
client connected (1)
ReadFile 1 msg (5 -> 05) : salut
ReadFile 2 msg (5 -> 10) : salut, c'e
ReadFile 2 msg (5 -> 15) : salut, c'est le
ReadFile 2 msg (5 -> 20) : salut, c'est le clie
ReadFile 2 msg (4 -> 24) : salut, c'est le client !
ReadFile2: ERROR_IO_PENDING
GQCIOS 0 255 003D3A18
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 5 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
GQCIOS 4 255 003D3A2C
ReadFile3: ERROR_IO_PENDING
ReadFile1: ERROR_IO_PENDING
Чего я не понимаю, так это того, что даже если я прочитаю все данные, ReadFile() все равно вернет ожидающую операцию (это сообщение об ошибке «ReadFile2: ERROR_IO_PENDING» после последнего вывода «msg»)
Мой цикл неправильный? Я неправильно использую ReadFile() / GetQueuedCompletionStatus() ?
Спасибо
Комментарии:
1. Проблема, похоже, в режиме канала. Я должен использовать режим сообщений (клиент и сервер), но это не помогает: первый вызов ReadFile() завершается неудачно, количество прочитанных байтов равно 0, а ошибка — ERROR_MORE_DATA. Хотя такая ошибка является нормальной, где хранятся первые 5 байт?
Ответ №1:
Где ваша функция, связанная с записью? похоже, что ваш код расположен в неправильном порядке. Сначала должна быть вызвана _read_data_cb
процедура GetQueuedCompletionStatus
, затем, в зависимости от lpOverlapped
параметра, полученные данные должны быть готовы в буфере, который вы указали в функции ReadFile. Поскольку вы вызываете Readfile, не проверяя, OVERLAPPED
является ли это перекрывающейся структурой для контекста отправки или recv, вы не получаете ожидаемый результат. Следующий код должен прояснить ситуацию:
while(TRUE)
{
bReturnValue=GetQueuedCompletionStatus(pIOCPServer->m_pIOCP, amp;dwBytesTransferred,(DWORD *)pClient,reinterpret_cast<LPOVERLAPPED*>(amp;pOverlapped),INFINITE);
if(!bReturnValue)
{
if(NULL==pOverlapped)
continue;
else
break;
}
else
{
if(pOverlapped==NULL)
continue;
}
if(dwBytesTransferred==0)
break;
if(lpOverlapped==amp;(pClient->m_pRecvContext->overlapped))
pClient->handleRecvEvent(dwBytesTransferred)
else if(lpOverlapped==amp;(pClient->m_pSendContext->overlapped))
pClient->handleSendEvent(dwBytesTransferred)
}
...