Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ClientSocket, ServerSocket - несколько отправок [D6]


Страницы:   1 2 3

Brand ©   (2002-07-11 23:07:00) 

Если один из этих компонентов выполняет SendText и тут в момент выполнения опять вызывается SendText. Что будет: выскочет ошибка или этот запрос станет в очередь и выполнится после того, как выполнится предыдущая SendText?


Володя Шарапов   (2002-07-25 11:15:00) [1]

Я тут почитал как предлагают организовать пересылку.
Попробовал с использованием разделительных символов - у меня получилось.


Alex SV   (2002-07-25 11:11:00) [2]

> Brand
Так расскажи нам как ты реализовал отправку?


Alibaba   (2002-07-25 11:09:00) [3]

> Brand
Ты ж акуратненько с такими вопросами... :)


Fredericco   (2002-07-23 10:38:00) [4]

2cyborg ©
Ты прав. У меня просто не совсем стандартное пременнение сокетов, и структура сети, моей, тоже спецефичная, поэтому такие идеи и рождались.


cyborg   (2002-07-22 20:03:00) [5]

С этим кодом работает как сервер так и клиент, сокет то в принцпе такой же, только сервер ждёт когда к нему подключатся, а клиент подключается, у меня чат работает по такому принципу, что сервер, что клиенты, каждая мессага идёт в свою трубу, никакие сокеты между собой по идее не смешиваются, когда сервер посылает одному клиенту, это сообщение никак не может придти в непредназначенный сокет. Если бы так было, как ты говоришь, то при отправке из сервера мессаг всем клиентам, то все вместе мессаги приходили бы только первому попавшемуся клиенту?
Я понимаю так, что при подключении клиента к серверу сервер создает новый сокет и никак данные из одного сокета не могут попасть в другой сокет, если только сам сервер не посылает им данные.
Лучше конечно сделать с sendbuf но в строке удобно то, что можно легко обратиться к определённому байту string[x] поэтому я так сделал, в принципе sendbuf и sendtext одно и тоже, sendtext использует тот же SendBuf, сам в исходниках посмотри. Ctrl держи и мышкой на функции нажимай, если у тебя пути прописаны к библиотекам модулей, то перескочишь на исходный текст той функции.


Fredericco   (2002-07-22 19:09:00) [6]

cyborg ©
Может я ошибаюсь и сейчас (конец рабочего дня - простительно), но на стороне сервера ИМХО, прием данных делать как ты сказал, а отправку по моему способу. Тогда и клиентское сообщение не потеряется на сервере (твой способ) и каждому клиенту дойдет его сообщение (мой способ).
Ежели что не так, критекуй!


Brand   (2002-07-22 17:35:00) [7]

А вот и я, автор.
Блин, я уже давно все сделал и забыл про эту тему. А вот зашел, шляжу, а тут такое..................
Граждане, спокойствие, только спокойствие.


cyborg   (2002-07-22 17:08:00) [8]

Делается так:
Procedure ProcessData( передаваемые данные; var Socket : TWinSocket);
Begin
//обрабатываем данные если нужно посылаем Socket что требуется
End;


дальше из моего примера

repeat
Move(StringReceive[1],ReceiveCheck,4);
Move(StringReceive[5],DataSize,4);
if ReceiveCheck=Check then //Если признак начала правильный
if DataSize+8<=Length StringReceive then
begin //Если сообщение не обрезанное
SetLength(StringMessage,DataSize);
Move(StringReceive[9],StringMessage[1],DataSize);
Delete(StringReceive,1,DataSize+8);
ProcessData( StringMessage, Socket);
end
else Quit:=True
else Quit:=True;
until quit;


Fredericco   (2002-07-22 16:51:00) [9]

Так. Я не прав. Думал только о клиентах. То что я придумал - можно проще, так как вы советуете. Сорри, что спорил.
Встает вопрос.
Скажем есть на сервере единая процедура обработки сообщения пришедшего от клиентов.
procedure TextReceiveFromClient(const Text:string);
Вот сервер получил сдвоенное сообщение, разделил его на два, как дальше поступить? Ведь нужно сначал вызвать процедуру с первым сообщением, а потом со вторым? Как быть?


Fredericco   (2002-07-22 16:39:00) [10]

2cyborg ©
У тебя только один клиент?
У меня нет. И важно что бы каждый получил таки свое сообщение.
А на счет разделителя в строке, мой собственный протокол построен так, что клиент только свое и заберет.
У меня структура системы такая, чот один клиент посылает серверу комманду: пошли клиенту такому-то такое-то сообщение. И если в тоже мнгновение получится: пошли клиенту другому-то такое-то сообщение. То сообщение придет первому и сдвоенное. Вот почему я использую алгоритм описанный мной выше.

> ИМХО для разных задач разный способ.


cyborg   (2002-07-22 14:55:00) [11]

panov © про разделители в строке мы тут обсуждали уже, работать будет, но всё таки .... короче обсуждали уже :)


