Пересылка через сокеты больших обьемов данных
От: Alexey Voytsehovich Украина  
Дата: 27.11.09 13:30
Оценка:
Всем доброго дня. Столкнулся с задачей, которую ранее не решал. Решил проконсультироватся с сообществом чтобы не изобрести очередной велосипед

Дано: необходимо переслать с клиента на сервер большой обьем данных (не хотелось бы ограничивать себя), с получением от сервера обратно подтверждения о получении данных.

Что есть. Есть ICS библиотека асинхронных сокетов, у которых есть send и recv (упрощенно).

вот я немного и подвис на этом. То есть соединение есть, данные туда сюда ходят, но как большие обьемы собрать в кучу, при этом учесть что может клиент отвалится и не полностью доставить данные, или они могут физически испортится (а значит надо хоть минимальный контроль с помощью CRC). Как потом, после сборки данных ответить клиенту что все ок. Иил через какое время у него данные повторно запросить. А таких клиентов может быть несколько, и по каждому надо накапливать буфер принимаемых данных.

В общем пока больше вопросов чем ответов. Может быть кто-то сможет базово что либо рассказать, или посоветовать как сформировать вопрос гуглю?

Заранее спасибо.
Я не умею быть злым, и не хочу быть добрым.
Re: Пересылка через сокеты больших обьемов данных
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 27.11.09 13:57
Оценка:
Здравствуйте, Alexey Voytsehovich, Вы писали:

AV>вот я немного и подвис на этом. То есть соединение есть, данные туда сюда ходят, но как большие обьемы собрать в кучу, при этом учесть что может клиент отвалится и не полностью доставить данные, или они могут физически испортится (а значит надо хоть минимальный контроль с помощью CRC). Как потом, после сборки данных ответить клиенту что все ок. Иил через какое время у него данные повторно запросить. А таких клиентов может быть несколько, и по каждому надо накапливать буфер принимаемых данных.


А ты для себя протокол обмена распиши:
1) Клиент шлет запрос на прием данных
2) Сервер отвечает
3) Клиент шлет кусок данных + CRC куска
4) Сервер подтверждает получение куска и совпадение контрольной суммы
5) Если все нормально — повторяем до победного конца, иначе уходим или на облом или на повтор передачи куска

Соответственно сервер куски данных до завершения должен ложить хотя бы в файловый поток...
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re[2]: Пересылка через сокеты больших обьемов данных
От: Alexey Voytsehovich Украина  
Дата: 27.11.09 14:14
Оценка:
Здравствуйте, DarkMaster, Вы писали:

DM>Здравствуйте, Alexey Voytsehovich, Вы писали:


AV>>вот я немного и подвис на этом. То есть соединение есть, данные туда сюда ходят, но как большие обьемы собрать в кучу, при этом учесть что может клиент отвалится и не полностью доставить данные, или они могут физически испортится (а значит надо хоть минимальный контроль с помощью CRC). Как потом, после сборки данных ответить клиенту что все ок. Иил через какое время у него данные повторно запросить. А таких клиентов может быть несколько, и по каждому надо накапливать буфер принимаемых данных.


DM>А ты для себя протокол обмена распиши:



DM>Соответственно сервер куски данных до завершения должен ложить хотя бы в файловый поток...


дык вроде ж tcp-ip это делать умеет? или я где то чтото не так понял?
Я не умею быть злым, и не хочу быть добрым.
Re: Пересылка через сокеты больших обьемов данных
От: Danchik Украина  
Дата: 27.11.09 14:17
Оценка: 2 (2)
Здравствуйте, Alexey Voytsehovich, Вы писали:

AV>Всем доброго дня. Столкнулся с задачей, которую ранее не решал. Решил проконсультироватся с сообществом чтобы не изобрести очередной велосипед


AV>Дано: необходимо переслать с клиента на сервер большой обьем данных (не хотелось бы ограничивать себя), с получением от сервера обратно подтверждения о получении данных.


AV>Что есть. Есть ICS библиотека асинхронных сокетов, у которых есть send и recv (упрощенно).


