Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> соккеты отправка/получение сообщений целиком 
:(
    Опции темы
GorbunovDiman
Дата 20.12.2011, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.3.2008

Репутация: нет
Всего: нет



Читая http://www.rsdn.ru/article/unix/sockets.xml я обратил особое внимание на функцию
Код

int sendall(int s, char *buf, int len, int flags)
{
    int total = 0;
    int n;

    while(total < len)
    {
        n = send(s, buf+total, len-total, flags);
        if(n == -1) { break; }
        total += n;
    }

    return (n==-1 ? -1 : total);
}


как я понял в случае неудачной отправки она посылает заново конец сообщения отдельным пакетом.

НО как на другом конце определить, что это куски одного и того же сообщения?
если при этом на один сокет может приходить инфа с нескольких компов( для udp)?

PM MAIL   Вверх
feodorv
Дата 20.12.2011, 18:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



UDP пакеты всегда посылаются целиком.
Тот пример, который Вы привели, относится к TCP.
Узел, с которого пришёл UDP-пакет, определяется по IP-адресу источника. Например, функция
Код

int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

возвращает адрес источника в параметре from.

Это сообщение отредактировал(а) feodorv - 20.12.2011, 18:43


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GorbunovDiman
Дата 20.12.2011, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.3.2008

Репутация: нет
Всего: нет



Нет а если я буду так же бить udp пакет (для параллельной отправки через один соккет нескольких сразу (то есть вроде как параллельной по очереди мелкие куски каждого)) есть ли какая нибудь возможность восстановить пакет на другой стороне?
И вот это уже (для tcp) если допустим мне пришло на соккет сообщение. Я его читаю, но во время чтения туда уже приходит следующее сообщение. Есть ли возможность разграничить их в этом случае? Не сольются ли они?
PM MAIL   Вверх
boostcoder
Дата 20.12.2011, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
если я буду так же бить udp пакет

это возможно, если вы напишите свой протокол ;)

Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
для параллельной отправки через один соккет нескольких сразу

например, как вы предполагаете это сделать?

Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
то есть вроде как параллельной по очереди мелкие куски каждого

бред какой-то пишите.

Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
во время чтения туда уже приходит следующее сообщение

следующее сообщение встанет в очередь, и вы его прочтете только после того, как прочтете предыдущее.
PM WWW   Вверх
feodorv
Дата 21.12.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
 есть ли какая нибудь возможность восстановить пакет на другой стороне?

Конечно, есть, но только если Вы сами будете следить за порядком UDP-пакетов. А это приводит нас к:
Цитата(boostcoder @  20.12.2011,  21:09 Найти цитируемый пост)
это возможно, если вы напишите свой протокол ;)



Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
И вот это уже (для tcp) если допустим мне пришло на соккет сообщение. Я его читаю, но во время чтения туда уже приходит следующее сообщение. Есть ли возможность разграничить их в этом случае? Не сольются ли они?

Если прямо вот во время чтения, то нет. Если же Ваш процесс занят чем-нибудь, и в это время приходит один пакет, потом другой, то, да, эти два сольются (если, конечно, буфер сокета их вместит).
Опять таки, чтобы их разграничить, Вам нужно внести в пакеты дополнительные данные (заголовок типа ид пакета, длина, номер, CRC заголовка и т.д.), то есть реализовать собственный протокол. И уже при чтении следить за границами пакетов.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GorbunovDiman
Дата 21.12.2011, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.3.2008

Репутация: нет
Всего: нет



Типа если я принимаю дыные с http сервера (незная длину сообщения) мне придётся самому по содержанию ловить точку конца?
PM MAIL   Вверх
feodorv
Дата 22.12.2011, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(GorbunovDiman @  21.12.2011,  19:51 Найти цитируемый пост)
Типа если я принимаю дыные с http сервера (незная длину сообщения) мне придётся самому по содержанию ловить точку конца? 

