Сетевое приложение

Тема в разделе "WASM.BEGINNERS", создана пользователем pashe4ka13, 23 ноя 2011.

  1. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Всем доброго времени суток! Решил написать сетевое приложение которое должно обладать следующими свойствами:должно быть одновременно и клиентом и сервером, передавать данные по протоколам TCP и UDP. Возникло несколько вопросов: можно ли сокет настроенный в качестве клиента не убивая перестроить на сервер? какой максимальный объем данных может быть передан за один раз? Как регулировать размер данных при передаче, писать свой протокол прикладного уровня? возможна ли одновременная работа двух или более блокирующих сокетов при запуске их в различных потоках?
     
  2. Sholar

    Sholar New Member

    Публикаций:
    0
    Регистрация:
    16 окт 2011
    Сообщения:
    189
    Честно говоря странный вопрос, да и зачем нужны такие фокусы? Что мешает использовать два разных сокета?
    Имеется ввиду в одном пакете? UDP - чуть меньше 64 кб. Если юзать TCP, это вообще не имеет значения.
    Да. Это придется делать в любом случае.
    Да.
     
  3. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Sholar
    Спасибо вам огромное.
    дело в том, что в качестве клиента сокет нужен будет лишь для передачи имени хоста и ip адреса серверу к которому уже подключен и ожидает имя и адрес другой клиент. Получив их он должен будет соединиться с сервером на указанный ip и на тот же порт.
     
  4. Sholar

    Sholar New Member

    Публикаций:
    0
    Регистрация:
    16 окт 2011
    Сообщения:
    189
    Ничто не мешает создать два сокета.
     
  5. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Всем снова здравствуйте! Подскажите пожалуйста как работает recv? Я использую блокирующий сокет. Когда recv вернет управление? Например: recv(s,char buf[1000],len(1000-1),0); а ответ от сервера будет размером <1000 она вернет управление или нет? Если да, то у меня почему то все виснет:dntknw: может это значит, что сервер вообще ответ не шлет? Что тогда делать? Может запускать recv отдельным тредом и если он зависнет прибивать его, а затем повторять запрос и снова запускать тред с recv?
    И еще такой вопрос: у меня два компа в сети, подключены через адсл-модем, который настроен в режим роутера. Можно ли как-то программным путем узнать глобальный ip-адрес компа? И как из глобальной сети обратиться к одному из моих компов?
     
  6. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    смотря какой сокет. Если TCP - то там нет понятия "длина ответа" - блокирующий сокет вернет управление либо только тогда, когда в потоке накопится не меньше запрошенного количества байт, либо когда оборвется TCP-соединение. Блокирующий же UDP сокет должен возвращать как только появится доступный пакет любого размера.
     
  7. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Сокет ТСР. Первый запрос к серверу такой:"HELO 127.0.0.1".Ответ сервера "220 smtp3.mail.ru ESMTP ready". При этом recv(s,char buf[1000],len(1000-1),0); возвращает 31(число принятых байт) и отдает управление(хотя по вашим словам не должно 31<1000), но после второго запроса виснет наглухо:dntknw:
     
  8. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    что возвращает recv? и код в студию, по возможности
     
  9. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    pashe4ka13,
    И никаких «когда в потоке накопится не меньше запрошенного количества байт».

    Подразумеваю, что сокет в блокирующем режиме: после HELO recv возвращает ответ сервера (не обязательно целиком – чтобы считать ответ сервера, может потребоваться и несколько recv, это ваше дело копить данные и звать recv, пока в буфере не появится CRLF, или что там по протоколу), после второго recv сервер ничего не отвечает, ведь команду вы ему не послали, и recv «виснет наглухо», ожидая данных.
     
  10. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    h0t
    При блокирующем сокете первый раз возвращает количество байт(символов) 31, затем виснет наглухо. Разблокировал сокет стало при втором вызове выдавать WSAEWOULDBLOCK (код 10035)Resource temporarily unavailable. Как я понимаю почтовый сервер не отвечает?
     
  11. h0t

    h0t Member

    Публикаций:
    0
    Регистрация:
    3 апр 2011
    Сообщения:
    735
    посмотрит wireshark'ом на всякий случай)
     
  12. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    pashe4ka13
    Блокирующий режим работы сокета.
    recv/read на таком сокете блокируется, если в ядерном буфере приёма данных из сети пусто. Если же в буфере что-то есть, то возвращается то, что есть. Точнее та часть того что есть, которая влезет в переданный юзерский буфер.
    При этом, не знаю как там в венде, в *nix, есть ещё одна хитрость: при последовательных recv/read на сокете, которые "вычитывают" всё содержимое ядерного буфера, последний вызов который не заблокируется всегда вернёт меньше байт, чем запрошено. То есть, допустим в ядерном буфере 10 байт. Мы читаем по 3 байта за раз. Значит первые три раза ядро нам будет возвращать по три байта, в четвёртый раз ядро вернёт один байт, пятый вызов заблокируется. Если мы читаем по 5 байт за раз, то ядро дважды вернёт нам по 5 байт, в третий раз вернёт 0 байт, и четвёртый вызов заблокируется.

    Неблокирующий режим.
    Ядро не блокирует вызовы никогда, но возвращает либо ненулевое количество байт (если есть что возвращать), либо -EWOULDBLOCK.

    У вас же возникает EWOULDBLOCK, я думаю потому, что просто протоколы вы не выдерживаете. smtp ведь чётко работает по правилу клиент отправил запрос, сервер прислал ответ. Сервер не "не отвечает", а ждёт следующего запроса, на который можно ответить.
     
  13. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Да действительно сервер не шлет ответа. Если я делаю вызов так
    Код (Text):
    1. bool SendData()
    2.        {  
    3.         char buffer[]= "HELO 127.0.0.1\r\n";
    4.            if (send(сокет.СокетСервера,buffer,sizeof(buffer),0)==SOCKET_ERROR)return false;
    5.      return true;
    6.        }
    то все работает и recv не виснет, но если я вызываю функцию передачи так
    Код (Text):
    1. bool SendData(char buffer[])
    2.        {  
    3.        
    4.            if (send(сокет.СокетСервера,buffer,sizeof(buffer),0)==SOCKET_ERROR)return false;
    5.      return true;
    6.        }
    7.  
    8. int main()
    9. {
    10. SendData("HELO 127.0.0.1\r\n");
    11. return 0;
    12. }
    то виснет, хотя SendData возвращает true.
     
  14. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    pashe4ka13
    может не робит потомучто это вам не 1С, а студия и нужно писать
    xD
     
  15. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    pashe4ka13, и чему, по вашему, равно sizeof(buffer) во втором случае?


    r90, где про это можно прочитать? Везде только “… return the length of the message on successful completion.” и “The return value will be 0 when the peer has performed an orderly shutdown”. И как в таком случае предполагается отличать нормально закрытый сокет от состояния, когда данные кончились?
     
  16. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    ASMatic
    Я предвидел, что это кто то скажет. SendData(); до посылки сюда была ПередачаДанных(); Я не придерживаюсь какой либо нотации и стандарта при написании кода, так как написание простеньких прог это мое хобби и не думаю, что кто то в дальнейшем будет читать мой быдлокод. А то что Сокет не стал Socket при отправки сюда, это моя невнимательность. Вы бы лучше ответили на второй вопрос как получить ip находясь за NATом. Я, как вариант, думаю отправить запрос сервису который определяет ip и распарсить его html ответ 'выдрав' от туда свой адрес. Но даже получив глобальный адрес как обратиться к конкретному компу?
     
  17. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    iZzz32
    sizeof(buffer) будет равно 4 байта, то есть длинна указателя. А как можно передать корректное значение в функцию? Мне в голову приходит только передача отдельно указателя и длинны
    Код (Text):
    1. bool SendData(char *buffer, int len)
    2.        {        
    3.            if (send(сокет.СокетСервера,buffer,len,0)==SOCKET_ERROR)return false;
    4.      return true;
    5.        }
    Может можно как-то красивее?
     
  18. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Всем большое спасибо! Заменил sizeof на strlen все работает теперь как надо, остался лишь вопрос как из глобальной сети получить доступ к компу который находиться за NATом?
     
  19. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    а потом в привычку войдет...зачем делать не правильно, если изначально можно делать как положено и не тратить время на исправления кода перед постингом на форум.да еще потом нарываться на всякие коментарии (типа мого) и оправдыватся что недоглядел еще там подправить%

    с доступом за NAT самое постое решение - бекконект.