![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
![]() Здравствуйте, возник такой вопрос:
Я начал писать клиент-серверное приложение и решил передавать данные с помощью разных структур. В интернете читал, искал примеры, но подходящие были связаны лишь с работой со строками. Но у меня же всё иначе. Для начала первый вопрос: 1.1 например имеем заранее известную структуру, допустим такую: Код:
TMyStructure = packed record A:Byte; B:Single; C:Integer; end; 1.2 Учесть, что если вдруг сразу не придет целиком одна структура. (т.е. её необходимо дочитать до полной структуры). 2) всё также, как и в первом вопросе, но только мы допустим имеем несколько различных структур, как их правильно принять и разделить ? ______ Исходя из того, что я читал, мне получается нужно ввести какую-то уникальную сигнатуру каждого пакета(или точнее структуры), что если структура допустим первая, то у нее: Код:
TMyStructure = packed record sign:Byte; // Сигнатура A:Byte; B:Single; C:Integer; end; Код:
TMyStructure2 = packed record sign:Byte; // Сигнатура A:String[20]; B:Integer; C:array[1..10] of Single; end; В общем нужен какой-то разделить или что-то подобное сигнатуры. И ещё вопрос насчет пункта 1.2: если структура небольшого размера, то вообще возможно ли такое, что она прийдет не вся целиком ? скорее всего возможно, поэтому я и задал этот вопрос. Помогите пожалуйста разобраться. ___ Ах да, ещё у меня такая мысль была, что если передавать массив байт, а в конце например сигнатуру FF FF FF, но будет довольно сложно каждый тип данных привести из байт к своему, например тотже Single из байт в Single и наоборот, также с каждым типом. Хотя эта идея мне кажется интересной. Помогите может какие идеи насчет этого есть. Т.к. Этот способ кажется попроще, но и возникает проблема с преобразованием байт в соответствующие типы. С нетерпением жду ответов. Если Вы находите ошибки, исправить которые дело долгое и нудное, ничего не делайте - просто внесите их в список особенностей ![]() Последний раз редактировалось Oleg, 20.02.2011 в 16:51. |
#2
|
||||
|
||||
![]() один из вариантов мультиплексирования:
-перед каждой структурой сервер передает либо ее "тип", либо ее размер -клиент сперва считывает "тип" (и по типу определяет размер структуры) или размер структуры -затем ожидает во входном буфере данных этого или большего объема -когда данные есть, считывает объем, равный размеру структуры -остальные данные будут относиться к следующей структуре - опять "тип" или размер+сама структура однако сокетные данные бьются, если их размер больше 8К = 8192 байта, имхо Пишу программы за еду. __________________ |
#3
|
||||
|
||||
![]() Это конечно понятно, принцип по какому нужно работать.
Но хотелось бы примера, пожалуйста. И вообще мне больше нравится вариант последний, который я описывал, как массив байт, возможно ли и как подобное реализовать ? Например мне нужны следующие типы данных, которые я буду передавать в структурах: Single, Integer, Char; самые основные пусть будут эти..как это передать и перевести обратно. например разделителем будет определенный код в конце по которому и будут разделяться пакеты.. Тогда тут будет выигрыш в том, что я могу передавать лишь определенные байты и все будет гораздо проще разделяться и т.п., ну это на мой взгляд. Если Вы находите ошибки, исправить которые дело долгое и нудное, ничего не делайте - просто внесите их в список особенностей ![]() |
#4
|
||||
|
||||
![]() один из вариантов мультиплексинга:
Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ScktComp; type PRec1 = ^TRec1; TRec1 = record ID: Word; Data: String[32]; end; PRec2 = ^TRec2; TRec2 = record ID: Word; Parent: Word; Data: String[32]; end; TForm1 = class(TForm) ServerSocket1: TServerSocket; CheckBox1: TCheckBox; Memo1: TMemo; ClientSocket1: TClientSocket; Button1: TButton; Button2: TButton; Button3: TButton; procedure CheckBox1Click(Sender: TObject); procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } FPipeRead: THandle; FPipeWrite: THandle; FDataLen: DWORD; procedure Multiplex; procedure Notify(data: PChar; len: DWORD); public { Public declarations } end; var Form1: TForm1; const PipeSize: Cardinal = 1024*1024; implementation {$R *.dfm} procedure TForm1.Multiplex; var len: DWORD; data: PChar; dummy: Cardinal; begin while True do begin len:=GetFileSize(FPipeRead, nil); if len=0 then Break; if FDataLen=0 then begin if len<SizeOf(DWORD) then Break; ReadFile(FPipeRead, FDataLen, SizeOf(DWORD), dummy, nil); end else begin if len<FDataLen then Break; GetMem(data, FDataLen); ReadFile(FPipeRead, data^, FDataLen, dummy, nil); Notify(data, FDataLen); FreeMem(data); FDataLen:=0; end; end; end; procedure TForm1.Notify(data: PChar; len: DWORD); begin Memo1.Lines.Add('--'); case len of SizeOf(TRec1): begin Memo1.Lines.Add('ID='+IntToStr(PRec1(data)^.ID)); Memo1.Lines.Add('Data='+PRec1(data)^.Data); end; SizeOf(TRec2): begin Memo1.Lines.Add('ID='+IntToStr(PRec2(data)^.ID)); Memo1.Lines.Add('Parent='+IntToStr(PRec2(data)^.Parent)); Memo1.Lines.Add('Data='+PRec2(data)^.Data); end; end; end; procedure TForm1.CheckBox1Click(Sender: TObject); begin ServerSocket1.Active:=CheckBox1.Checked; end; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var len: DWORD; data: PChar; dummy: Cardinal; begin len:=Socket.ReceiveLength; GetMem(data, len); len:=Socket.ReceiveBuf(data^, len); WriteFile(FPipeWrite, data^, len, dummy, nil); FreeMem(data); Multiplex; end; procedure TForm1.FormCreate(Sender: TObject); begin CreatePipe(FPipeRead, FPipeWrite, nil, PipeSize); FDataLen:=0; end; procedure TForm1.FormDestroy(Sender: TObject); begin CloseHandle(FPipeWrite); CloseHandle(FPipeRead); end; procedure TForm1.Button1Click(Sender: TObject); var rec1: TRec1; buf: DWORD; begin ClientSocket1.Open; rec1.ID:=$1; rec1.Data:='avatar'; buf:=SizeOf(rec1); ClientSocket1.Socket.SendBuf(buf, SizeOf(DWORD)); ClientSocket1.Socket.SendBuf(rec1, SizeOf(rec1)); ClientSocket1.Close; end; procedure TForm1.Button2Click(Sender: TObject); var rec2: TRec2; buf: DWORD; begin ClientSocket1.Open; rec2.ID:=$2; rec2.Parent:=$1; rec2.Data:='the stol'; buf:=SizeOf(rec2); ClientSocket1.Socket.SendBuf(buf, SizeOf(DWORD)); ClientSocket1.Socket.SendBuf(rec2, SizeOf(rec2)); ClientSocket1.Close; end; procedure TForm1.Button3Click(Sender: TObject); var rec1: TRec1; rec2: TRec2; buf: DWORD; i: Integer; begin ClientSocket1.Open; for i:=1 to 10 do begin rec1.ID:=i; rec1.Data:='avatar'; buf:=SizeOf(rec1); ClientSocket1.Socket.SendBuf(buf, SizeOf(DWORD)); ClientSocket1.Socket.SendBuf(rec1, SizeOf(rec1)); rec2.ID:=i*100; rec2.Parent:=i; rec2.Data:='the stol'; buf:=SizeOf(rec2); ClientSocket1.Socket.SendBuf(buf, SizeOf(DWORD)); ClientSocket1.Socket.SendBuf(rec2, SizeOf(rec2)); end; ClientSocket1.Close; end; end. TCheckBox вкл/выкл сервер Open1 посылает 1 тип рекорда Open2 посылает 2 тип рекорда OpenMany посылает 10 раз [1 тип, 2 тип] Пишу программы за еду. __________________ |
#5
|
||||
|
||||
![]() Большое спасибо, замечательный пример.
![]() Буду теперь делать все по такому принципу, очень понравился пример, просто супер, огромное спасибо ещё раз. Если Вы находите ошибки, исправить которые дело долгое и нудное, ничего не делайте - просто внесите их в список особенностей ![]() |
#6
|
||||
|
||||
![]() Сейчас начал писать обработки и возник такой вопрос...
а могу ли я сделать так: Код:
procedure ServerClientRead(Sender: TObject; Socket: TCustomWinSocket); var <...> begin < ...> Multiplex(Socket); end; procedure Multiplex(mSock: TCustomWinSocket); var <...> begin <...> Notify(data, FDataLen,mSock); <...> end; procedure Notify(data: PChar; len: DWORD;mFrom: TCustomWinSocket); begin <...> {Просто здесь мне нужен сокет, например чтобы отправить по заданному адресу обратно сообщение какое-то в зависимости от того, что пришло.} end; Будет ли такая конструкция правильно работать ? Если я добавил в аргумент каждой функции ещё один параметр, не будет ли путанницы ? просто подобный способ нужен на сервере(TServerSocket). Всё ли будет правильно обрабатываться, если сообщения одновременно могут прийти от разных клиентов ? Если Вы находите ошибки, исправить которые дело долгое и нудное, ничего не делайте - просто внесите их в список особенностей ![]() |