На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > UDP клиент и сервер , Как?
      Хочу сделать следующее:
      Клиент на Винмобаил каждые 20мС(желательно) шлет на сервер несколько байт.
      Сервер шлет ему свои несколько байт, затем подготавливает данные для следующего раза.
      Клиент будет только один.

      Для опытов я сделал оконные клиент и сервер на ВинХР на "большом" компе, пока без таймера.
      Попытка реализовать это увенчалась частичным успехом , все работает,но только один раз :), после чего(при следующей попытке), клиент зависает. :'(
      Если если перезапустить сервер, то клиент может послать еще одно сообщение.
      Пробовал консольный сервер из "Самоучителя по игре.." ,c ним все работает, ну так он сам все время "висит" в while(1).
      Думаю, я что-то в принципе не так делаю , поэтому код приводить смысла нет.Может, кто подскажет как надо.
      Пишу на Си.
      Сообщение отредактировано: Alexei -
        Ну, сервер UDP обязан висеть на recvfrom()- иначе это не сервер, а одноразовый шприц. :)
          Цитата Oleg2004 @
          Ну, сервер UDP обязан висеть на recvfrom()- иначе это не сервер, а одноразовый шприц. :)

          Почему ?
          Лучше висеть на select.
          Сделаем так:
          1. Для UDP нет разницы - "клиент" и "сервер" это будет почти одна и та-же программа.
          Тот, кто начинает обмен, называется клиентом.
          2. Для удобства (отладки) клиент будет слушать один порт, сервер - другой.
          3. С некоторым тайм-аутом ожидаем приёма сообщения. исключительно для того, чтобы
          опросить, например, клавиатуру и корректно завершить приложение.
          4. Если сообщение получено проверим опять же селектом готовность к передаче
          и пошлём ответ.
          5. Проверим условие на окончание работы приложения. Если нет, всё повторим с пункта 3.

          Разница между клиентом и сервером только в том, что клиент первым посылает сообщение,
          а потом ожидает приёма. Послать сообщение можно в том числе и по нажатию какой - либо клавиши
          в пункте 5.
            Цитата Oleg2004 @
            обязан висеть

            Висеть, но не вешать все.

            Цитата ЫукпШ @
            Лучше висеть на select.

            У меня он вообще не используется ! :o
            Ну я еще тот пограмист ;)
            Все решилось вставкой бесконечного цикла в процесс с recvfrom.

            Спасибо.
              Если верить StackOverflow, то вот работающий рецепт на select http://stackoverflow.com/questions/1559208...ith-select-in-c
              Хотя я для UDP тоже гоняю recvfrom в цикле - и пока проблем не ощутил.
                  Цитата ЫукпШ @
                  Лучше висеть на select.

                  Кто бы сомневался... :D
                  К сожалению, я именно это и предполагал, предложив топикстартеру цикл с recvfrom.
                  Цитата Alexei @
                  У меня он вообще не используется ! :o
                  Ну я еще тот пограмист ;)
                  Все решилось вставкой бесконечного цикла в процесс с recvfrom.
                  :)

                  Добавлено
                  Цитата ЫукпШ @
                  1. Для UDP нет разницы - "клиент" и "сервер" это будет почти одна и та-же программа.
                  Тот, кто начинает обмен, называется клиентом.

                  И с этим согласен, да вот только на сервере bind()обязателен, а на клиенте - три варианта - без бинда, с коннектом или биндом...
                    Рад что вас развеселил! :)
                    Вобщем у меня как-то все работает, но я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты , так что , наверно, имеет смысл прислушаться к вашим советам по select. Хотя, мне больше понравился EventSelect.
                    Но все примеры даны для консольных программ, а у меня будет оконная(в винмоб , помоему, других нет) .
                    Поэтому никто не будет так любезен показать структурно, как это будет выглядеть в оконной программе?
                      Цитата Alexei @
                      ... я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты , так что , наверно, имеет смысл прислушаться к вашим советам по select.

                      Это не совсем понятно. Надо разбираться.
                      Дело в том, что обмен с сервером DNS производится посредством UDP.
                      И если бы дело действительно было так плохо, интернет-сёрфинг
                      был бы не возможным. Или не комфортным.
                      Торрент - клиенты тоже (вроде) используют UDP для передачи информации.
                      Сообщение отредактировано: ЫукпШ -
                        Цитата Alexei @
                        но я смотрел Wireshark-ом: часто то сервер, то клиент шлют "деформированные" пакеты

                        Какой смысл вы вкладываете в понятие "деформированные" пакеты?
                        Насчет Eventselect ()
                        MSDN http://msdn.microsoft.com/en-us/library/aa925696.aspx
                        утверждает, что API для винмобиле не включает WSAEventSelect()или WSAAsyncSelect().
                        Сколько я помню, все варианты для мобильных систем работают на базе спецификации Винсок 1.1
                        А вот select() там есть.
                        Поэтому чисто оконного сетевого приложения найти будет трудно. Придется писать скажем в идеологии консоли, а потом код трансформировать в оконное приложение.

                        Цитата Alexei @
                        как это будет выглядеть в оконной программе?

                        Для начала вы должны познакомиться с идеологией работы оконных приложений.
                        Оконное приложение всегда "висит" в цикле обработки сообщений.
                        Сообщения приходят от системы и передаются по хендлу окна, а обработчик сообщений выполняет необходимые действия. Это так, быстро и на пальцах... :)
                          Цитата Oleg2004 @
                          Придется писать скажем в идеологии консоли, а потом код трансформировать в оконное приложение.
                          А потом этот код вынести в отдельный поток и не думать особо об окнах :)
                            Цитата Adil @
                            этот код вынести в отдельный поток

                            Дык у меня так и сделано в сервере. recvfrom и sendto в потоке.
                            Цитата Oleg2004 @
                            Это так, быстро и на пальцах...

                            На таких пальцах я и сам представляю.:) Непонятно было куда засунуть селект, но если в поток , а из него слать сообщения и в их обработке слать и принимать?
                            Цитата Oleg2004 @
                            утверждает, что API для винмобиле не включает

                            Возможно.
                            Я пишу #include <winsock2.h> и никто не против, :)

                            Цитата Oleg2004 @
                            Какой смысл вы вкладываете в понятие "деформированные" пакеты?

                            Ну "уродливые" , это не я , это Wireshark . Он пишет "malformed" , а в место данных там эррор.А в графе протокол вместо UDP пишет TAPA. (не знаю что это , но догадываюсь первые буквы надо заменить на "ЖО" :) )
                            Причем такие пакеты шлют и тот и другой.
                            Цитата ЫукпШ @
                            Дело в том, что обмен с сервером DNS производится посредством UDP.

                            У меня нет ДНС (я надеюсь :) ) все происходит в локальной сети: смартфон с вай-фаем -клиент , на писи- сервер, меж ними роутер с вай-фай.
                              Цитата Alexei @
                              Непонятно было куда засунуть селект, но если в поток, а из него слать сообщения и в их обработке слать и принимать?

                              Ну, для того чтобы засунуть куда-нибудь селект, надо представлять, что он будет делать.
                              Если у вас UDP-сервер, то на прием он висит на recvfrom(). У него нет внутреннего таймаута, а потому висеть может годами. Если такая ситуация не устраивает, то висят на селекте - но уже с таймаутом. Вот и весь смысл.
                              Цитата Alexei @
                              Я пишу #include <winsock2.h> и никто не против, :)

                              Зря. winsock2.h просто содержит всю информацию winsock.h - и только.
                              Цитата Alexei @
                              Wireshark. Он пишет "malformed", а в место данных там эррор. А в графе протокол вместо UDP пишет TAPA.

                              TAPA (Trapeze Access Point Access Protocol)
                              В Wiresharkе есть клизмы, когда он неправильно определяет протокол и не может его анализировать...
                              А здесь про "malformed"
                              Сообщение отредактировано: Oleg2004 -
                                Цитата Oleg2004 @
                                надо представлять, что он будет делать.

                                Думаю для начала, надо представлять что вообще надо. :)
                                А надо мне изменить работу клиента(работа сервера меня в целом устраивает)
                                Хотелось бы сделать так , чтобы клиент , послав пакет , не зависал, если возникнут проблемы с ответом , а продолжал работу и по таймеру послал следующий пакет.
                                Подозреваю, надо послать пакет sendto-ом , далее подождать в select некоторое время , после чего либо recvfrom, либо ждать сообщения от таймера.
                                sendto , наверно , в обработке сообщения от таймера, recvfrom обработке сообщения от select, а select в потоке. Типа того?
                                  Цитата Alexei @

                                  Думаю для начала, надо представлять что вообще надо. :)

                                  Это ваши проблемы :D

                                  Цитата Alexei @
                                  Подозреваю, надо послать пакет sendto-ом , далее подождать в select некоторое время , после чего либо recvfrom, либо ждать сообщения от таймера.

                                  Не понимаю (увы, я не телепат) зачем нужен таймер, ведь у селекта есть свой таймер таймаута.
                                  Приведу вам простой примерчик для селекта:
                                  ExpandedWrap disabled
                                    #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 сек, чтобы нажали клавишу на клаве...
                                  Селектом ждать можно чего угодно и как угодно..
                                    Цитата Oleg2004 @
                                    зачем нужен таймер

                                    Таймер нужен для того, чтобы запрашивать данные с сервера с нужной периодичностью.
                                      Цитата Alexei @

                                      Таймер нужен для того, чтобы запрашивать данные с сервера с нужной периодичностью.

                                      Понятно.
                                      Я бы лучше вызывал sleep().
                                      И никаких сообщений от таймера.
                                      Впрочем, на вкус и цвет... :)
                                        Цитата Oleg2004 @
                                        Я бы лучше вызывал sleep().

                                        Так она просто будет останавливать программу, а у меня большие планы :)

                                        Я попробовал WSAAsyncSelect , для wm6.1 все скомпилировалось(Гейц сам уже ничего не помнит) и так же работает и ... виснет также. :)
                                          Цитата Alexei @

                                          Так она просто будет останавливать программу, а у меня большие планы :)

                                          Ну ну.... :)
                                          К сожалению вы должны смириться с мыслью, что в сетевом программировании мы сплошь и рядом имеем дело с двумя вещами - кучей буферов по дороге данных - и кучу временных задержек - в основном недетерминированных, потому как сеть оооооочень капризный файл.
                                          И ей могут быть не по нраву ваши планы...
                                          Но зачем вам таймер теперь я понял :yes:
                                          Цитата Alexei @
                                          Я попробовал WSAAsyncSelect , для wm6.1 все скомпилировалось(

                                          Не вопрос, WSAAsyncSelect всегда входила в спецификацию Winsock 1.1 для Windows CE (а это основа всех мобильных операционок микрософта)
                                          Так что Билл не виноват... :D
                                          Вы бы код опубликовали ...тогда можно говорить предметно.
                                          И - точный и однозначный алгоритм взаимодействия клиент-сервер.
                                          Сообщение отредактировано: Oleg2004 -
                                            Цитата Oleg2004 @
                                            ей могут быть не по нраву ваши планы...

                                            Так поэтому я и выбрал UDP.Что не успело- то опоздало.

                                            Цитата Oleg2004 @
                                            - точный и однозначный алгоритм взаимодействия клиент-сервер.

                                            Дык, в самом начале я все однозначно пожелал
                                            Цитата Alexei @
                                            Клиент на Винмобаил каждые 20мС(желательно) шлет на сервер несколько байт.
                                            Сервер шлет ему свои несколько байт, затем подготавливает данные для следующего раза.
                                            Клиент будет только один.

                                            и, главное, чтобы клиент не вис, никогда! :)
                                            Пакеты могут теряться, связь пропадать, но программа должна реализовывать мои , далеко идущие ,планы. :)
                                              Цитата Alexei @
                                              Дык, в самом начале я все однозначно пожелал

                                              Это на алгоритм не похоже:
                                              Цитата Alexei @
                                              Хочу сделать следующее:
                                              Клиент на Винмобаил каждые 20 мС(желательно) шлет на сервер несколько байт.
                                              Сервер шлет ему свои несколько байт, затем подготавливает данные для следующего раза.
                                              Клиент будет только один.

                                              Смотрим по шагам:
                                              1. Клиент на Винмобаил каждые 20 мС(желательно) шлет на сервер несколько байт.
                                              Ну и как это представляете себе?
                                              20 мс - это обычный таймслайс для большинства операционных систем. Я не знаю на какой ОС у вас сервер, но тем не менее - вот пришли на серверный компутер первые байты. Если там куча приложений - то всем им дается интервал процессорного времени - и практически сто процентов, что серверное приложение получит эти байты через 20 мс+время по сети. На работу сервера выделяется тоже 20 мс за эти мс он должен принять, обработать и послать - а потом получит процессорное время после 100 мс или больше. А тут вы клиентиом уже 5 раз по 20 мс ему шлете свои байты... Не получается однако...
                                              Если эта схема будет работать на одной машине - и то я сомневаюсь в синхронизации процессов приема/отправки. 20 мс - это нереально...
                                              Предполагаю, что первый обмен у вас еще получится, но все последующие....
                                              2. Что означает - подготавливает данные..? Он знает, что вы ему на подготовку отпустили всего 20 мс?
                                                Цитата Oleg2004 @
                                                Ну и как это представляете себе?

                                                1.Во-первых желательно, во-вторых телефон успевает опросить,например акселерометр за это время, в-третьих ,возможно это и будет на только одном ПК.
                                                2. Там не сложно :) Клиенту будет сложнее.
                                                Когда эта проблема возникнет -будем порешать... :P

                                                Сейчас, вот проблема- похоже WSAAsyncSelect нет в вин се :angry:
                                                  Цитата Alexei @
                                                  1.Во-первых желательно,

                                                  Желательно - это не означает что есть возможность реализовать желание. К этому надо стремиться, однако...
                                                  Цитата
                                                  во-вторых телефон успевает опросить, например акселерометр за это время, в-третьих ,возможно это и будет на только одном ПК.

                                                  Если предполагается обработка где-то в сети на одном ПК - как я писал, будут проблемы.
                                                  И акселерометр???
                                                  Какая конкретно под него задача решается?
                                                  Поэтому как я еще раз повторю - интервал 20 мс может? быть реален только тогда, когда обработка его производится на одной и той же машине. Если телефон отдельно а ПК - в обычной Ethernet сети отдельно, следует менять концепцию.
                                                  Имхо.
                                                  Это и есть - описание алгоритма...
                                                  Буду рад, если вы меня опровергнете.

                                                  Цитата
                                                  Сейчас, вот проблема- похоже WSAAsyncSelect нет в вин се :angry:

                                                  Да, я проверил - в спецификацию Winsock 1.1 WSAAsyncSelect() входит, и хотя Микрософт заверяла, что эта спецификация поддерживается Windows CE - на самом деле это не так. Это же пишет и Олунд.
                                                  В результате действительно так - в мобильных системах не поддерживается, увы.
                                                  Сообщение отредактировано: Oleg2004 -
                                                    Цитата Oleg2004 @
                                                    Какая конкретно под него задача решается?

                                                    Пока,цифирки показываются в окошках. :)
                                                    Акселерометр взят на вскиду, чтобы было что передать в запросе.Для опытов.:) Может , в другой задаче будет управлять курсором.
                                                    Главное, получить от сервера 8 байт(даже , возможно 4) , их надо считать с джойстиков.
                                                    В принципе, сервер может быть консольным, если это облегчит жизнь.
                                                    Сейчас меня больше удручает необходимость создания потока в клиенте :(
                                                    В нем я бы хотел поэкономить ресурсы.
                                                      Цитата Alexei @
                                                      Главное, получить от сервера 8 байт(даже , возможно 4) , их надо считать с джойстиков.

                                                      Ну так в чем проблема то?
                                                      Значит висим на recvfrom() и все дела.
                                                      Цитата Alexei @
                                                      Сейчас меня больше удручает необходимость создания потока в клиенте :(

                                                      Теперь я снова не убежден что вам нужны потоки .
                                                      UDP-клиенты вообще примитивны...впрочем как и сервера.
                                                      Впрочем воля ваша...
                                                        Цитата Oleg2004 @
                                                        и все дела.

                                                        Сделал с WSAEventSelect без лишних потоков.Телефон(клиент) не виснет если закрыть сервер совсем, или только передачу.При "реанимации" сервера, работа вознобнавляется. :yes:
                                                          Я рад что все получилось... :)
                                                          Ставьте пометку - Вопрос решен...
                                                          Сообщение отредактировано: Oleg2004 -
                                                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                          0 пользователей:


                                                          Рейтинг@Mail.ru
                                                          [ Script execution time: 0,0675 ]   [ 15 queries used ]   [ Generated: 31.05.24, 13:22 GMT ]