![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ServerSocket , напрягает отправка ответа клиенту по номеру конне
ZV © (2011-01-27 12:59:00)Ситуация такая – клиенты шлют сообщения на сервер для их обработки, обработка в некоторые моменты времени происходит медленнее чем приходят запросы от клиента поэтому приходиться буферизировать запросы для дальнейшей обработки при буферизации запроса от клиента я сохраняю номер коннекта клиента для того что бы потом знать кому отправить ответ.
Все работает нормально до момента когда – клиент прислал запрос, программа его сохранила и сохранила номер коннекта , запрос ждет своей очереди, и в этот момент какой то клиент находящейся по номеру коннекта ниже того клиента который ждет ответа отключается, получается что теперь клиенту который ждет ответ соответствует другой номер коннекта и когда запрос будет обработан то ответ будет отправлен по номеру коннекта сохранённому перед обработкой , получается что ответ получает не тот клиент .
Можно конечно сохранять перед обработкой не номер коннекта клиента, а его IP , но тогда при отправке ответа клиенту придется перебрать все активные коннекты на соответствие нужному IP
адресу , хорошо если их с десяток , а если будет 200, хотя если это займет не больше 2мс то пойдет.
Как быть? Кто что посоветует?
Плохиш (2011-01-28 16:00:00) [1]
> Sha © (28.01.11 11:00) [32]
>
> О чем вообще речь?
> В прямой программе не бывает кривых данных.
>
Судя по ветке прямая программа отсутствует :-(
Sha (2011-01-28 11:00:00) [2]О чем вообще речь?
В прямой программе не бывает кривых данных.
Сергей М. (2011-01-28 10:40:00) [3]
> KSergey © (28.01.11 10:10) [30]
А он и обращался по уставу)
А устав гласит "В одной сессии допускается один кривой запрос, при получении повторного кривого запроса клиент получает пинок под зад"
KSergey (2011-01-28 10:10:00) [4]> Сергей М. © (28.01.11 10:02) [29]
> И чем же, спрашивается, клиент провинился ?)
А надо было по уставу обращаться!
Сергей М. (2011-01-28 10:02:00) [5]
> буфер по любому чистить приходиться
Нельзя так делать. Сетевому приложению не должно быть вообще никакого дела до того что там в буфере находится, его дело - выгребать из головы очереди ровно столько, сколько оно ожидает в соответствии с прикладным протоколом.
> очистить буфер не читая его полностью
Пусть в буфере на некий момент находится "полторы" прикладных дейтаграмм - "кривая" в голове очереди и пол-"прямой" следом за ней.
Ты выгреб первую, определил что она "кривая", очистил буфер и ждешь очередной дейтаграммы. В это время в буфер поступает оставшаяся половина "прямой" дейтаграммы, ты ее выгребаешь, она естественно интерпретируется как "кривая" (поскольку первую половину ты своими руками покоцал при предыдущей чистке буфера) и посылаешь клиента в эротическое путешествие, отключая его.
И чем же, спрашивается, клиент провинился ?)
Slym (2011-01-28 06:02:00) [6]ZV © (27.01.11 17:50) [16]
Ещё вопрос. Бывает ситуация когда приемный буфер сокета содержит не верную информацию и его нужно очистить , как это сделать?
тушить свет, рубить канаты! Exit; <-тут
поточный режим, создает отдельный поток для каждого соединения.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms,ScktComp, StdCtrls;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
Button1: TButton;
procedure ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
procedure Button1Click(Sender: TObject);
end;
var Form1: TForm1;
implementation
{$R *.dfm}
type
TClientThread=class(TServerClientThread)
protected
procedure ClientExecute; override;
end;
type
TPacketType=(IDasas,IDwewe,Undef);
TSign=packed array[0..1] of byte;
const
PacketSign:array[TPacketType] of TSign=((03,04),(54,140),(0,0));
PacketLen:array[TPacketType] of integer=(100,100,0);
function GetPacketType(const Sign:TSign):TPacketType;
begin
for result:=low(TPacketType) to high(TPacketType) do
if word(PacketSign[result])=word(Sign) then
exit;
end;
{ TClientThread }
function ReceiveBufFully(Peer:TCustomWinSocket;var Buf; Count: Integer):boolean;
var pBuf:PByte;
s:integer;
begin
result:=false;
pBuf:=@Buf;
while count>0 do
begin
s:=Peer.ReceiveBuf(pBuf^,Count);
if s=0 then exit;
inc(pBuf,s);
dec(Count,s);
end;
result:=true;
end;
function SendBufFully(Peer:TCustomWinSocket;var Buf; Count: Integer):boolean;
var pBuf:PByte;
s:integer;
begin
result:=false;
pBuf:=@Buf;
while count>0 do
begin
s:=Peer.SendBuf(pBuf^,Count);
if s=0 then exit;
inc(pBuf,s);
dec(Count,s);
end;
result:=true;
end;
procedure TClientThread.ClientExecute;
var
Sign:TSign;
PcktType:TPacketType;
PcktLen:integer;
Pckt:string;
begin
while not Terminated and ClientSocket.Connected do
begin
if not ReceiveBufFully(ClientSocket,Sign,2) then exit;
PcktType:=GetPacketType(Sign);
PcktLen:=PacketLen[PcktType];
SetLength(Pckt,PcktLen);
if not ReceiveBufFully(ClientSocket,PChar(Pckt)^,PcktLen) then exit;
end;
end;
procedure TForm1.ServerSocket1GetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread:=TClientThread.Create(false,ClientSocket);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ServerSocket1.ServerType:=stThreadBlocking;
ServerSocket1.OnGetThread:=ServerSocket1GetThread;
ServerSocket1.Active:=true;
end;
end.
Anatoly Podgoretsky (2011-01-27 23:34:00) [7]> Сергей М. (27.01.2011 22:22:22) [22]
А третья половина вообще не хочет иметь с ним дело
ZV (2011-01-27 23:07:00) [8]
> Очевидно, пробел лишний.
Данные приходят криптованые . И если ключ криптования не тот то клиента после нескольких попыток обмануть сервер отключает
ZV (2011-01-27 23:01:00) [9]
> А если партнер отправил заведомо неверную-непонятную, то
> нафих нужно с ним вошкаться - чистить буфер приема и продолжать
> ждать пока он такую же очередную хрень пришлет ?
> Отключить его к лешему - и всех делов ! Как это делает добрая
> половина приличных прикладных серверов)
Да так все и происходит.
Если клиент начинает мутить то сервер его отключит после нескольких не правильных запросов.Но несколько раз буфер по любому чистить приходиться
поэтому и спросил может есть какая то функция чтобы очистить буфер не читая его полностью.
KSergey (2011-01-27 22:44:00) [10]> Сергей М. © (27.01.11 22:22) [22]
> Что значит "не верную" ?
Очевидно, пробел лишний.
KSergey (2011-01-27 22:43:00) [11]> ZV © (27.01.11 20:33) [21]
> Устроит , а что это такое?
"Я, я свидетель! А что случилось?"
Сергей М. (2011-01-27 22:22:00) [12]
> Бывает ситуация когда приемный буфер сокета содержит не
> верную информацию
Что значит "не верную" ?
С какой луны она туда свалилась, если партнер отправил заведомо "верную" ?
А если партнер отправил заведомо неверную-непонятную, то нафих нужно с ним вошкаться - чистить буфер приема и продолжать ждать пока он такую же очередную хрень пришлет ?
Отключить его к лешему - и всех делов ! Как это делает добрая половина приличных прикладных серверов)
Ну можно еще перед этим послать предупреждающее сообщение и следом отключиться, как это делает другая половина приличных серверов)
ZV (2011-01-27 20:33:00) [13]
> поточная модель не устроит? там никаких i, сам себе сессия,
> знаешь только себя и клиента...
Устроит , а что это такое?
Slym (2011-01-27 20:07:00) [14]поточная модель не устроит? там никаких i, сам себе сессия, знаешь только себя и клиента...
KSergey (2011-01-27 18:09:00) [15]> ZV © (27.01.11 17:53) [17]
> Да я их не двигаю.После события Disconnect или Connect
> список обновляется автоматически компонентом TServerSocket
Это речь про TServerSocket.Socket.Connections[] чтоли??
Ту так элементы здесь типа TCustomWinSocket, а там есть поле Data
В нем и храни уникальное число для каждого соединения или указатель на связанную с соединением структуру, в которой уже хранить всю необходимую уникальную информацию.
Sha (2011-01-27 18:03:00) [16]> ZV © (27.01.11 17:53) [17]
[4], [8], [10]
ZV (2011-01-27 17:53:00) [17]
> В качестве быстрого устранения серьёзных финансовых потерь
> предлагаю не двигать записи в списке соединений.
Да я их не двигаю.После события Disconnect или Connect список обновляется автоматически компонентом TServerSocket
ZV (2011-01-27 17:50:00) [18]Ещё вопрос. Бывает ситуация когда приемный буфер сокета содержит не верную информацию и его нужно очистить , как это сделать?
Есть что то типаServerSocket1.Socket.Connections[0].ReceiveBuf.Clear;
На данный момент буфер очищаю считывая всю информацию из него
DiamondShark (2011-01-27 17:44:00) [19]
> Телепаю, что это у него номер позиции в списке соединений
Подтверждаю приём телепатограммы.
В качестве быстрого устранения серьёзных финансовых потерь предлагаю не двигать записи в списке соединений.
ZV (2011-01-27 17:43:00) [20]
> что это у него номер позиции в списке соединений
Угу, так и есть