Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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
6-1140071742
Adriano
2006-02-16 09:35
2006.06.25
Получить доступ к сетевой карте


15-1149230575
Prohodil_Mimo
2006-06-02 10:42
2006.06.25
что такое: полевая сторона?


3-1145982888
DDDiM
2006-04-25 20:34
2006.06.25
MYSQL И DELPHI


2-1149659506
Adrea
2006-06-07 09:51
2006.06.25
Графика


15-1149138054
Holy
2006-06-01 09:00
2006.06.25
Всех с праздником...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский