Модераторы: Snowy, Poseidon, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточный сервак 
:(
    Опции темы
Antony41
Дата 13.2.2013, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



впринципе переписал немного, получается что сервер работает в режиме blocking а клиент nonblocking, короче 

проблемка такова:
есть структура Record, и объект этой структуры GlobalData
указатель на эту структуру fData: PData

Код

fData := @GlobalData;

теперь заполняю структуру
Код

fData^.Command := 10; 

и отправлять её приходится непонятным пока образом.
Вот так всё нормально принимается клинтом:
Код

  fRSData.Write(fData^, SizeOf(fData)); //непонятно мне почему тут не так SizeOf(fData^) ???

если вместо этого написать 
Код

  fRSData.Write(fData^, SizeOf(fData^));

то отчет клиента такой:
Код

Соединение установлено
Пришло сообщение о проверке соединения //вот это Command := 10; которую я и посылал
Ответное сообщение отправлено
Command: 0 Команда не распознана //а вот это непонятная хрень что за пустые пакеты?
Command: 0 Команда не распознана 
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана
Command: 0 Команда не распознана


мне вот непонятно может быть эта строка всё таки верна?
Код

 fRSData.Write(fData^, SizeOf(fData));


Это сообщение отредактировал(а) Antony41 - 13.2.2013, 17:29
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



fData указатель. SizeOf = 4(8)

Добавлено @ 17:40
Пкажи fRSDataTWinSocketStream.Write

Добавлено через 11 минут и 29 секунд
Код

  TWinSocketStream = class(TStream)
  private
    ...
  public
    ...
    function Write(const Buffer; Count: Longint): Longint; override;
    ...
  end;


Это сообщение отредактировал(а) Чучмек - 13.2.2013, 17:41


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Цитата(Antony41 @  13.2.2013,  17:28 Найти цитируемый пост)
 fRSData.Write(fData^, SizeOf(fData))

Передаешь только первые 4 байта.
Твоя структура принимается частями. 
Каждую часть, при приеме, ты считаеш новой структурой.  


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 13.2.2013, 18:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



угу вот я тоже уже понял что это размер в памяти не структуры а указателя. Вот нифига не пойму

Структуры у меня одинаковы что в клиенте что на сервере
размер фиксированный у обоих как их не заполняй. вот она структура собственно
Код

const
  MAX_STRING = 30;
  MAX_CHAR = 10000;


type
  PData = ^TData;
  TData = packed record
    fCommand: Word;
    fNick: String[MAX_STRING];
    fMessages: array [0..MAX_CHAR - 1] of Char;
  end;


Смотрите пакет мне приходит рубленый значит потоки байт данных передаются последовательно один за другим это так?
а значит допустим событие OnRead в клиенте  может выполнится несколько раз...
А это значит мне нужно создать например MemoryStream, как глобальную переменную а при выполнении onRead писать всё в MemoryStream последовательно. Я в правильном направлении?

Как тогда мне определить начало и конец нового пакета? для того чтобы обработать принятый пакет очистить MemoryStream и начать принимать следующий пакет поток данных нового пакета?

Добавлено @ 18:10
Цитата(Чучмек @  13.2.2013,  18:05 Найти цитируемый пост)
Каждую часть, при приеме, ты считаеш новой структурой.   

С этим я согласен тупанул малёха, теперь делаю так 
Код

fRSData.Write(fData^, SizeOf(fData^));

но тут возникает вопрос чем отличается от того что выше вот это
fRSData.WriteBuffer(fData^, SizeOf(fData^));

Добавлено @ 18:15
Цитата(Чучмек @  13.2.2013,  17:33 Найти цитируемый пост)
Пкажи fRSDataTWinSocketStream.Write

А что показывать стандартный класс, стандартная функция))) (Delphi XE)

Это сообщение отредактировал(а) Antony41 - 13.2.2013, 18:18
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Цитата(Antony41 @  13.2.2013,  18:08 Найти цитируемый пост)
А что показывать стандартный класс, стандартная функция

Да. Я уже нашел.
Какой протокол?  TCP?


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 13.2.2013, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



может вобще стоит перевести ClientSocket в режим блокинга

Добавлено через 6 минут и 52 секунды
Цитата(Чучмек @  13.2.2013,  18:19 Найти цитируемый пост)
Какой протокол?  TCP?

ну наверно))) ведь TServerSocket/TClientSocket использует его вроде как

Добавлено через 11 минут и 54 секунды
И еще вот такой вопрос например если у меня клиент будет работать в режиме nonblocking я так понимаю это в основном потоке будут приниматься данные... Предположим что пакет принимался принимался а пользователь затем открыл какое нибудь окно ShowModal,
прием данных приостановится? если я размещу на форме компонент TidAntifreeze который собственно не относится к TClientSocket, будет ли пролжаться приём данных в таком случае?
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Цитата(Antony41 @  13.2.2013,  18:08 Найти цитируемый пост)
Как тогда мне определить начало и конец нового пакета

По размеру передаваемой структуры.

Делаешь глобальными (или  свойство) буфер (размер твоей структуры) Buff
и размер данных записанных в буфер. L

В onRead,
 0. offset:=0;
 1. записываешь в буфер, с позиции L,принятые данные   c позиции offset размером count:=min(BuffSize-L,ReadLength-offset) ;
 2. L=L+count;
 3. If L=BuffSize -> Передаешь записанный буфер на обработку ; L:=0; offset:=offset+count; if offset< ReadLength then goto 1


Это сообщение отредактировал(а) Чучмек - 13.2.2013, 18:39


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 13.2.2013, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



Жесть что попроще ни как ? может всё таки перевести клиента в режим блокинга и работать уже в потоках?
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



А какая разница?
Неблокирующий: пришел пакет -> событие
Блокирующий режим: пришел пакет ->поток вышел из Write.
Хоть так хоть эдак,  сколько пакетов, столько фрагментов.

Добавлено через 3 минуты и 58 секунд
Цитата(Antony41 @  13.2.2013,  18:20 Найти цитируемый пост)
а пользователь затем открыл какое нибудь окно ShowModal,
прием данных приостановится

Есть системный буфер. После выхода из Modal прочитаешь несколько пакетов сразу.

Это сообщение отредактировал(а) Чучмек - 13.2.2013, 18:51


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 13.2.2013, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



Интерфейс не будет подвисать?

Добавлено через 1 минуту и 47 секунд
Цитата(Чучмек @  13.2.2013,  18:50 Найти цитируемый пост)
Есть системный буфер. После выхода из Modal прочитаешь несколько пакетов сразу

Тоесть они уже будут приняты останется только состыковать?

Это сообщение отредактировал(а) Antony41 - 13.2.2013, 18:56
PM MAIL   Вверх
Чучмек
Дата 13.2.2013, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Цитата(Antony41 @  13.2.2013,  18:55 Найти цитируемый пост)
Тоесть они уже будут приняты останется только состыковать?

да


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 13.2.2013, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



ну вот смотрите вот как я сейчас всё переписал приблизительно... 
Подопните плиз в нужную сторону если что то не так.
Processing(@GlobalData); //там я уже работаю с пакетом

SIZE_OF_STRUCT это постоянный размер моей структуры
ReadedLen это кол-во прочитанных байт (глобальная Integer)
MS это TMemoryStream


Код

procedure TClient_Form.CSRead(Sender: TObject; Socket: TCustomWinSocket);
var I, RecCount, OutLen:Integer;
    ReadBuf: array [0..10000] of Byte;