AV>вот я немного и подвис на этом. То есть соединение есть, данные туда сюда ходят, но как большие обьемы собрать в кучу, при этом учесть что может клиент отвалится и не полностью доставить данные, или они могут физически испортится (а значит надо хоть минимальный контроль с помощью CRC). Как потом, после сборки данных ответить клиенту что все ок. Иил через какое время у него данные повторно запросить. А таких клиентов может быть несколько, и по каждому надо накапливать буфер принимаемых данных.


AV>В общем пока больше вопросов чем ответов. Может быть кто-то сможет базово что либо рассказать, или посоветовать как сформировать вопрос гуглю?


Делить большой кусок на чанки (chunk)
Например так:
1. Посылаем серверу пакет — сейчас будет кусок данных (размера DataSize, поделенный на чанки ChunkSize)
  packed record
    PacketType : Byte;     // control packet type (start chunking, for example 1)
    DataSize : LongWord;
    ChunkSize : Word;
  end;

Сервер, генерирует ChunkStreamID и отвечает
  packed record
    PacketType : Byte;     // control packet type (confirm chunking 2)
    ChunkStreamID: Word    // возвращаем с сервера ChunkStreamID - уникальное для сервера число, по которому будет идентифицироваться кусок, который мы пересылаем.
  end;

2. Посылаем чанки
  packed record
    PacketType : Byte;     // chunk packet type, 3
    ChunkStreamID:         // previously returned by server
    ChunkNumber : LongWord // инкрементируем для каждого чанка
    ChunkData: array [ChunkSize] of Byte;
  end;

Последний чанк-пакет может быть меньше предыдущих (данных меньше)

Теперь придумываем спопобы синхронизации, опишу для TCP, CRC уже сам протокол проверит:
На сервере создаем запись — будет огромный кусок данных такого то размера и так то поделенный.
Собираем чанки в массив по ChunkStreamID и сортируем по ChunkNumber. Если какой то чанк для ChunkStreamID не пришел, например через 10 sec после последнего пакета по ChunkStreamID — пересылка обламалась. Можем про это проинформировать клиента:
  packed record
    PacketType : Byte;     // control packet type, (chunking failed, 4)
    ChunkStreamID:         // previously returned by server
  end;


Все пришло (DataSize <= ReceivedChunkCount * ChunkSize) — собираем бааальшой буфер. Нотифицируем клиента что все гут
  packed record
    PacketType : Byte;     // control packet type, (chunking SUCCESS, 5)
    ChunkStreamID:         // previously returned by server
  end;


Так как протокол ассинхронный, неплохо будет наставить таймаутов где надо. Не пришло то то за такое то время — делаем то то.
Надеюсь все понятно?
Re[2]: Пересылка через сокеты больших обьемов данных
От: Alexey Voytsehovich Украина  
Дата: 27.11.09 14:26
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Alexey Voytsehovich, Вы писали:


AV>>Всем доброго дня. Столкнулся с задачей, которую ранее не решал. Решил проконсультироватся с сообществом чтобы не изобрести очередной велосипед


D>Делить большой кусок на чанки (chunk)

D>Например так:

D>Так как протокол ассинхронный, неплохо будет наставить таймаутов где надо. Не пришло то то за такое то время — делаем то то.

D>Надеюсь все понятно?

ну вроде примерно так и я думал, вот только вот что меня напрягает — вроде бы как tcp-ip протокол тоже умеет чанковать и собирать на другой стороне? или же я заблуждаюсь и он это умеет делать в пределах 64К?
Я не умею быть злым, и не хочу быть добрым.
Re[3]: Пересылка через сокеты больших обьемов данных
От: Alexey Voytsehovich Украина  
Дата: 27.11.09 14:36
Оценка:
Здравствуйте, Alexey Voytsehovich, Вы писали:

AV>Здравствуйте, Danchik, Вы писали:


D>>Здравствуйте, Alexey Voytsehovich, Вы писали:


AV>>>Всем доброго дня. Столкнулся с задачей, которую ранее не решал. Решил проконсультироватся с сообществом чтобы не изобрести очередной велосипед


D>>Делить большой кусок на чанки (chunk)

D>>Например так:

D>>Так как протокол ассинхронный, неплохо будет наставить таймаутов где надо. Не пришло то то за такое то время — делаем то то.

D>>Надеюсь все понятно?