Web-сервер вполне может указать длину содержимого в заголовке Content-Length, правда, полагаться на неё не стоит.
Если Keep-Alive выключен, то по окончании передачи данных сервер просто прикроет соединение. Пользовательской программой это событие может быть воспринято как FD_CLOSE в виндах или ноль как возвращаемое значение функции чтения из сокета. 
Если же используются постоянные соединения, то каждый ответ сервера обязан содержать правильный заголовок Content-Length, по которому клиент и определяет границы сообщений (Постоянные соединения (Persistent Connections)). Это опять-таки тонкости протокола HTTP, а не TCP.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 22.12.2011, 17:42 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



У меня появилось некоторое предположение, что Вы не совсем понимаете, что такое сокет. Грубо говоря, сокет - это сочетание трёх параметров:
  • протокол обмена
  • адрес узла в сети
  • номер сокета, определённый в рамках того самого узла сети, для которого задан адрес
Таким образом, для одного и того же узла можно создать целый набор различных сокетов. Различаться сокеты будут как раз по номеру, в TCP/IP - это номер порта. Более того, если какой-то номер сокета уже используется (порт занят), создать (без дополнительных ухищрений) сокет с тем же номером не удастся.

Соединение есть некая корреляция двух сокетов (созданных на разных узлах или даже на одном узле). Соединение характеризуется уже пятью параметрами:
  • протокол обмена
  • адрес локального узла
  • номер сокета для локального узла
  • адрес удалённого узла
  • номер сокета для удалённого узла
И когда Вы пишете:
Цитата(GorbunovDiman @  20.12.2011,  20:39 Найти цитируемый пост)
И вот это уже (для tcp) если допустим мне пришло на соккет сообщение. Я его читаю, но во время чтения туда уже приходит следующее сообщение. Есть ли возможность разграничить их в этом случае? Не сольются ли они? 

Цитата(GorbunovDiman @  21.12.2011,  19:51 Найти цитируемый пост)
Типа если я принимаю дыные с http сервера (незная длину сообщения) мне придётся самому по содержанию ловить точку конца? 

я понимаю, что вы сокет себе представляете без номера, типа всё течёт в одну дыру. Нет, не в одну.

Клиент работает через вызовы:
  • socket() - создаёт локальный несвязанный сокет
  • bind() - связывает локальный сокет с локальным адресом и/или локальным портом. Если порт не указывать, система сама назначит (свободный) порт локальному сокету.
  • connect() - связывает локальный сокету с адресом/портом удалённого узла.
То есть при правильной настройке socket()+bind()+connect() приведёт к отсылке специального пакета соединения от локального узла к удалённому (серверу) с указанием клиентского порта. 

Сервер работает через вызовы:
  • socket() - создаёт серверный сокет
  • bind() - связывает серверный сокет с серверным адресом и серверным портом.
  • listen() - сокет становится прослушиваемым
  • accept() - приём соединения
При приёме соединения сервером ОС (через accept) создаёт ещё один сокет, присваивает ему подходящий IP и порт сервера и устанавливает IP и порт клиента, и посылает обратно специальный пакет с указанием порта/IP серверного сокета. Соединение установлено (клиент его ещё подтвердить должен). Оно совершенно уникально - более такого сочетания пятикомпонентных параметров соединения не получится. Поэтому в один и тот же присоединённый серверный сокет попасть пакеты не из этого соединения (типа с разных узлов и разных программ) не могут.

Это сообщение отредактировал(а) feodorv - 22.12.2011, 18:08


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
GorbunovDiman
Дата 24.12.2011, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 3.3.2008

Репутация: нет
Всего: нет



Цитата

У меня появилось некоторое предположение, что Вы не совсем понимаете, что такое сокет. Грубо говоря, сокет - это сочетание трёх параметров:


Спасибо за детальное объяснение.
Цитата

Поэтому в один и тот же присоединённый серверный сокет попасть пакеты не из этого соединения (типа с разных узлов и разных программ) не могут.

Я это прекрасно понимаю НО!

