Форум: "Сети";
Текущий архив: 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