Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2005.11.06;
Скачать: [xml.tar.bz2];

Вниз

Промогите разобраться ServerSocket1 и ClientSocket1   Найти похожие ветки 

 
Кабан   (2005-10-11 23:31) [0]

С компонентами ServerSocket1 и ClientSocket1 рабоаю в первый раз, в связи с этим в проуессе работы  возникли вопросы.

1. Вот кусок кода в обработчике ClientRead

ServerSocket1.Socket.Connections[0].SendText("трям");
ServerSocket1.Socket.Connections[0].SendText("бла бла");

При посылке этих двух сообщений клинская часть иногда принимает склеенное сообщение причем не всегда. Почему так происходит и как этого избежать ?

2. В документации прочитал что существует метод SendBuf который позволяет пересылать целые структуры данных на пример массив или запись. Но как им пользоваться до конца не понял, в частности интересует параметр Count, в документации написанно что он указывает на размер пересылаемых данных. Это получаеться что я сам должен подсчитывать количество пересылаемых данных ? Пожалуйста приведите пример пересылки данных  методом  SendBuf.


 
kami ©   (2005-10-12 09:24) [1]

Кабан   (11.10.05 23:31)

Читать статьи, например, http://www.delphimaster.ru/articles/sockets/index.html и http://www.delphimaster.ru/articles/socksrv/index.html .
Там как раз с примерами.


 
Digitman ©   (2005-10-12 11:24) [2]


> Это получаеться что я сам должен подсчитывать количество
> пересылаемых данных ?


ну а как же ты думал иначе ?

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

то же самое относится и к принимающей стороне, использующей ReceiveBuf()


 
Кабан   (2005-10-13 18:17) [3]

Короче запутался я с методом SendBuf
На стороне сервера пишу следующее:

procedure TForm1.Button1Click(Sender: TObject);
var
 i:string[3];
 c:integer;
begin
 i:="sss";
 c:=Length(i);
 ServerSocket1.Socket.Connections[0].SendBuf(i,c);
end;

На стороне клинта :

procedure TForm1.ClientSocket1Read(Sender: TObject;
 Socket: TCustomWinSocket);
var
 i:string[3];
 c:integer;
begin
 c:=Socket.ReceiveLength;
 SetLength(i,c);
 Socket.ReceiveBuf(i,c);
 Memo1.Lines.Add(i);
end;

В место строки "sss" на клинт приходит "ssw" ((( В чём моя ошибка ?


 
kami ©   (2005-10-13 19:12) [4]

SendBuf(i[1],c);

ReceiveBuf(i[1],c);

Если используешь строки с фиксированнной длиной, то не нужно устанавливать их длину (SetLength).

Сразу - вопрос: а ты уверен, что прийдет именно 3 байта (String[3]) ?


 
Кабан   (2005-10-13 23:25) [5]

Спасибо за помощь с SendBuf вроде разобрался, но возникла другая проблема. Когда на сервере обрабатываю событие ServerSocket1ClientRead и в нём использую для отправки клиенту метод SendBuf, сервер виснет (( Если для отправки информации использую метод SendText, то всё работает нормально. Вот код обработчика. Если вставляю этот код куда нибудь в другое место например в в обработчик нажатия кнопки, то тоже нормально всё работает.

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
type
 RBufer=record
   i:integer;
   s:string;
 end;

var
 Bufer:RBufer;
 command:string;
 c:integer;
begin
 command:=Socket.ReceiveText;
   if command="1" then begin
   Bufer.i:=12;
   Bufer.s:="sar";
   c:=SIZEOF(Bufer);
   ServerSocket1.Socket.Connections[0].SendBuf(Bufer,c);
end;

end;


 
kami ©   (2005-10-14 00:01) [6]

Что-то мне подсказывает, что клиент и сервер находятся в одном приложении, возможно даже на одной форме :)
НИЗЯ пытаться переслать таким боком record-ы.
Попробуй поменять содержимое Bufer.s и посмотри на изменение SIZEOF(Bufer); - ничего ! не изменится, как было 8 байт, так и останется. Потому что твой Bufer - всего лишь указатели на структуру в памяти (наверно, неправильно сказал, Мастера поправят).
Для примера - я всё передаю членораздельно -<вырезано цензурой> каждый член в своей раздельности :)</вырезано цензурой>
То есть -
SendBuf(Bufer.i,SizeOf(integer));
SendBuf(Bufer.s[1],Length(Bufer.s));


 
Кабан   (2005-10-14 00:34) [7]

kami нет клиент и сервер находяться в разных приложаениях.
Ещё раз описываю суть проблемы.
Если в серверной части я и использую метод SendBuf в обработчике событий ClientRead то то серверная часть виснет, а если например использую тот же метод но например в обработчике нажатия какой нибудь кнопки или ещё где то то данные отправляються нормально, причём без всяких ошибок, то есть как надо. Но меня это не устраивает мне надо что бы данные отправлялись в обработчике событий ClientRead, то есть когда с клинта на сервер приходит команда. Из приведённого кода видно что клиенская часть посылает серверной части команду, после которой клиенской части должны отсылаться данные, но сервер при этом виснет. Если использую методод SendText по данной схеме всё работает нормально. Могу если надо исходнеки выслать.


 
Digitman ©   (2005-10-14 10:37) [8]


> Кабан   (14.10.05 00:34) [7]


После установки соединения между клиентом и сервером образуется некий "транспортный канал", по которому стороны обмениваются инф.потоками вплоть до разрыва этого канала по каким-либо причинам.

Пользуя этот канал стороны соединения полностью эквивалентны с т.з. цели существования и использования созданного канала - в каждый момент времени какая-то из сторон передает данные, а другая, соответственно, ожидает/принимает эти данные .... Поэтому здесь следует придерживаться иной терминологии - "передатчик" и "приемник"  инф.сообщения, а кто из них "сервер" и кто "клиент" - с этой т.з. совершенно безразлично.

Ну это так, к слову ..

Т.е. ты утверждаешь, что если в событии On[Client]Read вызвать SendBuf(), то именно при выполнении этой строчки происходит "вис" ?


 
kami ©   (2005-10-14 10:49) [9]

Кабан   (14.10.05 0:34) [7]
Проблема явно не в том, что данные отсылаются в OnClientRead - у меня в этом событии отправляются мегабайты, и без проблем. C SendBuf проблем тоже не вижу, если только то, что передается ни разу не содержимое буфера (меня как-то ткнули носом в это). В приведенном коде зависания быть не должно.

Могу если надо исходнеки выслать
Не надо, разбираться в чужом, тем более плохо форматированном коде нет особого желания, к тому же я работаю на D5 и не знаю, может в D7 в сокетах появились новые свойства, да и конвертить dfm нет желания :) Отладчиком пробовал пройтись по серверу?

Попробуй ещё вместо
> ServerSocket1.Socket.Connections[0].SendBuf(Bufer,c);

поставить Socket.SendBuf(Bufer,c); ,так как в обработчике ClientRead параметр Socket - это как раз гнездо того клиента, который прислал данные.

Но, ещё раз говорю - лучше (имхо) пересылать всё в отдельности, особенно если дело касается длинных строк. Что мешает сделать отдельную процедуру, отвечающую за передачу RBuffer, допустим

type
RBuffer=record
  i:integer;
  s:string;
end;
//------------------------------
procedure RBufSender(const buffer : RBuffer; Socket : TCustomWinSocket);
begin
 Socket.SendBuf(buffer.i, SizeOf(Buffer.i));
 Socket.SendBuf(buffer.s[1], Length(Buffer.s));
end;

procedure TForm1.ServerSocket1ClientRead(Sender : TObject; Socket : TCustomWinSocket);
var
 command : string;
 Buffer : RBuffer;
begin
 command := Socket.ReceiveText;
 if command = "1" then
   begin
     Buffer.i := 12;
     Buffer.s := "sar";
     RBufSender(Buffer, Socket);
   end;
end;

Тогда при изменении структуры RBuffer нужно будет переделать только процедуру RBufSender, а данные через неё можно отправлять в обработчиках любых событий.


 
Digitman ©   (2005-10-14 11:17) [10]

В неблок.режиме :

1. Следует обязательно анализировать результат выполнения вызванного передатчиком инф.сообщения любого send-метода - этот результат покажет, сколько байт из числа запрошенных к передаче было успешно поставлено в очередь на передачу (именно поставлено в очередь, а не фактически передано и доставлено приемнику !)

2. Если анализируемый результат покажет, что в очередь на передачу поставлены данные размером меньше, чем затребовано к постановке, следует немедленно прекратить все дальнейшие попытки постановки в очередь, дождаться ближайшего по времени события On[Client]Write и только по факту возникновения этого события пытаться продолжить постановку в очередь оставшихся (реально не поставленных при предыдущем по времени вызове send-метода) данных.

Нереализация такой логики ведет к ПОЛНОЙ неработоспособности алгоритмов распределенных сет.приложений в межсетевых условиях транспорта.


 
kami ©   (2005-10-14 12:20) [11]

Digitman ©   (14.10.05 11:17) [10]
Это уже пахнет :) собственной надстройкой над TXXXSocket с, хотя бы, собственной очередью на передачу.

Имхо, если пересылаются (как в [5]) несколько байт, причем не часто, то это излишнее - сокет триста раз успеет передать всё, что в его буфере оказалось даже при большой загруженности сети, прежде чем поступят новые данные.


 
Digitman ©   (2005-10-14 12:41) [12]


> kami ©   (14.10.05 12:20) [11]


> Это уже пахнет :) собственной надстройкой над TXXXSocket


очередной велосипед ?)

на то куча готовых компонентов существует... взять хоть все те же Indy-компоненты


> если пересылаются (как в [5]) несколько байт, причем не
> часто, то это излишнее


про "излишнее" будешь втирать своему заказчику, который заплатил тебе за однажды отказавшее по именно этой причине приложение

как будут двигаться фрагменты TCP-потока по глоб.сети, как этот поток будет фрагментироваться/собираться при доставке адресату - судить никто не вправе : это зависит от реальных (а не предполагаемых тобой на основании ограниченных экспериментов) сетевых условий,


 
kami ©   (2005-10-14 13:52) [13]

Digitman ©   (14.10.05 12:41) [12]
Почему велосипед ? предпочитаю, если возможно, не использовать сторонние библиотеки(а размер программы они увеличивают неплохо), чтобы не добавлять функционал, который я не буду использовать и на половину. Поэтому из всех готовых компонентов этой области я выбрал свои, сделанные при помощи Verg © и Alexander Panov ©.

> про "излишнее" будешь втирать своему заказчику

Это да, есть такое дело, может ещё самого без фонарика отправить искать потерявшийся пакет :) Но опять же по поводу Indy - про их глюки и недоработки здесь уже были ветки (на вскидку назову только один - при проходе MemProof-ом показывает, что не освобождается критическая секция). Поэтому, опять таки - лучше искать глюки в своем коде, чем в чужом, пусть и самом великолепном. Имхо.


 
Кабан   (2005-10-15 00:11) [14]

Переделал серверную часть, то есть создал проект с нуля, написал тот же самый код, как ни странно всё заработало ))) Всем спасибо за ответы.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2005.11.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.047 c
14-1129192100
Иванов__
2005-10-13 12:28
2005.11.06
Что случилось с форумом?


1-1129207393
Квэнди
2005-10-13 16:43
2005.11.06
Цвета в StringGrid


14-1129609939
DelphiN!
2005-10-18 08:32
2005.11.06
Выделить из предложения все глаголы


2-1129123747
DelphiLexx
2005-10-12 17:29
2005.11.06
Проблемы с TChart


14-1129203524
BaxTMaH
2005-10-13 15:38
2005.11.06
треба помощь





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский