Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.04.07;
Скачать: CL | DM;

Вниз

СерверСокет   Найти похожие ветки 

 
TButton ©   (2003-02-13 18:07) [0]

Задача.
Есть некий сервер к которому подключено х клиентов.
Спрашивается.
Как отправить сообщение определенному клиенту.

сервер и клиент построены на сокетах. загвоздка в том что количество клиентов постоянно меняется и при попытке отправить сообщение через Socket.Connections[n] оно может прийти совсем другому клиенту.


 
mrcat ©   (2003-02-13 21:37) [1]

у каждого сокетного соединения есть хэндл, можно им пользоваться, можно также юзать Data: Pointer;


 
TButton ©   (2003-02-14 05:33) [2]

про хендл я сообразил. не сообразил, как зная хендл отправить ему месаг.


 
dimich1978 ©   (2003-02-14 10:30) [3]

У клиента определяй имя машины(ИМЯ КОМПА), а на серваке пиши типа
for kl:=0 to serversocket1.Socket.ActiveConnections-1 do begin
serverSocket1.Socket.connections[kl].sendtext("go"+ИМЯ КОМПА КУДА ХОЧЕШЬ СЛАТЬ);
end;

Клиент же в свою очередб проверяет
if ("go"=copy(s,0,2)) and (copy(s,3,length(s)=ИМЯ КОМПА) then поехали
Все где то так, у меня все работает


 
dimich1978 ©   (2003-02-14 10:42) [4]

Да только у пакетов надо определять(фрагментирование и склейку).
т.е. при приходе не полного пакета(развит на два пакета) и его дальнейшую склейку.


 
TButton ©   (2003-02-14 15:39) [5]

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

а насчет рассылки всем клиентам, а если их будет ооочень много?


 
mrcat ©   (2003-02-14 16:19) [6]

>> как зная хендл отправить ему месаг.

for conn_index := 0 to pred(ServerSocket.Socket.ActiveConnections) do
if ServerSocket.Socket.connections[conn_index].SocketHandle = My_index then
begin
// Вот и все =)
end;


Но правильней хэндл хранить в стуктуре данных, которая обращается к данному соединению...


 
mrcat ©   (2003-02-14 16:32) [7]

>>if ("go"=copy(s,0,2)) and (copy(s,3,length(s)=ИМЯ КОМПА) then поехали

Куда "поехали"?
Если необходимо передавать данные только одному клиенту зачем сервер должен отправлять данные всем?! И, соответственно, ВСЕ клиенты должны их принимать?! Неправильно это...


 
Digitman ©   (2003-02-14 16:45) [8]

Уже язык стер до костей, но - повторюсь еще раз :

если гнездо работает в неблок.режиме, на передающей что-либо стороне при любом раскладе СТРОГО НЕОБХОДИМО реагировать на событие On[Client]Write !!!!! Буфер передачи - НЕ РЕ-ЗИ-НО-ВЫЙ !!! Событие On[Client]Write() на то и введено в компоненты, чтобы извещать алгоритм передатчика о факте действительного освобождения буфера передачи.

Нереагирование на результаты вызова передатчиком send-методов и игнорирование событий On[Client]Write() ведет к "глюкам" - потере данных в ходе их доставки приемнику.


 
TButton ©   (2003-02-14 20:47) [9]

2Digitman ©
и что ты предлагаешь писать в On[Client]Write()? как-то не хотелось бы глюков...

в ходе работы сервера возникла ерора при обращении к памяти... произошло это из-за отключения юзера. т.е. я просто снял прогу на CtrlAltDel


 
dimich1978 ©   (2003-02-15 08:54) [10]

Вообщем для склейки и фрагментации пакетов делай юнит на основе этого кода, не без помощи Digitmana довели его до ума, а вот всем компам слать мессиаги согласен кривовато это у меня хоть и все работает.
>>mrcat
А поподробнее про My_index-он откуда берется?
unit LongDataTransfer;

interface
uses ScktComp;
Type TMySProc = procedure(const S:AnsiString) of object;
function SendLongText(Socket:TCustomWinSocket; S:ansiString):boolean;
function ReceiveLongText(Socket:TCustomWinSocket;MySProc:TMySProc;SafeCalledStr :string = ""):boolean;


var
InputBuf : ansiString;
InputDataSize : LongWord;
InputReceivedSize : LongWord;

implementation
function SendLongText(Socket:TCustomWinSocket; S:ansiString):boolean;
Var TextSize:integer;
TSSig : string[4];
begin
Result:=True;
Try
If not Socket.Connected then Exit;
TextSize:=Length(S);
asm
mov EAX,TextSize;
mov dword ptr TSSig[1],EAX;
mov byte ptr TSSig[0],4;

end;
S:=String(TSSig+S);
Socket.SendBuf(Pointer(S)^,Length(S));
except Result:=False;
end;
end;

procedure FlushBuffers;
begin
InputBuf:="";
InputDataSize:=0;
InputReceivedSize:=0;
end;

function ReceiveLongText(Socket:TCustomWinSocket;MySProc:TMySProc;SafeCalledStr :ansistring = ""):boolean;
var
S:ansiString;
RDSize:LongWord;
F:String[4];
begin
Result:=True;
try
If SafeCalledStr="" then begin
RDSize:=Socket.ReceiveLength;
S:=Socket.ReceiveText;
end
else begin

S:=SafeCalledStr;
RDSize:=length(S);
end;
If (Length(InputBuf)<4) and (Length(InputBuf)>0) then begin //?????????????, ? ??? ??????
S:=InputBuf+S; //???? ?????????????? ??? ?????????
FlushBuffers; //????? ??????
end;
If InputBuf="" then
begin //????? ?????? ?????;
F:=Copy(S,0,4);
asm
mov EAX,dword ptr F[1];
mov InputDataSize,EAX;
end;

if InputDataSize=RDSize-4 then begin //???? ???? ? ??????

InputBuf:=Copy(S,5,RDSize-4); //?? ??????, ?? ???????????? ???.
MySProc(InputBuf);
FlushBuffers;
Exit;
end;
if InputDataSize<RDSize-4 then begin //????? ???????.
InputBuf:=Copy(S,5,InputDataSize);
MySProc(InputBuf);
Delete(S,1,InputDataSize+4);
FlushBuffers;
ReceiveLongText(Socket,MySProc,S);
Exit;
end;
if InputDataSize>RDSize-4 then begin //??? ?????? ????????
InputBuf:=Copy(S,5,RDSize-4); //???????? ??????
InputReceivedSize:=RDSize-4;
end;
end
else begin //????? ?????? ?? ????
//InputBuf:=
If RDSize+InputReceivedSize=InputDataSize then
begin //???????? ?????????
InputBuf:=InputBuf+Copy(S,0,RDSize); //???????? ???????
MySProc(InputBuf); //? ??????, ??????
FlushBuffers; // ? ?????? ?????? ???
Exit;
end;
If RDSize+InputReceivedSize<InputDataSize then // ????????
begin //?????????
InputBuf:=InputBuf+Copy(S,0,RDSize); //????????
InputReceivedSize:=InputReceivedSize+RDSize;
Exit;
end;
If RDSize+InputReceivedSize>InputDataSize then //???????? ????????
begin // ?? ? ?????? ???? ??? ?????? - ???????.
InputBuf:=InputBuf+Copy(S,0,InputDataSize-InputReceivedSize);
MySProc(InputBuf);
Delete(S,1,InputDataSize-InputReceivedSize);
FlushBuffers;
ReceiveLongText(Socket,MySProc,S);
end;
end;
except Result:=False;
end;
end;

end.

Пример использования
описываем
procedure DataProcessing(const S:ansiString);
.....
Procedure tform1.DataProcessing(const S:String); //Эта процедура будет обрабатывать
begin //полученные данные, и
ShowMessage(S); //автоматически вызывается каждый
end; //при получении нового блока данных.

//Процедура отправки - по нажатию кнопки отправляем через компонент
//ClientSocket три строки.
procedure TForm1.Button1Click(Sender: TObject);
begin
SendLongText(ClientSocket.Socket,"Первая строчка!");
SendLongText(ClientSocket.Socket,"Вторая строчка!");
SendLongText(ClientSocket.Socket,"Третья строчка! Все три показаны по отдельности!!!");
end;

//Процедура ServerSocket OnClientRead содержит одну строчку
//вызова ReceiveLongText, передавая ей в качесте параметра
//имя вашей процедуры обработки.
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
ReceiveLongText(Socket,DataProcessing);
end;




 
mrcat ©   (2003-02-15 10:47) [11]

dimich1978 © (15.02.03 08:54)
>>поподробнее про My_index-он откуда берется?


хэндл сокета необходимо сохранять, например, при возникновении события OnClientConnect в объекте данных, который будет с данным сокетом работать.

Но вообще - это один и вариантов. Как уже говорил TCustomWinSocket содержит поле Data, типа pointer, в котором можно (и нужно!) хранить указатель на объект. Объектов может быть множество, но каждый будет работать только со своим сокетом.



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

Текущий архив: 2003.04.07;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.017 c
1-19639
olimpic
2003-03-25 12:55
2003.04.07
Изменение цвета текста в TRichEdit, TMemo


1-19655
h@1f-e1f
2003-03-25 21:06
2003.04.07
Вычисление даты!


14-19817
reticon
2003-03-19 19:56
2003.04.07
установка приложения


1-19540
msoftware
2003-03-24 17:51
2003.04.07
Вопрос по RXLIB


7-19901
Wizard
2003-02-14 12:28
2003.04.07
Сервер документов