begin
  RecCount := Socket.ReceiveLength;
  if RecCount = 0 then
    Exit;
  try
    I:=0;
    OutLen := SIZE_OF_STRUCT - ReadedLen;
    ZeroMemory(@ReadBuf, SizeOf(ReadBuf)); //чистим буфер
    RecCount := Socket.ReceiveLength;

    repeat
      OutLen := SIZE_OF_STRUCT - ReadedLen;
      if OutLen >= RecCount then
        I:=Socket.ReceiveBuf(ReadBuf, RecCount)
      else
        I:=Socket.ReceiveBuf(ReadBuf, OutLen);
      If I > 0 Then
        begin
          MS.Write(ReadBuf, I);
          ReadedLen := ReadedLen + I;
        end;
      RecCount := Socket.ReceiveLength;
    until (RecCount = 0) or (OutLen = 0);

    if OutLen = 0 then
      begin
        ReadedLen := 0; //сбрасываем общее кол-во принятых байт
        //обрабатываем MS
        MS.Seek(0, soFromBeginning); //Устанавливаем начальную позицию
        MS.Read(GlobalData, MS.Size); //Читаем данные в нашу структуру
        MS.Clear; //Очищаем поток
        //отправляем пакет на обработку
        Processing(@GlobalData);
      end;

  except
    on E: Exception do
    begin
      Memo1.Lines.Add(E.Message);
    end;
  end;
end;


Это сообщение отредактировал(а) Antony41 - 13.2.2013, 19:39
PM MAIL   Вверх
Чучмек
Дата 14.2.2013, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Antony41, извини сразу не ответил, был занят.
Я с TClientSocket не работал. Работал с сокетами только через API
Но чтение я бы сделал так.
Код

procedure TForm1.CSRead(Sender: TObject; Socket: TCustomWinSocket);
type
 pr=^tr;
 tr=record
  count:integer;
  data:TData; //Твоя структура
 end;
var
 p:pr;
 rb,br:integer;
begin
if  socket.Data = nil then     //Если память для структуры tr не выделена - выделяем
  begin
  GetMem(p,sizeof(tr));        //По завершении работы(в OnDisconnect, наверное) необходимо вызвать FreeMem для socket.Data
  socket.Data:=p;
  p^.count:=0;
  end else p:=socket.Data;
repeat
 br:=sizeOf(TData)-p^.count;    //Сколько байт прочитать
 rb:=Socket.ReceiveBuf((PAnsiChar(@(p^.data))+p^.count)^,br); //только PAnsiChar !!! 
 p^.count:=p^.count+rb;         //Уже записанно байт в p^.data
 if p^.count=sizeOf(TData) then //Если p^.data полностью заполнена
  begin
  proc(p^.data);  //передаем p^.data в обработчик
  p^.count:=0;
  end;
until rb<br;    //Пока есть принятые данные - читаем
end;


Это сообщение отредактировал(а) Чучмек - 14.2.2013, 02:45


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Antony41
Дата 14.2.2013, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 27.12.2008

Репутация: нет
Всего: 1



Цитата(Чучмек @  14.2.2013,  00:22 Найти цитируемый пост)
 if p^.count=sizeOf(TData) then //Если p^.data полностью заполнена
  begin
  proc(p^.data);  //передаем p^.data в обработчик
  p^.count:=0;
  end;
until rb<br;    //Пока есть принятые данные - читаем
end;

впринципе похоже, только вот как быть если данных принято больше чем сама структура.
тоесть если пришли данные еще и из слудующего пакета, надо вырезать нужное кол-во байт, а к оставшимся начинать дописывать следующий пакет. Или пакеты не мугут быть склеины?
PM MAIL   Вверх
Чучмек
Дата 14.2.2013, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 4
Всего: 41



Цитата(Antony41 @  14.2.2013,  09:55 Найти цитируемый пост)
впринципе похоже, только вот как быть если данных принято больше чем сама структура.

Вызовется несколько раз proc. Остаток (меньший, чем размер TData) ,будет хранится в выделенной памяти. Адрес  выделенной памяти хранится в связанном с сокетом указателе Data. На каждый сокет свой указатель, своя память. Это гарантирует, что при получении, данные разных соединений не будут смешиваться.
  


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0662 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.