cyborg   (2002-07-22 14:53:00) [12]

Какой один, какой другой клиент?
В один сокет приходит, в одном и разделяется всё. И все сообщения получаются, а не только первое. Этот код хоть 100 склееных сообщений разделит.


panov   (2002-07-22 13:45:00) [13]

Если передается текстовая информация, достаточно к каждой строке добавить символ(символы)-разделители, и при обработке принятой информации просто вычленять строки, что делается достаточно просто...


Fredericco   (2002-07-22 10:53:00) [14]

2cyborg ©
Давай относительно не нужного бреда будем помягче.
Может для кого-то это не бред и нужный.
В моем случае исключена возможность "склееных" сообщений. В твоем же идет проверка, что дает клиенту возможность однозначно прочитать только свое сообщение.
Минусы моего способа низкая скорость.
Минусы твоего способа "склеенное" сообщение получит только один клиент, второй ничего не получит.
ИМХО для разных задач разный способ.


cyborg   (2002-07-20 08:28:00) [15]

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

Выдумываем структуру передачи данный в которой обязательно должен быть признак правильности данных, т.е. получатель будет опозноватьь данные что это те данные которые нужны, т.е. правильные.Сразу после него должна быть длина следующих за ним данных.
Назовём например признак данных именем Check, длинну DataSize.
Теперь по этим данным у нас будет в начало каждого сообщения входить эти данные.

Const
Check : Cardinal = $ABABAB01;//Признак начала получаемых данных
Var
DataSize : Cardinal; //Размер данных


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


Var
StringMessage : AnsiString;
HeadData : Array[1..8] of char;//Заголовок
...

StringMessage:="Привет!";
DataSize:=Length(StringMessage);
Move(Check,HeadData[1],4);
Move(DataSize,HeadData[5],4);
StringMessage:=HeadData[1]+HeadData[2]+HeadData[3]+HeadData[4]+
HeadData[5]+HeadData[6]+HeadData[7]+HeadData[8]+
StringMessage;
//Нужно отдельно складывать потому что если встретится в массиве
//#0 то он обрежется
Socket.SendText(StringMessage);//Отсылаем

теперь получаем строку

Var
StringReceive : AnsiString;
ReceiveCheck : Cardinal;
Quit : Boolean;
...
Quit:=False;
StringReceive:=Socket.ReceiveText;
repeat
Move(StringReceive[1],ReceiveCheck,4);
Move(StringReceive[5],DataSize,4);
if ReceiveCheck=Check then //Если признак начала правильный
if DataSize+8<=Length StringReceive then
begin //Если сообщение не обрезанное
SetLength(StringMessage,DataSize);
Move(StringReceive[9],StringMessage[1],DataSize);
Delete(StringReceive,1,DataSize+8);
Тут выводим строку StringMessage в окно или обрабатываем её
end
else Quit:=True
else Quit:=True;
until quit;


Вот простой способ разделения строк, единственное он не склеивает разорванные строки.
Писал код в браузере в Дельфи не проверял, возможны некоторые ошибки.


Fredericco   (2002-07-19 18:35:00) [16]

2Alibaba
Но я же не посылаю сообщение каждые 50 миллисекунд, а лишь проверяю, если есть сообщение в очереди я его пошлю, а если нет то и не буду ничего посылать

> if CurrentM<1 then Exit;


Alibaba   (2002-07-19 17:40:00) [17]

У нас на работе иногда сетка притормаживает по разным причинам:
1. С одного компа на другой качают жирный кусок информации.
2. Перестраивают сетку, меняют конфигурацию.

И тогда наблюдаются заметные задержки при работе с сетью.
Можно говорить о том что сетка администрится не правильно и настроенна не очень хорошо - только мне от этого не легче.


Fredericco   (2002-07-19 17:25:00) [18]

2Alibaba ©
Из-за чего сетка будет тормозить то?!
50 миллисекунд вполне приемлемо, по крайней мере у меня нормально работает.


Alibaba   (2002-07-19 16:57:00) [19]

Да, это тоже может работать, но..
Почему 50 миллисекунд?
Сетка может очень тормозить и указанного времени не хватит для отправки - в результате опять все склеится.


Fredericco   (2002-07-19 16:45:00) [20]

2Brand
Я делаю так.
Есть масив и переменная

Mas:array[1..100] of string;
CurrentM:integer;

Когда я хочу отправить текст я просто делаю так

CurrentM:=CurrentM+1;
Mas[CurrentM]:=YourText;

Есть так же таймер с интервалом в 50 миллисекунд, каждый раз когда он срабатывает выполняется такой код:

if CurrentM<1 then Exit;
ClientSocket1.Socket.SendtText(Mas[1]);
for i:=2 to CurrentM do
Mas[i-1]:=Mas[i];
CurrentM:=CurrentM-1;

Как видишь вместо того, что бы отправлять сообщение сразу, я его ставлю в очередь. А каждые 50 миллисекунд отправляю сообщение стоящее первым в очереди.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо