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

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

ServerSocket , напрягает отправка ответа клиенту по номеру конне


Страницы:   1 2

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]


> что это у него номер позиции в списке соединений

Угу, так и есть


Страницы:   1 2

Наверх

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