AV>ну вроде примерно так и я думал, вот только вот что меня напрягает — вроде бы как tcp-ip протокол тоже умеет чанковать и собирать на другой стороне? или же я заблуждаюсь и он это умеет делать в пределах 64К?


агааа, в этом треде
Автор:
Дата: 19.11.09
обсуждают примерно тоже Глаза открываются
Я не умею быть злым, и не хочу быть добрым.
Re[3]: Пересылка через сокеты больших обьемов данных
От: Danchik Украина  
Дата: 27.11.09 14:46
Оценка: 4 (1)
Здравствуйте, Alexey Voytsehovich, Вы писали:

AV>Здравствуйте, Danchik, Вы писали:


D>>Здравствуйте, Alexey Voytsehovich, Вы писали:


AV>>>Всем доброго дня. Столкнулся с задачей, которую ранее не решал. Решил проконсультироватся с сообществом чтобы не изобрести очередной велосипед


D>>Делить большой кусок на чанки (chunk)

D>>Например так:

D>>Так как протокол ассинхронный, неплохо будет наставить таймаутов где надо. Не пришло то то за такое то время — делаем то то.

D>>Надеюсь все понятно?

AV>ну вроде примерно так и я думал, вот только вот что меня напрягает — вроде бы как tcp-ip протокол тоже умеет чанковать и собирать на другой стороне? или же я заблуждаюсь и он это умеет делать в пределах 64К?


В принципе, все можно возложить на TCP/IP, но если вы хотите слать асинхронно, то размер буфера действительно ограничен. В синхронном варианте — просто шлете первый кусок с размером:
  packed record
    PacketType : Byte;     // sending buffer
    DataSize: LongWord     // размер данных
  end;

И досылаете остальные данные простым send в цикле пока буфер не закончится.
Re[4]: Пересылка через сокеты больших обьемов данных
От: Alexey Voytsehovich Украина  
Дата: 27.11.09 14:52
Оценка:
Здравствуйте, Danchik, Вы писали:


D>В принципе, все можно возложить на TCP/IP, но если вы хотите слать асинхронно, то размер буфера действительно ограничен.


понятно. спасибо. Работать надо именно асинхронно.
Я не умею быть злым, и не хочу быть добрым.
Re: Пересылка через сокеты больших обьемов данных
От: Anton Golinko  
Дата: 27.11.09 21:18
Оценка:
Здравствуйте, Alexey Voytsehovich, Вы писали:

AV>Дано: необходимо переслать с клиента на сервер большой обьем данных (не хотелось бы ограничивать себя), с получением от сервера обратно подтверждения о получении данных.


AV>Что есть. Есть ICS библиотека асинхронных сокетов, у которых есть send и recv (упрощенно).


Правильно, зачем изобретать велосипед, когда все уже изобретено до нас

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

1. Качать Ыксплорером
Обрыв связи — и перезакачивать все заново.
Это обычный TCP-стриминг.

2. Качать Оперой/Огнелисом.
При обрыве связи, есть возможность возобновления закачки.
Это более интеллектуальная передача контента, с возможностью его "дособирания" по кусочкам

3. Качать даунлоадменеджером.
Многопоточная закачка, сразу нескольких кусков контента.
Максимальная производительность — если пакет от одного чанка где-то и застрял, то освободившуюся нишу в ширине канале займет пакет из другого чанка.
Это более продвинутая разновидность второго способа.

=================================================================
Навскидку, мой mindflow:

Для обеспечения надежности нужно каким-то образом возобновлять коннект. Предположим что связь осуществляется по принципу как в HTTP — на каждый запрос, должен быть ответ.

У каждой пары Request&Response должен быть уникальный ID — для запроса и ответа. RequestID и ResponseID.
При обрыве связи инициирующая сторона должна переконнектится и:
1. Если она передавала данные, то она должна спросить у другой стороны сколько данных та получила(по ID), и возобновить передачу с места обрыва
2. Если принимала данные, то также само: переконнектится, сказать что мне нужны данные для такого-то запроса(ID), с такого-то места

На каждой стороне должен быть таймаут на время жизни запроса.
Например если клиент при заборе данных с сервера, оборвался, и не переконнектился в течении timeout, то буффер (кеш ответа) на сервере очищается.


Как-то где-то так,
а сейчас спать!
хронический недосып, это очень и очень плохо...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.