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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.008 c
7-19880
alexsandri
2002-12-20 17:31
2003.04.07
Возможно полные бредни ,но все же


1-19546
spogi
2003-03-26 22:58
2003.04.07
vopros po TPanel on RUN-TIME


4-19922
Ricks
2003-02-09 14:11
2003.04.07
USER Objects


14-19850
partizan
2003-03-21 11:38
2003.04.07
No war in Iraq


6-19726
TButton
2003-02-13 18:07
2003.04.07
СерверСокет





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский