![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
|
Опции темы | Поиск в этой теме |
![]() |
#11 |
Новичок
Джуниор
Регистрация: 18.01.2008
Сообщений: 1,720
|
![]()
А как обычно. GetQueuedCompletionStatus либо вернёт ошибку, либо сообщит, что прочитано 0 байт. Дальше - GetLastError и по обстоятельствам...
|
![]() |
![]() |
![]() |
#12 |
Пользователь
Регистрация: 16.05.2008
Сообщений: 17
|
![]()
GetQueuedCompletionStatus возвращает "истину"... а в dwBytesXfered всегда ноль.
Надо ли перезапускать WSARecv после сробатывания события? Я перезапускаю. ![]() ...тут я ещё не заполнял структуру WSABUF... 1. WSARecv если нет данных а клиент не отключился возвращает -1, полсе этого, вызов WSAGetLastError возвращает WSA_IO_PENDING (типа, ждите данных). 2. WSARecv если нет данных? а клиент отключился возвращает 0, полсе этого, вызов WSAGetLastError возвращает тоже 0! и чего с этими нулями делать?... 3. Если данные пришли, но мало, и я не желаю их считывать ![]() может существует функция вроде socketstatus? - нет - а хотелось бы ![]() |
![]() |
![]() |
![]() |
#13 |
Новичок
Джуниор
Регистрация: 18.01.2008
Сообщений: 1,720
|
![]()
А. Главный поток.
1. Создаём completion port (далее с-порт) - CreateIoCompletionPort с параметрами по умолчанию. 2. создаём рабочий поток. 3. создаём overlapped сокет. 4. запускаем этот сокет - listen 5. "слушаем" 6. при поступлении коннекта копируем сокет - то, что вернула WSAAccept, создаём структуры данных для нового клиента, при этом не забываем про свою OVERLAPPED для каждого и прикручиваем этот "новый" сокет к с-порту через CreateIoCompletionPort - FileHandle - это "новый" сокет, ExistingCompletionPort - это наш изначальный c-порт, CompletionKey - адрес, например, нашей структуры. 7. Запускаем overlapped WSARecv. Буфер, естественно, указываем. ОС ведь должна куда-то поместить прочитанные данные. 8. возвращаемся к п. 5. Б. Рабочий поток. 1. Ждём GetQueuedCompletionStatus. При этом предполагается, что параметры мы передали верные, в документации указано, что мы получим иначе. 2. Если ввод/вывод завершился с ошибкой то получаем 0 и выясняем что за ошибка - GetLastError, сколько байт получили и т.п. Если сокет "весь вышел", значит закрываем его, "выбрасываем" данные, которые выделялись для коннекта и т.п. и к пункту 1. 3. Если в/в успешный, то получаем не 0, читаем/записываем куда-нибудь/выбрасываем пришедшие данные, если нужно что-нибудь отправить клиенту, значит overlapped WSASend, если продолжаем читать, значит WSARecv. возвращаемся к п. 1. Если необходимо организовать связь главного потока с рабочим, скажем для остановки операций, значит из главного отправляем некий оговоренный статус через PostQueuedCompletionStatus или начинаем аккуратно закрывать сокеты. Выделенные для коннекта данные, пока они находятся "внутри" GetQueuedCompletionStatus трогать нельзя, освобождает их, например, рабочий поток после ошибки если сокет закрылся или даже деструктор класса клиента, если угодно. |
![]() |
![]() |
![]() |
#14 |
Пользователь
Регистрация: 16.05.2008
Сообщений: 17
|
![]()
Спасибо! Подробно
![]() а что делать с хандлом созданым CreateIoCompletionPort, в конце, когда уничтожается рабочий поток CloseHandle()? просто про это нигде ничего не сказано... для WSASend и WSARecv, каждому своя overlapped структура? (проверять уже прийдётся не раньше чем через неделю. командировки в Питер и Новгород) |
![]() |
![]() |
![]() |
#15 |
Новичок
Джуниор
Регистрация: 18.01.2008
Сообщений: 1,720
|
![]()
Все ненужные хэндлы, естественно, закрываются через CloseHandle. Для каждого отдельного ввода и вывода должна быть своя overlapped, хотя после завершения в/в (именно с конкретной структурой) её (фактически, участок памяти) можно использовать заново. Если WSASend и WSARecv будут осуществляться одновременно, тогда у каждого должна быть своя, если строго по-очереди, то можно пользоваться одной (но, разумеется, в пределах данного сокета).
|
![]() |
![]() |
![]() |
#16 |
Пользователь
Регистрация: 16.05.2008
Сообщений: 17
|
![]()
Хорошо...
А можно пользоваться одновременно и WSA и обычными функциями? т.е. отправлять данные с помощью "send" а не "WSASend". мне допустим нужно отправлять данные пакетами асинхронно с приёмом, причём количество пакетов не известно и ждать завершения передачи "не хочеться" - когда освободится соответствующий буфер в overlapped структуре, не создовать же её для каждой процедуры передачи. в 100 строк не укладываюсь. Нужен ещё и тайм-аут для ожидания первого пакета клиента сразу после подключения, не пришлёт - отключить. Не тривиальная задачка то, получается ![]() |
![]() |
![]() |
![]() |
|
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Помогите оценить, сколько может стоить проект. Его покупают - сколько взять? | grenles | Свободное общение | 4 | 16.07.2008 09:38 |
Помогите подключиться к серверу. | КривойПрограммист | Помощь студентам | 1 | 27.10.2007 23:41 |
Сервер и несколько клиентов | Andr | Работа с сетью в Delphi | 10 | 17.09.2007 09:24 |
Как подключиться к серверу используя API функции? | BR17UY | Win Api | 3 | 16.04.2007 02:12 |
Создать список клиентов банка | Klyan | Паскаль, Turbo Pascal, PascalABC.NET | 3 | 15.01.2007 12:45 |