Это не сколько понимание сокетов, сколько изначально задумавшаяся архетектура проги (Которая частично пересмотрена).

Подрозумевалось следующие: 
               Для чтения и записи существуют свои потоки (pthread)
               Конкретно для чтения:
                      Существует множество в которое записываются функции которые должны быть вызваны на выполнение(в потоке чтения) по приходу на сокет какого либо сообщеняя.

проблема как раз в том чтобы разграничить сообщения (пометки о длине в них даже и не предпологаются).

Это была некая попытка сделать (СВОЮ! boost не предлагать!)  надстройку над стандартными сокетами,отдалённо напоминающую std::cout.

Вот конкретный пример(на сокет приходят сообщения не с разных машин а с одной!):
сервер посылает 
    сообщение 1
    сообщение 2
клиент начинает читать(по каким-то причинам уже когда к ниму пришли оба сообщения)

   Может ли он их разграничит(там нет инфы о длине)? Из ваших постов стало понятно что нет.




А вот (чтобы темы не плодить)  :

 У меня есть (уже хорошо отлаженный модуль : обвязка селекта)
ему ставются дискрипторы на слежения и функции обработчики.А он вызывает их когда это нужно.

Но меня осенило так как я использую отдельные потоки для чтения и записи то можно сокеты делать и блокирующими.
(надобность в модуле как бы отпадает отпадает)
Вопрос: если в одном потоке send заблокировал сокет, то может ли в другом потоке проходить операция чтеня.(Попытка сделать максимальную асинхронность)

И какие приимущества/недостатки у блокирующих/неблокирующих сокетов?


PM MAIL   Вверх
feodorv
Дата 25.12.2011, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Цитата(GorbunovDiman @  24.12.2011,  18:42 Найти цитируемый пост)
Я это прекрасно понимаю

Извините, если что не так  smile 

Цитата(GorbunovDiman @  24.12.2011,  18:42 Найти цитируемый пост)
Может ли он их разграничит(там нет инфы о длине)? Из ваших постов стало понятно что нет.

Нет, не может.

Цитата(GorbunovDiman @  24.12.2011,  18:42 Найти цитируемый пост)
Но меня осенило так как я использую отдельные потоки для чтения и записи то можно сокеты делать и блокирующими.

Верно  smile 

Цитата(GorbunovDiman @  24.12.2011,  18:42 Найти цитируемый пост)
если в одном потоке send заблокировал сокет, то может ли в другом потоке проходить операция чтеня

Может. Всё равно все синхронные вызовы реализованы через асинхронные)))

Цитата(GorbunovDiman @  24.12.2011,  18:42 Найти цитируемый пост)
И какие приимущества/недостатки у блокирующих/неблокирующих сокетов?

Гм. Конечно, всё зависит от задачи, которую Вы реализуете. Многие задачи, реализацию которых я видел на асинхронных вызовах, могут быть решены с использованием синхронных сокетов. Однако лично я настолько оценил удобство асинхрона, что про синхронные вызовы просто забыл))) У синхронных сокетов есть одно очевидное преимущество - простота их программирования. Использование асинхронных сокетов требует более тонких подходов. Но со временем к ним привыкаешь и не мыслишь себя без них)))

Наверняка меня дополнят, но вот так навскидку я вижу такие преимущества применения асинхронных вызовов:
  • уменьшается число потоков. Если ограничиться, скажем, максимум 62-63 клиентами, то вообще весь сервер можно реализовать на одном потоке
  • полнодуплексный обмен
  • возможность с лёгкостью контролировать различные таймауты, в том числе и на connect.

По поводу полнодуплескного режима обмена (я имею в виду, на пользовательском уровне, конечно). Видите, Вам понадобилось аж 2 потока, чтобы иметь возможность одновременно и писать и читать. Потребуется и дополнительная синхронизация этих потоков, если Ваш сервер делает что-нибудь полезное. А ещё нужен один поток, который будет принимать соединения...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0886 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.