Форум: "Начинающим";
Текущий архив: 2011.05.01;
Скачать: [xml.tar.bz2];
ВнизServerSocket , напрягает отправка ответа клиенту по номеру конне Найти похожие ветки
← →
ZV © (2011-01-27 12:59) [0]Ситуация такая – клиенты шлют сообщения на сервер для их обработки, обработка в некоторые моменты времени происходит медленнее чем приходят запросы от клиента поэтому приходиться буферизировать запросы для дальнейшей обработки при буферизации запроса от клиента я сохраняю номер коннекта клиента для того что бы потом знать кому отправить ответ.
Все работает нормально до момента когда – клиент прислал запрос, программа его сохранила и сохранила номер коннекта , запрос ждет своей очереди, и в этот момент какой то клиент находящейся по номеру коннекта ниже того клиента который ждет ответа отключается, получается что теперь клиенту который ждет ответ соответствует другой номер коннекта и когда запрос будет обработан то ответ будет отправлен по номеру коннекта сохранённому перед обработкой , получается что ответ получает не тот клиент .
Можно конечно сохранять перед обработкой не номер коннекта клиента, а его IP , но тогда при отправке ответа клиенту придется перебрать все активные коннекты на соответствие нужному IP
адресу , хорошо если их с десяток , а если будет 200, хотя если это займет не больше 2мс то пойдет.
Как быть? Кто что посоветует?
← →
brother © (2011-01-27 13:11) [1]у меня дежаву?
← →
ZV © (2011-01-27 13:15) [2]
> у меня дежаву?
Нет :)
← →
brother © (2011-01-27 13:16) [3]тогда я спокоен...
← →
Anatoly Podgoretsky © (2011-01-27 13:47) [4]> ZV (27.01.2011 12:59:00) [0]
Надо ввести понятие Сессия
← →
ZV © (2011-01-27 13:52) [5]
> Надо ввести понятие Сессия
А это как? Где на это понятие можно посмотреть ?
← →
Плохиш © (2011-01-27 14:03) [6]Может всё-таки почитать теорию и технологии распределённых систем. В делфи даже есть мастера для создания нескольких вариантов таких сиатем.
← →
ZV © (2011-01-27 14:13) [7]
> Может всё-таки почитать теорию
А что без технологии распределенных систем мою проблему не решить?
Сервер остановлен на пару дней для устранения проблемы которую я привел выше. По этому времени на изучение теории нет, надо быстро искать решение на практике. Каждый день простоя сервера сервера, приносит серьезные финансовые потери и не довольство клиентов.
← →
DiamondShark © (2011-01-27 14:36) [8]А нафига вам какой-то номер клиента?
Хэндл сокета или ссылка на экземпляр класса-обёртки для сокета вполне однозначно идентифицируют клиента.
Какая вам разница, что переберать, номера, хэндлы, адреса?
В 2 мс уложится линейный перебор статыщьмильёнов простых значений.
Но в случае ссылки на объект или хэндла никакого перебора не надо вообще.
← →
ZV © (2011-01-27 14:56) [9]
> Хэндл сокета или ссылка на экземпляр класса-обёртки для
> сокета вполне однозначно идентифицируют клиента.
Без примера я не пойму о чем идет речь.
Радует то что решение есть но жаль что я не могу понять об чем вы
> Какая вам разница, что переберать, номера, хэндлы, адреса?
Так дело в том что я ни чего не перебираю , зная номер коннекта клиента я просто подставляю его и ответ отправлен кому надо (но увы не всегда из за выше описанной проблемы)
Сервер работает таким образом по событию таймера программа проходит по всем коннектам и проверяет размер входных данных каждого клиента, если он соответствует нужному размеру то отправить пакет данных на обработку прикрепив к нему номер коннекта клиента приславшего данный запрос. Процедура обработки после того как обработает пакет данных отсылает ответ по номеру коннекта который был перекреплен к пакету данных.
← →
Sha © (2011-01-27 16:38) [10]ZV © (27.01.11 13:52) [5]
>> Надо ввести понятие Сессия
> А это как? Где на это понятие можно посмотреть ?
Это запись или объект, хранящие необходимую тебе информацию о соединении.
Сохраняй адрес записи или ссылку на объект.
← →
Плохиш © (2011-01-27 16:45) [11]
> Сервер остановлен на пару дней для устранения проблемы которую
> я привел выше. По этому времени на изучение теории нет,
> надо быстро искать решение на практике. Каждый день простоя
> сервера сервера, приносит серьезные финансовые потери и
> не довольство клиентов.
Ну продолжайте ездить на своём велосипеде.
← →
KSergey © (2011-01-27 16:48) [12]> ZV © (27.01.11 14:56) [9]
> зная номер коннекта клиента
Не понятно что есть "номер коннекта клиента".
и почему он изменяется, если один из клиентов отваливается??
как устроен это самый учет коннектов сейчас?
в примерах, пожалуйста.
← →
Sha © (2011-01-27 16:51) [13]Телепаю, что это у него номер позиции в списке соединений
← →
ZV © (2011-01-27 17:43) [14]
> что это у него номер позиции в списке соединений
Угу, так и есть
← →
DiamondShark © (2011-01-27 17:44) [15]
> Телепаю, что это у него номер позиции в списке соединений
Подтверждаю приём телепатограммы.
В качестве быстрого устранения серьёзных финансовых потерь предлагаю не двигать записи в списке соединений.
← →
ZV © (2011-01-27 17:50) [16]Ещё вопрос. Бывает ситуация когда приемный буфер сокета содержит не верную информацию и его нужно очистить , как это сделать?
Есть что то типаServerSocket1.Socket.Connections[0].ReceiveBuf.Clear;
На данный момент буфер очищаю считывая всю информацию из него
← →
ZV © (2011-01-27 17:53) [17]
> В качестве быстрого устранения серьёзных финансовых потерь
> предлагаю не двигать записи в списке соединений.
Да я их не двигаю.После события Disconnect или Connect список обновляется автоматически компонентом TServerSocket
← →
Sha © (2011-01-27 18:03) [18]> ZV © (27.01.11 17:53) [17]
[4], [8], [10]
← →
KSergey © (2011-01-27 18:09) [19]> ZV © (27.01.11 17:53) [17]
> Да я их не двигаю.После события Disconnect или Connect
> список обновляется автоматически компонентом TServerSocket
Это речь про TServerSocket.Socket.Connections[] чтоли??
Ту так элементы здесь типа TCustomWinSocket, а там есть поле Data
В нем и храни уникальное число для каждого соединения или указатель на связанную с соединением структуру, в которой уже хранить всю необходимую уникальную информацию.
← →
Slym © (2011-01-27 20:07) [20]поточная модель не устроит? там никаких i, сам себе сессия, знаешь только себя и клиента...
← →
ZV © (2011-01-27 20:33) [21]
> поточная модель не устроит? там никаких i, сам себе сессия,
> знаешь только себя и клиента...
Устроит , а что это такое?
← →
Сергей М. © (2011-01-27 22:22) [22]
> Бывает ситуация когда приемный буфер сокета содержит не
> верную информацию
Что значит "не верную" ?
С какой луны она туда свалилась, если партнер отправил заведомо "верную" ?
А если партнер отправил заведомо неверную-непонятную, то нафих нужно с ним вошкаться - чистить буфер приема и продолжать ждать пока он такую же очередную хрень пришлет ?
Отключить его к лешему - и всех делов ! Как это делает добрая половина приличных прикладных серверов)
Ну можно еще перед этим послать предупреждающее сообщение и следом отключиться, как это делает другая половина приличных серверов)
← →
KSergey © (2011-01-27 22:43) [23]> ZV © (27.01.11 20:33) [21]
> Устроит , а что это такое?
"Я, я свидетель! А что случилось?"
← →
KSergey © (2011-01-27 22:44) [24]> Сергей М. © (27.01.11 22:22) [22]
> Что значит "не верную" ?
Очевидно, пробел лишний.
← →
ZV © (2011-01-27 23:01) [25]
> А если партнер отправил заведомо неверную-непонятную, то
> нафих нужно с ним вошкаться - чистить буфер приема и продолжать
> ждать пока он такую же очередную хрень пришлет ?
> Отключить его к лешему - и всех делов ! Как это делает добрая
> половина приличных прикладных серверов)
Да так все и происходит.
Если клиент начинает мутить то сервер его отключит после нескольких не правильных запросов.Но несколько раз буфер по любому чистить приходиться
поэтому и спросил может есть какая то функция чтобы очистить буфер не читая его полностью.
← →
ZV © (2011-01-27 23:07) [26]
> Очевидно, пробел лишний.
Данные приходят криптованые . И если ключ криптования не тот то клиента после нескольких попыток обмануть сервер отключает
← →
Anatoly Podgoretsky © (2011-01-27 23:34) [27]> Сергей М. (27.01.2011 22:22:22) [22]
А третья половина вообще не хочет иметь с ним дело
← →
Slym © (2011-01-28 06:02) [28]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.
← →
Сергей М. © (2011-01-28 10:02) [29]
> буфер по любому чистить приходиться
Нельзя так делать. Сетевому приложению не должно быть вообще никакого дела до того что там в буфере находится, его дело - выгребать из головы очереди ровно столько, сколько оно ожидает в соответствии с прикладным протоколом.
> очистить буфер не читая его полностью
Пусть в буфере на некий момент находится "полторы" прикладных дейтаграмм - "кривая" в голове очереди и пол-"прямой" следом за ней.
Ты выгреб первую, определил что она "кривая", очистил буфер и ждешь очередной дейтаграммы. В это время в буфер поступает оставшаяся половина "прямой" дейтаграммы, ты ее выгребаешь, она естественно интерпретируется как "кривая" (поскольку первую половину ты своими руками покоцал при предыдущей чистке буфера) и посылаешь клиента в эротическое путешествие, отключая его.
И чем же, спрашивается, клиент провинился ?)
← →
KSergey © (2011-01-28 10:10) [30]> Сергей М. © (28.01.11 10:02) [29]
> И чем же, спрашивается, клиент провинился ?)
А надо было по уставу обращаться!
← →
Сергей М. © (2011-01-28 10:40) [31]
> KSergey © (28.01.11 10:10) [30]
А он и обращался по уставу)
А устав гласит "В одной сессии допускается один кривой запрос, при получении повторного кривого запроса клиент получает пинок под зад"
← →
Sha © (2011-01-28 11:00) [32]О чем вообще речь?
В прямой программе не бывает кривых данных.
← →
Плохиш © (2011-01-28 16:00) [33]
> Sha © (28.01.11 11:00) [32]
>
> О чем вообще речь?
> В прямой программе не бывает кривых данных.
>
Судя по ветке прямая программа отсутствует :-(
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.05.01;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.004 c