сервер, использующий перекрывающийся именованный канал: как использовать GetOverlappedResult () с ReadFile ()? - PullRequest
1 голос
/ 02 апреля 2011

Я написал сервер и клиент, которые используют перекрывающийся именованный канал.Моя проблема в основном с Readfile () и GetOverlappedResult ().

Обратите внимание, что эта программа является тестовым кодом.Позже он будет интегрирован в среду (я портирую код linux на unix, который использует семейство адресов AF_UNIX для соединений с сокетами)

Я описываю серверную часть.У меня есть 2 потока:

1) основной поток открывает перекрывающийся именованный канал, затем зацикливается на WaitForMultipleObjects ().WaitForMultipleObjects () ожидает 3 события: первое ожидает подключения клиента.2-й позволяет мне чисто выйти из программы.Третий сигнализируется, когда операция ожидает в ReadFile ().

2) Второй поток запускается при подключении клиента.Он зацикливается на ReadFile ().

Вот код сервера:

http://pastebin.com/5rka7dK7

Я в основном использовал MSDN doc (именованный канал-сервер с использованием перекрывающегося ввода-вывода, названныйтруба клиента), SDK и другие документы в Интернете, чтобы написать этот код.Посмотрите в [1] код клиента.Код клиента нуждается в некоторой любви, но сейчас я сосредоточен на том, чтобы сервер работал идеально.

В коде сервера есть 4 функции (я забыл функцию, которая отображает сообщения об ошибках):

a) svr_new: он создает перекрывающийся именованный канал и 3 события и вызывает ConnectNamedPipe ()

b) svr_del освобождает все ресурсы

c) _read_data_cb: поток, вызывающий ReadFile ()

d) функция main () (основной поток), которая зацикливается на WaitForMultipleObjects ()

Моя цель - обнаружить в _read_data_cb (), когда клиент отключается (сбой ReadFile ()и GetLastError () возвращает ERROR_BROKEN_PIPE) и когда данные поступают от клиента.

Что я не понимаю:

  • Должен ли я вызывать GetOverlappedResult ()?
  • Если да, то где?Когда ReadFile () завершается неудачно и GetLastError () возвращает ERROR_IO_PENDING (строка 50 вставки)?Когда WaitForMultipleObjects () возвращает (строка 303 вставки, я прокомментировал код там)?Где-то еще?
  • Я делаю ResetEvent события ReadFile (), когда WaitForMultipleObjects () возвращает (строка 302 вставки).Это правильное место для его вызова?

С кодом, который я вставил, вот результат, если клиент отправляет эти 24 байта (буфер ReadFile () имеет размер 5 байтов. Я намеренно установилэто значение, чтобы проверить, что делать, если клиент отправляет некоторые данные, превышающие размер буфера ReadFile ()

: «salut, c'est le client!»

output:

$ ./server.exe ожидает клиента ... WaitForMultipleObjects: 0 клиент подключен (1) WaitForMultipleObjects: 2 * ReadFile: 5 WaitForMultipleObjects: 2 * ReadFile: 5 WaitForMultipleObjects: 2 * ReadFile: 5 WaitForMultipleObjects: 2 * ReadFile5 WaitForMultipleObjects: 2 * ReadFile: 4

Примечание: WaitForMultipleObjects () может быть вызвано меньше, чем это кажется случайным.

Итак, в моем коде я не вызываю getOverlappedResult (),ReadFile () завершается успешно (il читает 5 * 4 + 4 = 24 байта), но я не знаю, когда операция чтения завершится.

Примечание: я добавляю printf (), когда ReadFile () завершается неудачно сERROR_IO_PВ завершение, этот printf () вызывается бесконечно.

Кроме того, клиент отправляет 2 сообщения.Один выше, а другой через 3 секунды.2-е сообщение никогда не читается и ReadFile () завершается с ошибкой ERROR_SUCCESS ... (если быть точным, ReadFile () возвращает FALSE, а GetLastError () возвращает ERROR_SUCCESS)

Итак, я полностью потерян.Я искал часы в Интернете, в MSDN, в коде SDK (Server32.c и Client32.c).Я до сих пор не знаю, что делать в моем конкретном случае.

Итак, кто-то объяснит мне, как использовать GetOverlappedResult () (если я должен его использовать), чтобы узнать, как проверить, завершена ли операция чтения и где?И даже, если кто-то может исправить мой код :-) Я дал код, чтобы каждый мог его протестировать (я нахожу много документов в интернете, но это почти всегда не точно:* спасибо

[1] http://pastebin.com/fbCH2By8

1 Ответ

1 голос
/ 02 апреля 2011

Посмотрите на порты завершения ввода / вывода.На мой взгляд, это самый эффективный способ получения и обработки уведомлений о перекрывающихся операциях в Windows.Поэтому в основном вам нужно будет использовать GetQueuedCompletionStatus и GetQueuedCompletionStatusEx в режиме блокировки и неблокирования, когда вы будете готовы обрабатывать новые события завершения, вместо того, чтобы время от времени вызывать GetOverlappedResult.На самом деле, вы даже можете полностью избавиться от WaitForMultipleObjects.

Кроме того, на какую разновидность Unix вы нацеливаетесь?В Солярисе есть очень похожая абстракция.Проверьте man port_create.

К сожалению, в Linux нет ничего подобного.Сигналы (в том числе в режиме реального времени) могут в некоторой степени использоваться в качестве ожидаемых объектов завершения, но они не являются такими полными, как порты в Windows и Solaris.

...