Форум: "Прочее";
Текущий архив: 2006.06.25;
Скачать: [xml.tar.bz2];
ВнизНесколько TClientSocket Найти похожие ветки
← →
Новичоккк (2006-05-31 10:27) [0]Столкнулся с тем, что путаются ответы
Вот такой массив:aSock:array of record
s:TClientSocket;
r:TSRes;
m:string;
end;
Так инициализирую:
const THREADS=5
...
SetLength(aSock,THREADS);
for i:=0 to Length(aSock)-1 do
begin
aSock[i].s:=TClientSocket.Create(nil);
with aSock[i].s do
begin
address:="xxx.xxx.xxx.xxx";
port:=xxxx;
clienttype:=ctNonBlocking;
tag:=i;
onRead:=aSockRead;
onDisconnect:=aSockDisconnect;
end;
aSock[i].r:=lWRONG;
end;
while not DONE do
begin
for i:=0 to Length(aSock)-1 do
begin
if DONE or (aSock[i].r=lBF) then
begin
AddInfo("----- Stop Threads -----",clBlue,"["+IntToStr(i)+"] ",clPurple);
break;
end;
if aSock[i].r=lWRONG then
begin
aSock[i].m:=GenNewMessage;
aSock[i].r:=lWAIT;
aSock[i].s.Active:=true;
end;
Application.ProcessMessages;
end;
end;
Обработчик события:procedure TfrmMain.aSockRead(Sender: TObject; Socket: TCustomWinSocket);
var
str:string;
tag:integer;
begin
str:=Socket.ReceiveText;
tag:=(Sender as TClientSocket).Tag;
AddInfo(IntToStr(Length(str))+" bytes from server",clBlack,"["+IntToStr(tag)+"] ",clPurple);
if Length(str)=11 then
begin
AddInfo("-> 50 bytes",clBlack,"["+IntToStr(tag)+"] ",clPurple);
socket.SendText(aSock[tag].m);
exit;
end;
if Length(str)=18 then
begin
AddInfo("WRONG: "+aSock[tag].p,clRed,"["+IntToStr(tag)+"] ",clPurple);
aSock[tag].r:=lWRONG;
end;
if Length(str)=50 then
begin
done:=true;
AddInfo("OK: "+aSock[tag].p,clGreen,"["+IntToStr(tag)+"] ",clPurple);
aSock[tag].r:=lOK;
end;
aSock[tag].s.Active:=false;
aSock[tag].s.Close;
end;
Протокол общения:
Соединяемся с сервером, ждём приветствия 11 байт, посылаем серверу сообщение. Сервер отвечает либо 18 байт, либо 50 байт. Завершение сессии.
В итоге у меня сокеты получают свои персональные сообщения и общаются с сервером. В итоге каждому сообщению присваивается флаг 0 или 1 (по полученному ответу от сервера 18 или 50 байт).
Так вот в чем проблема - ответы путаются. Уже вторые сутки пытаюсь разобраться почему возникают коллизии?
Я конечно понимаю, что информации много. Но очень надеюсь, что кто-нибудь из мастеров уделит мне несколько минут и поможет решить проблему.
← →
Сергей М. © (2006-05-31 10:33) [1]
> if Length(str)=11 then
> if Length(str)=18 then
> if Length(str)=50 then
Ни одно из этих условий не обязано выполняться.
← →
Новичоккк (2006-05-31 10:39) [2]
> Ни одно из этих условий не обязано выполняться.
В моём случае выполняется всегда. А даже если и произойдет уникальное событие - сокет просто закрывается.
← →
Сергей М. © (2006-05-31 10:57) [3]
> В моём случае выполняется всегда
Как только разнесешь свои клиент и сервер на разные хосты разных подсетей в глоб.сети, эта "железная логика" тут же потерпит крах.
← →
Новичоккк (2006-05-31 11:12) [4]Буду знать... Но сейчас это вопрос второстепенный... Почему сокеты получают чужие ответы?
← →
Сергей М. © (2006-05-31 11:27) [5]
> Почему сокеты получают чужие ответы?
Сокет не может получать "чужие ответы" - он получает ответ именно от того сервера, с которым был установлен коннект.
← →
Новичоккк (2006-05-31 12:05) [6]Сервер один и тот же. Несколько сокетов соединяются с одним сервером. Обработчик onRead общий (код в первом посте).
Что в итоге получается (упрощенный вариант)
1. Сокету S0 назначается сообщение "0". Активация сокета.
2. Сокету S1 назначается сообщение "1". Активация сокета.
3. Сокету S2 назначается сообщение "2". Активация сокета.
Я знаю, что на сообщение "1" сервер должен дать ответ OK, на сообщения "0" и "2" ответ ERROR.
Т.е. S0 и S2 должны принять ERROR, S1 - OK.
А в итоге, этот ответ OK попадает случайным образом или к S0, или к S1, или к S2. Почему там происходит - я не могу разобраться уже второй день.
Код выше. Надеюсь на вашу помощь.
← →
Новичоккк (2006-05-31 12:14) [7]Плюс ответ ОК может придти двум или даже всем сокетам S0-S2, а может вообще ни кому не поступить (S0-S2 получат ответ ERROR).
← →
Сергей М. © (2006-05-31 12:23) [8]Неплохо было бы на код сервера взглянуть ..
← →
Новичоккк (2006-05-31 12:28) [9]Сервер 100% работает правильно
Если сделать один поток в клиенте (THREADS=1 в примере), то все ответы приходят правильно (все OK на нужные сообщения и все ERROR на остальные)
← →
Сергей М. © (2006-05-31 12:33) [10]
> Если сделать один поток в клиенте (THREADS=1 в примере),
В примере я не вижу никаких потоков...
← →
Новичоккк (2006-05-31 12:37) [11]Ну не потоки... сокеты
aSock - массив сокетов (плюс текущий статус и сообщение в каждом элементе массива)
Все они ctNonBlocking
← →
Сергей М. © (2006-05-31 12:56) [12]Мне не понятен смысл, заложенный в протоколе.
> Сокету S0 назначается сообщение "0"
Сообщение клиента серверу, содержащее строку из одного символа, это реальное сообщение в соответствии с протоколом или просто некий пример ?
← →
Новичоккк (2006-05-31 13:08) [13]Упрощенный пример. Реальный протокол:
1. Соединение
2. Сервер посылает приветствие 11 байт
3. Клиент посылает серверу пакет, содержащий несколько полей (пакет 50 байт). Поля - операнды...
4. Сервер выполняет над полями некоторые операции и высылает ответ. Два типа ответа - 18 байт и 50 байт. В данном случае содержимое ответов не важно - главное длина ответа. В соответствии с чем устанавливается флаг (0 или 1, OK или ERROR).
5. Разъединение
Чтобы ускорить проверку, я создаю массив сокетов. В итоге ответ из пунтка 4 путается (его может получить случайный сокет). Как факт - на свой запрос, сокет получает ответ, предназначенный для другого сокета из массива.
Если массив будет состоять всего лишь из одного сокета (THREADS=1), то на все запросы приходят правильные ответы.
← →
Сергей М. © (2006-05-31 13:12) [14]
> Клиент посылает серверу пакет, содержащий несколько полей
> (пакет 50 байт)
Покажи как сервер принимает эти 50 байт ..
← →
Новичоккк (2006-05-31 13:21) [15]Сервер написан давно еще и его исходников нет. Сейчас пишу обновленный клиент...
← →
Сергей М. © (2006-05-31 13:35) [16]
> Два типа ответа - 18 байт и 50 байт. .. В соответствии
> с чем устанавливается флаг (0 или 1, OK или ERROR).
Твой код противоречит этому !
Если 18 байт - это ОК, а 50 байт - это ERROR, то почему
> if Length(str)=50 then
> begin
> done:=true; //а это вообще непонятно - флаг DONE=True прервет цикл while not DONE do..
> AddInfo("OK: "+aSock[tag].p,clGreen,"["+IntToStr(tag)+"] ",clPurple);
> aSock[tag].r:=lOK;
> end;
?!
← →
Новичоккк (2006-05-31 13:39) [17]Я не это имел ввиду =) "В соответствии" имеет немного другой смысл =)
← →
Сергей М. © (2006-05-31 13:59) [18]
> "В соответствии" имеет немного другой смысл
Я не телепат и разгадывать твои тайные смыслы у меня нет желания.
Так что изволь сопоставить свой "другой смысл" с примером кода..
← →
Новичоккк (2006-05-31 17:29) [19]Код в первом примере. В посте [13] в "Два типа ответа - 18 байт и 50 байт. В данном случае содержимое ответов не важно - главное длина ответа. В соответствии с чем устанавливается флаг (0 или 1, OK или ERROR)."
Имелось ввиду не то, что "18 байт"="0" или "ОК" и "50 байт"="1" или "ERROR", а что всего два варианта интерпретации. Порядок соблюден не был.
В соответствии с чем ваш пост [16] не имеет смысла.
Вообще я изначально спросил - в каком месте идёт не правильная работа с сокета, в следствии чего несколько сокетов получают один и тот же ответ (или получают чужие ответы), при этом какие-то ответы могут быть утеряны - т.е. возникают коллизии. Я понятия не имею почему там происходит. Поэтому я и создал ветку - спросить у вас. В данном случае какой ответ воспринимается как OK или ERROR, 18 байт или 50 - значения не имеет.
← →
Сергей М. © (2006-05-31 17:37) [20]Если утверждение [2] верно (что весьма сомнительно), то ошибка не в приведенном коде
← →
Новичоккк (2006-05-31 17:52) [21]
> Если утверждение [2] верно (что весьма сомнительно)
Добавил условие:
if not ((Length(str)=11) or (Length(str)=18) or (Length(str)=50)) then ShowMessage("");
Сообщение не было выведено ни разу
> то ошибка не в приведенном коде
В принципе это почти весь код. Что же, попробую написать упрощенную версию сервера и клиента (работающего по такому же принципу с массивом сокетов), будут ли ошибки, или их не будет...
← →
Сергей М. © (2006-06-01 08:29) [22]
> Сообщение не было выведено ни разу
Разнеси клиент и сервер по разным хостам (даже в пределах ЛВС) и рано или поздно получишь это сообщение.
> с массивом сокетов
Зачем тебе тот массив дался - ума не приложу.
Ты сам себе усложнил задачу с этим массивом.
На то есть TComponent.Owner
← →
Новичоккк (2006-06-01 12:46) [23]
> Зачем тебе тот массив дался - ума не приложу.Ты сам себе
> усложнил задачу с этим массивом.На то есть TComponent.Owner
Можно подробнее?
2All
Может кто-нибудь знает в чем проблема (код в первом посте)
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2006.06.25;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.009 c