
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Хочу сделать следующее:
Клиент на Винмобаил каждые 20мС(желательно) шлет на сервер несколько байт. Сервер шлет ему свои несколько байт, затем подготавливает данные для следующего раза. Клиент будет только один. Для опытов я сделал оконные клиент и сервер на ВинХР на "большом" компе, пока без таймера. Попытка реализовать это увенчалась частичным успехом , все работает,но только один раз ![]() ![]() Если если перезапустить сервер, то клиент может послать еще одно сообщение. Пробовал консольный сервер из "Самоучителя по игре.." ,c ним все работает, ну так он сам все время "висит" в while(1). Думаю, я что-то в принципе не так делаю , поэтому код приводить смысла нет.Может, кто подскажет как надо. Пишу на Си. |
Сообщ.
#2
,
|
|
|
Ну, сервер UDP обязан висеть на recvfrom()- иначе это не сервер, а одноразовый шприц.
![]() |
Сообщ.
#3
,
|
|
|
Цитата Oleg2004 @ Ну, сервер UDP обязан висеть на recvfrom()- иначе это не сервер, а одноразовый шприц. ![]() Почему ? Лучше висеть на select. Сделаем так: 1. Для UDP нет разницы - "клиент" и "сервер" это будет почти одна и та-же программа. Тот, кто начинает обмен, называется клиентом. 2. Для удобства (отладки) клиент будет слушать один порт, сервер - другой. 3. С некоторым тайм-аутом ожидаем приёма сообщения. исключительно для того, чтобы опросить, например, клавиатуру и корректно завершить приложение. 4. Если сообщение получено проверим опять же селектом готовность к передаче и пошлём ответ. 5. Проверим условие на окончание работы приложения. Если нет, всё повторим с пункта 3. Разница между клиентом и сервером только в том, что клиент первым посылает сообщение, а потом ожидает приёма. Послать сообщение можно в том числе и по нажатию какой - либо клавиши в пункте 5. |
Сообщ.
#4
,
|
|
|
Цитата Oleg2004 @ обязан висеть Висеть, но не вешать все. Цитата ЫукпШ @ Лучше висеть на select. У меня он вообще не используется ! ![]() Ну я еще тот пограмист ![]() Все решилось вставкой бесконечного цикла в процесс с recvfrom. Спасибо. |
Сообщ.
#5
,
|
|
|
Если верить StackOverflow, то вот работающий рецепт на select http://stackoverflow.com/questions/1559208...ith-select-in-c
Хотя я для UDP тоже гоняю recvfrom в цикле - и пока проблем не ощутил. |
Сообщ.
#6
,
|
|
|
Сообщ.
#7
,
|
|
|
Цитата ЫукпШ @ Лучше висеть на select. Кто бы сомневался... ![]() К сожалению, я именно это и предполагал, предложив топикстартеру цикл с recvfrom. Цитата Alexei @ У меня он вообще не используется ! ![]() Ну я еще тот пограмист ![]() Все решилось вставкой бесконечного цикла в процесс с recvfrom. ![]() Добавлено Цитата ЫукпШ @ 1. Для UDP нет разницы - "клиент" и "сервер" это будет почти одна и та-же программа. Тот, кто начинает обмен, называется клиентом. И с этим согласен, да вот только на сервере bind()обязателен, а на клиенте - три варианта - без бинда, с коннектом или биндом... |
Сообщ.
#8
,
|
|
|
Рад что вас развеселил!
![]() Вобщем у меня как-то все работает, но я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты , так что , наверно, имеет смысл прислушаться к вашим советам по select. Хотя, мне больше понравился EventSelect. Но все примеры даны для консольных программ, а у меня будет оконная(в винмоб , помоему, других нет) . Поэтому никто не будет так любезен показать структурно, как это будет выглядеть в оконной программе? |
Сообщ.
#9
,
|
|
|
Цитата Alexei @ ... я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты , так что , наверно, имеет смысл прислушаться к вашим советам по select. Это не совсем понятно. Надо разбираться. Дело в том, что обмен с сервером DNS производится посредством UDP. И если бы дело действительно было так плохо, интернет-сёрфинг был бы не возможным. Или не комфортным. Торрент - клиенты тоже (вроде) используют UDP для передачи информации. |
Сообщ.
#10
,
|
|
|
Цитата Alexei @ но я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты Какой смысл вы вкладываете в понятие "деформированные" пакеты? Насчет Eventselect () MSDN http://msdn.microsoft.com/en-us/library/aa925696.aspx утверждает, что API для винмобиле не включает WSAEventSelect()или WSAAsyncSelect(). Сколько я помню, все варианты для мобильных систем работают на базе спецификации Винсок 1.1 А вот select() там есть. Поэтому чисто оконного сетевого приложения найти будет трудно. Придется писать скажем в идеологии консоли, а потом код трансформировать в оконное приложение. Цитата Alexei @ как это будет выглядеть в оконной программе? Для начала вы должны познакомиться с идеологией работы оконных приложений. Оконное приложение всегда "висит" в цикле обработки сообщений. Сообщения приходят от системы и передаются по хендлу окна, а обработчик сообщений выполняет необходимые действия. Это так, быстро и на пальцах... ![]() |
Сообщ.
#11
,
|
|
|
Цитата Oleg2004 @ А потом этот код вынести в отдельный поток и не думать особо об окнах Придется писать скажем в идеологии консоли, а потом код трансформировать в оконное приложение. ![]() |
Сообщ.
#12
,
|
|
|
Цитата Adil @ этот код вынести в отдельный поток Дык у меня так и сделано в сервере. recvfrom и sendto в потоке. Цитата Oleg2004 @ Это так, быстро и на пальцах... На таких пальцах я и сам представляю. ![]() Цитата Oleg2004 @ утверждает, что API для винмобиле не включает Возможно. Я пишу #include <winsock2.h> и никто не против, ![]() Цитата Oleg2004 @ Какой смысл вы вкладываете в понятие "деформированные" пакеты? Ну "уродливые" , это не я , это Wireshark . Он пишет "malformed" , а в место данных там эррор.А в графе протокол вместо UDP пишет TAPA. (не знаю что это , но догадываюсь первые буквы надо заменить на "ЖО" ![]() Причем такие пакеты шлют и тот и другой. Цитата ЫукпШ @ Дело в том, что обмен с сервером DNS производится посредством UDP. У меня нет ДНС (я надеюсь ![]() |
Сообщ.
#13
,
|
|
|
Цитата Alexei @ Непонятно было куда засунуть селект, но если в поток, а из него слать сообщения и в их обработке слать и принимать? Ну, для того чтобы засунуть куда-нибудь селект, надо представлять, что он будет делать. Если у вас UDP-сервер, то на прием он висит на recvfrom(). У него нет внутреннего таймаута, а потому висеть может годами. Если такая ситуация не устраивает, то висят на селекте - но уже с таймаутом. Вот и весь смысл. Цитата Alexei @ Я пишу #include <winsock2.h> и никто не против, ![]() Зря. winsock2.h просто содержит всю информацию winsock.h - и только. Цитата Alexei @ Wireshark. Он пишет "malformed", а в место данных там эррор. А в графе протокол вместо UDP пишет TAPA. TAPA (Trapeze Access Point Access Protocol) В Wiresharkе есть клизмы, когда он неправильно определяет протокол и не может его анализировать... А здесь про "malformed" |
Сообщ.
#14
,
|
|
|
Цитата Oleg2004 @ надо представлять, что он будет делать. Думаю для начала, надо представлять что вообще надо. ![]() А надо мне изменить работу клиента(работа сервера меня в целом устраивает) Хотелось бы сделать так , чтобы клиент , послав пакет , не зависал, если возникнут проблемы с ответом , а продолжал работу и по таймеру послал следующий пакет. Подозреваю, надо послать пакет sendto-ом , далее подождать в select некоторое время , после чего либо recvfrom, либо ждать сообщения от таймера. sendto , наверно , в обработке сообщения от таймера, recvfrom обработке сообщения от select, а select в потоке. Типа того? |
Сообщ.
#15
,
|
|
|
Цитата Alexei @ Думаю для начала, надо представлять что вообще надо. ![]() Это ваши проблемы ![]() Цитата Alexei @ Подозреваю, надо послать пакет sendto-ом , далее подождать в select некоторое время , после чего либо recvfrom, либо ждать сообщения от таймера. Не понимаю (увы, я не телепат) зачем нужен таймер, ведь у селекта есть свой таймер таймаута. Приведу вам простой примерчик для селекта: ![]() ![]() #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #define STDIN 0 /* дескриптор файла для стандартного ввода */ main () { struct timeval tv; fd_set readfds; tv.tv_sec = 2; tv.tv_usec = 500000; FD_ZERO(&readfds); FD_SET (STDIN, &readfds); /* Нас не интересуют writefds и errorfds */ select (STDIN+1, &readfds, NULL, NULL, &tv); /*После нажатия клавиши клавиатуры нажать Enter*/ if (FD_ISSET (STDIN, &readfds)) printf (" Клавиша была нажата! \n ") else printf ("Timed out \n "); } Селект ждет 2,5 сек, чтобы нажали клавишу на клаве... Селектом ждать можно чего угодно и как угодно.. |