WinSock: как лучше?

Тема в разделе "WASM.NETWORKS", создана пользователем perez, 10 ноя 2005.

  1. perez

    perez Member

    Публикаций:
    0
    Не думал, что могут возникнуть проблемы в этой теме,

    но все же.

    Есть сервер и несколько клиентов (протокол TCP).

    Клиенты общаются с сервером. Причем данные ходят

    совершенно разного типа: могут передаваться файлы,

    может передаваться просто какая-нибудь управляющая

    информация и т. п.

    Сначала я сделал так, чтобы при каждой потребности

    клиент подключается к серверу и передает/получает инфу,

    после чего закрывает соединение.

    Но здесь много минусов:

    1) каждый раз надо создавать соединение

    2) есть вероятность застрять на accept в клиенте

    при обрыве связи во время того, как сервер в цикле

    передает данные

    3) Больше проверок на ошибки

    4) etc...



    Потом переделал так:

    Клиент коннектится к серверу и хранит соединение во

    время всей работы. Сервер создает отдельный тред

    и в бесконечном цикле принимает данные от клиента (recv).

    Приняв какие-то данные, сервер отвечает клиенту send-ом.

    Все вроде бы хорошо, НО функция recv возвращает ноль,

    только при ОБРЫВЕ связи с клиентом. Т.е. когда клиент

    разрывает соединение.

    Я сделал так: recv бесконечно принимает данные порциями

    по 100 байт. И каждый раз проверяет эти 100 байт на

    вхождение сигнатуры, обозначающей конец приема "*EOF*".

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

    на recv.



    Минусов у этого метода предостаточно.



    Так как же делать лучше?

    Жду советов...
     
  2. perez

    perez Member

    Публикаций:
    0
    :dntknw:

    67 просмотров и ни одного ответа..
     
  3. MegaZu

    MegaZu New Member

    Публикаций:
    0
    Ты задачу обьясни нормально. В чем проблема ?!
     
  4. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Реализуй свой простой протокол. В своей проге я делал так. Первые 4 байта идут на длину пакета, дальше принимается и накапливается в буфере пока не придет весь пакет. Главное поставить ограничение на длину и т.п. чтоб сильно не ломали. При передачи файлов немного расширил формат "пакета" :) Сначала длина всего пакета, потом позиция с какой файл передается, потом длина имени, потом имя, и только потом файл. Прекрасно работает + докачка.
     
  5. MegaZu

    MegaZu New Member

    Публикаций:
    0
    Если проблема в опознаваию данных тогда зделай свои пакеты (структуры). В каждом пакете должно быть поле ХЕДЕР пакета. ПроЕнумь все типы пакетов(для удобства). И читай с сокета хедер пакета что пришел. Когда получил тип пакета читаешь сам пакет.



    struct Hdr

    {

    int PacketId;

    int PacketLen;

    };



    struct Packet1

    {

    Hdr packetHdr;

    ...

    };



    struct Packet2

    {

    Hdr packetHdr;

    ...

    };



    Hdr PacketInfo;

    Packet1 p1;

    Packet2 p2;



    recv(socket,(char*)&PacketInfo,sizeof(Hdr),0);

    switch(PacketInfo.PacketId)

    {

    case 1:

    {

    memcpy(&p1.packetHdr,&PacketInfo,sizeof(Hdr));

    recv(socket,(char*)(&p1+sizeof(Hdr)),sizeof(Packet1)-sizeof(Hdr),0);

    }



    Что то типа такого. Валял здесь так что мог что-то профтикать :) Но суть я думаю понятна.
     
  6. perez

    perez Member

    Публикаций:
    0
    SnugForce

    Я примерно так и сделал. Но проблема не в этом.

    Если связи не обрывать, recv будет беконечно принимать

    данные, сколько бы раз клиент не вызвал send. Проблема

    различить логические блоки данных. Например, клиент

    послал запрос на получение файла и сразу же запрос на

    получение фамилии какого-то пользователя в базе. Сервер все примет в один бкфер. А если коиент еще и файл

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



    MegaZu

    Насчет своих пакетов идея хорошая, попробую..
     
  7. MegaZu

    MegaZu New Member

    Публикаций:
    0
    А принимать все данные в один буфер а потом парсить - БРЕД !!!Загнаться можна в 3 секи, что зделает прога если клиент отправит такой набор данных как твой идентификатор пакета ? Юзать свои пакеты оптимальный вариант. Так как ты будеш всегда знать какой пакет пришел + мона crc присобачить для верификации данных.
     
  8. SnugForce

    SnugForce New Member

    Публикаций:
    0
    perez

    Нет не получиться, для этого нуна указать типа пакета. Только есть еще проблема, если начать пересылать файл, то отправка других пакетов, как и прием будет не возможен. Я просто сделал на разных портах. Я делал не на структурах, а просто выдерал из памяти необходимые данные, проверив их до этого на все что можно. Далее в зависимости от типа пакета передавал в свою функцию для обработки. При при необходимости, а она была, делал вложенные пакеты т.е. иерархия внутреннего протокола.
     
  9. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Код приводить не буду. т.к. на Паскале... боюсь...
     
  10. perez

    perez Member

    Публикаций:
    0
    у меня было так:

    каждый логический блок состоит из:



    5 байт- длина заголовка

    по смещению из этого числа идет буфер, к примеру, файл.

    заголовок устроин как в методе GET:

    название=значение&название=значение&название=значение.



    Но как сервер узнает, что пришел новый логический блок?

    Логический блок может быть большим и принимается

    циклически recv-ом.
     
  11. perez

    perez Member

    Публикаций:
    0
    Если использовать свои пакеты, тоже много проблем.

    Файл может быть большим.
     
  12. perez

    perez Member

    Публикаций:
    0
    SnugForce

    я тоже делал на разных портах- файлы на один порт,

    управляющая инфа-на другой. Но это надо пересылать

    как от клиента к серверу, так и наоборот. Много возьни

    и проверок.

    Хотелось сделать все через одно подключение, хранимое

    в течение всейго времени работы клиента
     
  13. MegaZu

    MegaZu New Member

    Публикаций:
    0
    perez

    Какие проблемы ?? Делаешь доп. поля в пакете для обмена файлами - bool AppendToFile , i int SegmentSize.



    Если файл = 4097 байта а буфер для данных допустим 4к , то клиент будет слать 2 пакета.

    В 1 пакете AppendToFile - false (то есть создать файл или перезаписать) , SegmentSize - 4к;

    В 2 пакете AppendToFile - true , SegmentSize - 1;
     
  14. perez

    perez Member

    Публикаций:
    0
    Спасибо всем за ответы.

    Примерно так и придется делать, наверное.
     
  15. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Тады надо отсылку пакетов ставить в очеред. Формировать пакеты в одной функции. По-любому слать файл нуна будет в отдельном потоке, а месаги в другом. Синхронизировать доступ к функции формат-пакетов с CriticalSection. Очередь можно организовать либо самому, либо юзать стандратные функции NT. Я брал первый способ, хотя использовал немного по другому назначению пул обработки.
     
  16. perez

    perez Member

    Публикаций:
    0
    Думаю сделать так.

    Будут идти такие пакеты: заголовок и, если есть,

    буфер данных.



    Если надо передать упр. информацию, проблем нет- в

    заголовке будет указано, что это управляющая информация.



    Если это файл, клиент разбивает его на куски по 150 байт

    и отправляет пакетами. В заголовках таких пакетов будет

    название файла и информация о части файла, к примеру,

    3-й из 10-ти.



    Когда все части соберутся, сервер сохранит на диск файл.
     
  17. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Да тут главная проблема по ходу в отправке данных, а не приеме. Одно замечание - зачем весь файл хранить в буфере, а только после приема сохранять на диск? И зачем номер куска файла? Отправлять все равно будешь посл-но, а TCP обеспечит правильную последовательность автоматом.
     
  18. perez

    perez Member

    Публикаций:
    0
    Млин, приехали.

    Попробую объяснить еще раз.

    После отправки файла клиент НЕ разрывает связь.

    Это значит, что recv продолжает слушать интерфейс.

    КАК УЗНАТЬ, что отправка файла закончена,

    и начилась отправка ДРУГОГО?

    Собственно, это вопрос, с которым я обратился сюда
     
  19. SnugForce

    SnugForce New Member

    Публикаций:
    0
    ААА :)) я сразу не понял

    В начале отсылать размер файла :)
     
  20. perez

    perez Member

    Публикаций:
    0
    не пойдет. Может в это время другая инфа прийти