TServerSocket – пердача данных
Билдер 6
Задача – прога принимает данные (текст) с сервера на линухе, который просто копирует текст строку за строкой из файла в сокет
while( f ) /*sending file string by string*/
{
getline(f, line, '\n');
fprintf(s, line.c_str());
}
Где f – поток связаный с дисковым файлом, а s – поток привязанный к открытому сокету
На стороне сервера к которому он подрубается (винды) имеем компонент TServerSocket (stNonBlocking)
void __fastcall TForm1::SS1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
AnsiString s;
s = Socket->ReceiveText();
Memo1->Lines->Add("Lines are:");
Memo1->Lines->Add(s);
}
Когда передается несколько строк – все ок. (строка по 100-150 символов), но если размер байла больше нескольких килобайт то происходит такое – строки получаются сервером кусками, т.е. как если бы SS1ClientRead вызывалась несколько раз подряд и каждый раз получала куски файла с того момента где передача была прервана 
Задача – получать строки в любом количестве (заранее их число не известно), размеры фалов от 1к до 10Мб целиком, без подобных происшествий...
Как я понимаю AnsiString хранит данные до 2Гигов....
Подскажите выход кто знает ... это мой первый проект клиент-сервер
Решение очевидно. Нужно сначала посылать размер передаваемых данных. На стороне сервера после приема будет известен размер данных которые необходимо получить. После этого посылются собственно данные. На стороне сервера ReceiveText вызывается до тех пор, пока не получены все данные. Вновь полученные данные дописываются в конец принимающего буфера.
Хм... а можешь набросать примерно как это должно выглядеть?
На стороне сервера вызывается не ReceiveText а именно вся функция в которой вызывается ReceiveText, т.е. в Мемо1
пишется
Lines are:
line1
line2
....
lineN - обычно не полностью
далее снова
Lines are:
LineN - оставшийся кусок строки
LineN+1
....
и так далее
НЕ НУЖНО.
2 - Надеюсь TMemo только для отладочных целей используешь.(Он сильно снижает скорость работы программы и не может отображать тексты более 50 кб. или 500 кб - точно не помню - кто помнит пусть поправит.)
Подробное описание см. здесь:
TServerSocket::прием данных
и здесь:
TClientSocket::отправка данных
1 - Посылать размер передаваемых данных
НЕ НУЖНО.
2 - Надеюсь TMemo только для отладочных целей используешь.(Он сильно снижает скорость работы программы и не может отображать тексты более 50 кб. или 500 кб - точно не помню - кто помнит пусть поправит.)
Подробное описание см. здесь:
TServerSocket::прием данных
и здесь:
TClientSocket::отправка данных
Спасибо за ответ ART-CODE. Вроде разобрался только пока разбирался перешел на компонент TTcpServer. Все идет хорошо, но только - по вызову Close() Он почему-то не перестает слушать указанный ему порт :) Не знаешь в чем может быть проблема? Причем он принимает клиентские запросы но не вызывает никаких обработчиков. Кроме того при повторном вызове Open() он тоже принимает запросы и тоже ничего не делает :) Приходится закрыть-открыть программу.
Кто сталкивался с таким?
Каждый из используемых тобой компонентов является
оберткой для настоящих виндовских сокетов. Чтобы пользоваться оберткой нужно понимать что делают сокеты на самом деле.
Где-то на этом форуме я уже писал:
Настоятельно рекомендую приобрести книгу
"Эффективное программирование TCP/IP"
из серии "библиотека программиста"
там шаг за шагом в лабораторных работах подводят к пониманию работы протоколов.
На прочтение книги потеряешь неделю, но
без этого написать устойчиво работающюю сетевую программу нельзя.
Из книги ты узнаешь, что есть несколько способов остановить сервер,
быстро-не всегда оказывается правильно!
По твоему вопросу:
Так и должно быть.
Вероятно тебе при использовании TcpServer->Close()
прийдется ждать 2-4 минуты до реальной остановки сервера (Таковы правила работы протокола TCP/IP в чати состояния TIME_WAIT)или найти какой-то метод этого класса, оcтанавливающий сервер немедленно.(Я с этим классом не работал поэтому не знаю, но протокол TCP/IP такую возможность предусматривает.)
Набери в командной строке
netstat -a
посмотри что написано рядом с номером порта твоего сервера после вызова
TcpServer->Close() если я прав, то там будет в поле "СОСТОЯНИЕ" запись "TIME_WAIT".
Все идет хорошо, но только - по вызову Close() Он почему-то не перестает слушать указанный ему порт :)
Каждый из используемых тобой компонентов является
оберткой для настоящих виндовских сокетов. Чтобы пользоваться оберткой нужно понимать что делают сокеты на самом деле.
Где-то на этом форуме я уже писал:
Настоятельно рекомендую приобрести книгу
"Эффективное программирование TCP/IP"
из серии "библиотека программиста"
там шаг за шагом в лабораторных работах подводят к пониманию работы протоколов.
На прочтение книги потеряешь неделю, но
без этого написать устойчиво работающюю сетевую программу нельзя.
Из книги ты узнаешь, что есть несколько способов остановить сервер,
быстро-не всегда оказывается правильно!
По твоему вопросу:
Так и должно быть.
Вероятно тебе при использовании TcpServer->Close()
прийдется ждать 2-4 минуты до реальной остановки сервера (Таковы правила работы протокола TCP/IP в чати состояния TIME_WAIT)или найти какой-то метод этого класса, оcтанавливающий сервер немедленно.(Я с этим классом не работал поэтому не знаю, но протокол TCP/IP такую возможность предусматривает.)
Набери в командной строке
netstat -a
посмотри что написано рядом с номером порта твоего сервера после вызова
TcpServer->Close() если я прав, то там будет в поле "СОСТОЯНИЕ" запись "TIME_WAIT".
Дело в том что по описанию класса Close() или установка свойства Active=false должна приводить к закрытию серверного сокета. Но этого не происходит.. причем свойство Active после вызова Close() всетаки false :) Но сокет находится не в состоянии TIME_WAIT а в состоянии LISTENING неограниченно долго.
Здесь не обойтись без написания тестовой програмки и ковыряния исходников компонента, а времени сейчас нет. Мож кто другой подскажет...
Удачи.