K>он не получает не только FD_READ но и FD_CLOSE при закрытии клиента. K>В чем может быть проблемма ?
FD_CLOSE вы не получаете, вероятно, потому что вы не считали данные, которые послал клиент.
FD_READ вы, возможно, теряете, сбрасывая событие при event.reset(). WSAEnumNetworkEvents атомарно сбрасывает событие, после чего оно может вновь установиться до вызова reset.
ЗЫ. Разбираться в таком коде не имея всех исходников — достаточно сложно. Никогда не понимал, для чего нужно делать обёртки для системных вызовов и типов, когда их можно использовать напрямую. При чём, какой-то выгоды именно для этого кода обёртки не дают, IMHO.
Здравствуйте, butcher, Вы писали:
B>FD_CLOSE вы не получаете, вероятно, потому что вы не считали данные, которые послал клиент. B>FD_READ вы, возможно, теряете, сбрасывая событие при event.reset(). WSAEnumNetworkEvents атомарно сбрасывает событие, после чего оно может вновь установиться до вызова reset.
B>ЗЫ. Разбираться в таком коде не имея всех исходников — достаточно сложно. Никогда не понимал, для чего нужно делать обёртки для системных вызовов и типов, когда их можно использовать напрямую. При чём, какой-то выгоды именно для этого кода обёртки не дают, IMHO.
Что за чушь вы говорите? В чем ошибка — Тут ясно как день (написал сообщением выше).
Обёртка делается обычно в виде классов, чтобы во время разработки приложения забыть про сокеты вообще. Это важно, когда сокеты не на первом месте стоят в реализации. Да и всегда так выгоднее сделать, чтобы не делать лишней работы.
Здравствуйте, cod3r_200, Вы писали:
_>Здравствуйте, k732, Вы писали:
K>>В чем может быть проблемма ?
_>во первых WSACreateEvent, во вторых WSAEventSelect делается после bind и до listen. и в третих проверяй ошибки от ф-ций. ВСЕ ОШИБКИ !
на счет WSACreateEvent не понял
сделат WSAEventSelect после bind и до listen — тоже самое
K>>он не получает не только FD_READ но и FD_CLOSE при закрытии клиента. K>>В чем может быть проблемма ?
B>FD_CLOSE вы не получаете, вероятно, потому что вы не считали данные, которые послал клиент. B>FD_READ вы, возможно, теряете, сбрасывая событие при event.reset(). WSAEnumNetworkEvents атомарно сбрасывает событие, после чего оно может вновь установиться до вызова reset.
закоментировал reset — ничего не поменялось
B>ЗЫ. Разбираться в таком коде не имея всех исходников — достаточно сложно. Никогда не понимал, для чего нужно делать обёртки для системных вызовов и типов, когда их можно использовать напрямую. При чём, какой-то выгоды именно для этого кода обёртки не дают, IMHO.
у меня событие (WsaEvent) и сокет (Socket) хранятся в std::map
и я забыл думать про закрытие сокета и т.п. все сделается в деструкторах — помоему очень удобно
Здравствуйте, cod3r_200, Вы писали:
B>>ЗЫ. Разбираться в таком коде не имея всех исходников — достаточно сложно. Никогда не понимал, для чего нужно делать обёртки для системных вызовов и типов, когда их можно использовать напрямую. При чём, какой-то выгоды именно для этого кода обёртки не дают, IMHO.
_>Что за чушь вы говорите? В чем ошибка — Тут ясно как день (написал сообщением выше). _>Обёртка делается обычно в виде классов, чтобы во время разработки приложения забыть про сокеты вообще. Это важно, когда сокеты не на первом месте стоят в реализации. Да и всегда так выгоднее сделать, чтобы не делать лишней работы.
Это не чушь. Не похоже что вы забыли про сокеты при разработке приложения. Но зато Ваш код стал неудобоваримым для всех кроме Вас самого. И "лишней работы" в нём не поубавилось...
Здравствуйте, k732, Вы писали:
K>Клиент шлет данные. WSASend говорит, что все прошло без ошибок, но сервер не получает события FD_READ.
<супер-мега-объектно-ориентированный код поскипан> K>В чем может быть проблемма ?
Неохота ковыряться в Вашем коде, но проблема скорее всего в том что сервер никак не дал знать WinSock2 что он хочет читать из сокета. Вызовите recv сразу после accept (вызов, ессно, обломится с WSAEWOULDBLOCK) и FD_READ установится, когда появятся данные для чтения.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Здравствуйте, k732, Вы писали:
K>>Клиент шлет данные. WSASend говорит, что все прошло без ошибок, но сервер не получает события FD_READ. MC><супер-мега-объектно-ориентированный код поскипан> K>>В чем может быть проблемма ?
MC>Неохота ковыряться в Вашем коде, но проблема скорее всего в том что сервер никак не дал знать WinSock2 что он хочет читать из сокета. Вызовите recv сразу после accept (вызов, ессно, обломится с WSAEWOULDBLOCK) и FD_READ установится, когда появятся данные для чтения.
попробовал — вызов обломался, но события так и не приходят
Здравствуйте, k732, Вы писали:
K>у меня событие (WsaEvent) и сокет (Socket) хранятся в std::map
Да.. Я бы проверил, все ли API функции получают параметры тех типов, которые они хотят, а не указатели на объекты каких-то непонятных им классов, массивы непонятного содержания и т.п.
K>и я забыл думать про закрытие сокета и т.п. все сделается в деструкторах — помоему очень удобно
По мне так лучше помнить всё что нужно и делать правильно, чтобы через пару лет взглянув на код не пришлось долго и мучительно рыться по всем исходникам, что бы удоствериться "делается ли в таком-то констукторе такое-то действие".
Но это так, лирика.. возможно это просто я привык ковыряться в Си'шном коде..
Здравствуйте, k732, Вы писали:
K>на счет WSACreateEvent не понял
K>сделат WSAEventSelect после bind и до listen — тоже самое
извиняюсь, я загнул насчет ошибок, ты всё верно проверяешь. И поменять местами тоже ничего не поменяет. А вот WSACreateEvent надо делать перед WSAEventSelect. А иначе оно просто на пустом евенте будет делать, и работать не будет. У сервера принцип примерно такой:
createsocket(); // серв сокет
bind(); // серв сокет
WSACreateEvent(); // для серв сокет. парная закрывающая - WSACloseEvent
WSAEventSelect(); //серв сокетwhile (true) {
//цикл бесконеч.
//внимательно!!! для TCP указывать нада
//таймаут обязательно. в районе 10-15 мс. Иначе попа.
Err = WSAWaitForMultipleEvents;
if(Err OK?) {
Err2 = WSAEnumNetworkEvents();
if(Err2 OK?) {
//проверяем нужные поля
//если есть FD_ACCEPT
//то мы принимаем сокет и опять крутим цикл.
//т.е. мы создаем Event новый и добавляем в массив.
//для него тоже потребуется WSAWaitForMultipleEvents, как для сервер. сокета.
} else {
//проверим ошибку
}
} else {
//проверить ошибку
}
}
задачу можно усложнить вплоть до пула потоков и расчета нагрузки + защиты от DDoS атаки.
так что это очень простой пример.
Здравствуйте, Michael Chelnokov, Вы писали:
MC>Это не чушь. Не похоже что вы забыли про сокеты при разработке приложения. Но зато Ваш код стал неудобоваримым для всех кроме Вас самого. И "лишней работы" в нём не поубавилось...
думал я над этим, в итоге реализовал "обертку" в виде удобных классов. Они подойдут для большинства проектов, с поддержкой сети. Но есть вещи поважнее, чем эти сокеты. лучше сразу сделать высокоуровневую обертку и забыть про них до конца разработки проги. ИМХО.
Здравствуйте, cod3r_200, Вы писали:
_>Здравствуйте, k732, Вы писали:
K>>на счет WSACreateEvent не понял
K>>сделат WSAEventSelect после bind и до listen — тоже самое
_>извиняюсь, я загнул насчет ошибок, ты всё верно проверяешь. И поменять местами тоже ничего не поменяет. А вот WSACreateEvent надо делать перед WSAEventSelect. А иначе оно просто на пустом евенте будет делать, и работать не будет. У сервера принцип примерно такой: _>
_>createsocket(); // серв сокет
_>bind(); // серв сокет
_>WSACreateEvent(); // для серв сокет. парная закрывающая - WSACloseEvent
_>WSAEventSelect(); //серв сокет
_>while (true) {
_> //цикл бесконеч.
_> //внимательно!!! для TCP указывать нада
_> //таймаут обязательно. в районе 10-15 мс. Иначе попа.
_> Err = WSAWaitForMultipleEvents;
_> if(Err OK?) {
_> Err2 = WSAEnumNetworkEvents();
_> if(Err2 OK?) {
_> //проверяем нужные поля
_> //если есть FD_ACCEPT
_> //то мы принимаем сокет и опять крутим цикл.
_> //т.е. мы создаем Event новый и добавляем в массив.
_> //для него тоже потребуется WSAWaitForMultipleEvents, как для сервер. сокета.
_> } else {
_> //проверим ошибку
_> }
_> } else {
_> //проверить ошибку
_> }
_>}
_>
_>задачу можно усложнить вплоть до пула потоков и расчета нагрузки + защиты от DDoS атаки. _>так что это очень простой пример.
Может я ошибаюсь, но в строчке "OnSelect (socket, FD_ACCEPT | FD_CLOSE);" ты явно указываеш флаги событий которые будут срабатывать. Попробуй поставить туда FD_READ и FD_CLOSE
P.S. Сам занимаюсь подобной проблемой. Очень понравился код — респект.
Здравствуйте, k732, Вы писали:
K>В чем может быть проблемма ?
знаю что дата уже давно просрочена . И всё таки истина должна востаржествовать.
Проблема в том что нельзя просто копировать HANDLE и сокеты. Они будут работать только в единственной копии. А сдесь же:
K>m_map[event] = socket; K>WsaEvent event = m_events [index — WSA_WAIT_EVENT_0];
и т.д.
при замене таких копий на операции взятия адреса или просто исключая их, всё начинает работать. проверил.