Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.141.31.240] |
|
Страницы: (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 сек, чтобы нажали клавишу на клаве... Селектом ждать можно чего угодно и как угодно.. |