Конференция "Сети" » Передача типов через TClientsData [D6, Win2k, WinXP]
 
  • Calligraff © (10.12.08 10:53) [0]
    Добрый день.

    Подскажите пожалуйста как можно реализовать следующее:

    Есть тип:

    type
     TClientsData = class(TObject)
       UIN: Integer;
       Password: String;
     end;

    var
      Data: TClientsData;
    begin
    Data := TClientsData.Create;
    Data.Login := 450355355;
    Data.Password := '';

    // TClientSocket
    // Как отправить?

    end;


    Как отправить Data через TClientSocket, а на TServerSocket принять??

    Зарание благодарен
  • Медвежонок Пятачок © (10.12.08 11:46) [1]
    TClientsData = record
      UIN: Integer;
      Password: shortstring;
    end;

    var cd : TClientsData;

    .....

    soket.WriteBuff(cd,SizeOf(TClientsData));
  • Calligraff © (10.12.08 12:21) [2]
    Спасибо, Медвежонок Пятачок :)

    Не подскажешь еще одно.

    Вот на серверной стороне программы делаю так


    procedure TformMain.socketServerClientWrite(Sender: TObject;
     Socket: TCustomWinSocket);
    var
      Data: TClientsData;
    begin
    ClientSocket1.Active := True;
    Data := TClientsData.Create;
    Socket.ReceiveBuf(Data,Socket.ReceiveLength);
    end;



    но в итоге Data.UIN = 0, а Data.Password Пустой
  • Медвежонок Пятачок © (10.12.08 12:33) [3]
    Data := TClientsData.Create;

    А должен быть тот же тип что и при отправке.
  • Calligraff © (10.12.08 12:39) [4]

    > А должен быть тот же тип что и при отправке.

    Точно. Спасибо  огромное :)
  • Сергей М. © (10.12.08 13:04) [5]

    > Calligraff


    Все равно работать не будет
  • Calligraff © (10.12.08 14:03) [6]
    ВСе. заработало!

    только теперь другая проблема

    Есть тип:

    type
     RClientLoginInfo = record
       FUIN: Integer;
       TUIN: Integer;
       TypeData: Shortint;
       Data: String[254];
     end;



    Все отлично работает, НО. необходимо передать строку длиной более 255 символов. поэтому заменяю Data: String[254]; на Data: String;

    В следствии чего при посылке данных от клиента к серверу
    procedure SendRegInfo();
    var
      Data: RClientLoginInfo;
    begin
    Data.FUIN := 1111111;
    Data.TUIN := 2222222;
    Data.TypeData := 0;
    Data.Data := '<текст длиной более 255 символов>';

    formMain.ClientSocket1.Socket.SendBuf(Data,SizeOf(RClientLoginInfo));
    end;



    и получение сервером данных

    procedure TformMain.socketServerClientRead(Sender: TObject;
     Socket: TCustomWinSocket);
    var
      Data: RClientLoginInfo;
    begin
    Socket.ReceiveBuf(Data,Socket.ReceiveLength);
    Memo1.Lines.Add(Data.Data);
    end;



    на моменте строки Memo1.Lines.Add(Data.Data); возникает ошибка Out of Memory.

    Как исправить и как быть со строками большой длины?

    Зарание благодарен.
  • Сергей М. © (10.12.08 14:17) [7]

    > как быть со строками большой длины?


    их нужно отправлять принимать отдельно, а не в составе структуры
  • Calligraff © (10.12.08 14:21) [8]
    Может как-то переводить переменную в Pointer и посылать? Но тогда я тем более не имею представления как
  • Сергей М. © (10.12.08 14:37) [9]
    см. SendText, ReceiveText
  • Calligraff © (10.12.08 15:09) [10]
    SendText, ReceiveText - не вариант, так как с текстом необходимо передавать данные
      FUIN: Integer;
      TUIN: Integer;
      TypeData: Shortint;

  • Сергей М. © (10.12.08 16:00) [11]

    > Calligraff ©   (10.12.08 15:09) [10]


    Раз ты озаботился передачей-приемом дин.типов данных с управляемым временем жизни, таких как AnsiString, затею с передачей структуры "одним махом" выбрось из головы.

    Для для передачи/приема данных типа AnsiString используй Send/ReceiveText
    Для для передачи/приема иных данных используй SendStream, Send/ReseiveBuf.
  • Calligraff © (10.12.08 16:08) [12]
    Ясно.

    Прям неудобно, но у меня еще возник вопрос

    Как задать подключению определенный ID, например такой же как и UIN пользователя для того чтобы можно было быстро отправлят сообщение от одного пользователя к тому, которому адресованно сообщение не ища в искусственно созданой таблице активных пользователей адресата.
  • Calligraff © (10.12.08 16:08) [13]
    Или может есть другие варианты?
  • Сергей М. © (10.12.08 16:20) [14]
    "не ища" не получится.


    > в искусственно созданой таблице


    Не надо создавать никакие "искуственные таблицы".

    Список активных клиентов сервера доступен в ServerSocket.Socket.Connections.
    У каждого эл-та списка - объекта TServerClientWinSocket - есть св-во Data, которое предназначено для хранения любой индивидуальной клиентской инф-ции.
  • Calligraff © (10.12.08 17:39) [15]
    Угумс...

    Тогда как в Socket.Data (кот. имеет тип Pointer) запихнуть целое (типа Integer) число???
  • clickmaker © (10.12.08 17:52) [16]
    > как в Socket.Data (кот. имеет тип Pointer) запихнуть целое

    szieof(pointer) >= sizeof(integer)
  • Calligraff © (10.12.08 17:53) [17]
    Не понял немного.. поподробнее можно.. Дело в том, что с типом Pointer не работал

    Зарание благодарен
  • Calligraff © (10.12.08 18:01) [18]
    Понял как!

    type
     TUIN = class(TObject)
       UIN: Integer;
     end;

    ........

    procedure TformMain.socketServerClientRead(Sender: TObject;
     Socket: TCustomWinSocket);
    var
      Clnt: TUIN;
      Clnt1: TUIN;
    begin
    Clnt := TUIN.Create;
    Clnt.UIN := 250355355;
    Socket.Data := Clnt;
    Clnt1 := TUIN.Create;
    Clnt1 := Socket.Data;
    Memo1.Lines.Add(IntToStr(Clnt1.UIN));
    end;


  • clickmaker © (10.12.08 18:14) [19]
    можно и без класса-обертки
    pointer = integer в 32 битных ОС и int64 в 64-битных
  • Calligraff © (10.12.08 18:29) [20]
    ясно
  • Calligraff © (10.12.08 18:48) [21]
    Спасибо огромное :)
  • Calligraff © (10.12.08 18:56) [22]

    > Для для передачи/приема данных типа AnsiString используй
    > Send/ReceiveText


    Тогда как указать, что данный текст посылается определенному пользователю в сети??
  • Сергей М. © (10.12.08 19:48) [23]

    > как указать, что данный текст посылается определенному пользователю
    > в сети?


    Перед посылкой текста посылай инф-цию о том кому он адресован.
  • Calligraff © (11.12.08 15:03) [24]
    День добрый

    возникли еще вопросики :)

    буду рад помощи.


    procedure SendContactsList(Socket: TCustomWinSocket; Data: RUsrReceiveData);
    var
      i: Integer;
      ToSocketID: Integer;
      Contact: TContactListID;
      Contacts: TList;
    begin

     ....................

          Contacts := TList.Create;
          Contact := TContactListID.Create;
          for i := 1 to formMain.queryContactsList.RecordCount do begin
             formMain.queryContactsList.First;
             Contact.UIN := formMain.queryContactsList.FieldValues['uininlst_id'];
             Contact.Visiblity := formMain.queryContactsList.FieldValues['visiblity'];
             Contacts.Add(Contact);
             formMain.queryContactsList.Next;
          end;
          Contact.Free;
       end;
       formMain.queryContactsList.Close;
       Data.DataPointer := Contacts;
       Contacts.Free;

       // временная проверка
       Contacts := TList.Create;
       Contacts := Data.DataPointer;
       Contacts.Free;



    Хотел проверить возможно ли обратно получить данные, но на строке Contacts := Data.DataPointer; ничего в Contacts от Data.DataPointer не присваивается, хотя в Data.DataPointer данные есть.

    Подскажите как быть?
  • Сергей М. © (11.12.08 16:06) [25]
    В коде куча грубейших ошибок, демонстрирующих полное непонимание тобой предмета.

    Data.DataPointer := Contacts; // здесь ты скопировал указатель на объект
    Contacts.Free; // и тут же уничтожил этот объект, теперь скопированная ссылка смотрит в никуда (в поле Data.DataPointer отныне "мусор")

    ..

    Contacts := TList.Create; // здесь ты создан новый объект и записал ссылку на него в перем-ю Contacts
    Contacts := Data.DataPointer; // а здесь ты похерил эту ссылку, затерев ее "мусором" из Data.DataPointer, появившемся там при см.выше обстоятельствах

    Ну и твоя работа с объектом Query в части хотя бы навигации по нему не выдерживает никакой критики.
  • Calligraff © (12.12.08 10:52) [26]
    Согласен в запросах исправлюсь. Тип Pointer - поучу :)

    Тогда другой вопрос.

    вот когда я передаю

    formMain.ClientSocket1.Socket.SendBuf(Data,SizeOf(RClientLoginInfo));



    то Data - Это у меня какой-то тип определенный, в данном случае Data: RClientLoginInfo; и на клиенте я получаю данные и все в порядке.

    НО, допустим я хочу в передавать разные типы в зависимости от запросов клиента

    наример есть два типа:
    Data: RClientLoginInfo;
    Data: RClientContactList;

    Каким образом можно узнать на клиентской машине, какой именно тип я передал?

    Зарание благодарен.
  • Сергей М. © (12.12.08 10:59) [27]

    > Каким образом можно узнать на клиентской машине, какой именно
    > тип я передал?


    Ну ты же сам сказал - в зависимости от запросов клиента.

    Если клиент запросил конкретно RClientLoginInfo, то совершенно очевидно, что ожидает он ответ сервера в формате именно RClientLoginInfo и ни в каком ином.
  • Calligraff © (12.12.08 11:02) [28]
    согласен, но иногда сервер должен будет передавать данные без запроса например обновление информации у клинтов о текущем состоянии.

    тогда получится клиент-программа не будет знать что за тип ей пришел

    Как можно поступить здесь?
  • Медвежонок Пятачок © (12.12.08 11:23) [29]
    тогда получится клиент-программа не будет знать что за тип ей пришел

    для этого люди придумали понятие "протокол"
  • Сергей М. © (12.12.08 11:26) [30]
    Ввведи в спецификацию своего прикл.протокола префикс типа инф.пакета.
    Любой передаваемый (неважно от кого кому) пакет предваряется передачей соотв.префикса.

    Для не болоее чем 256-ти различных типов пакетов достаточно префикса размеров в 1 байт.
  • Calligraff © (12.12.08 12:01) [31]
    Сергей, к сожаления я не силен в протоколах.

    Я использую компоненты TServerSocket и TCkientSoket

    Подскажи пожалуйста, где мне копать, чтобы разобраться с префиксом?
  • Сергей М. © (12.12.08 12:08) [32]

    > не силен в протоколах


    Речь идет о твоем собственном прикладном протоколе информационного обмена !

    А компоненты TServerSocket и TCkientSoket предназначены лишь для осуществления соединения и передачи данных любого содержания между клиентами и сервером.

    Префикс - это тоже данные.
  • Calligraff © (12.12.08 12:41) [33]
    Где можно почитать о прикладных протоколах и как их писать?
  • Сергей М. © (12.12.08 13:05) [34]
    Возьми за пример для изучения любой из известных протоколов - ftp, http, smtp, pop3

    В Тырнете подробных описаний этих протоколов (кто, кому, что, в каком формате, в какой последовательности и при каких условиях передает) - как грязи..
  • Calligraff © (16.12.08 10:04) [35]
    ЗАРАААБООООТАЛОООО!!! :)
  • Calligraff © (16.12.08 10:07) [36]
    Сергей, а не подскажешь, как в функции, например


    function MyQuery(inSQL: String): Boolean;
    begin
    ..........
    end;



    выполнить запрос к SQL так, чтобы он не зависил от компонента TQuery находящегося на форме.
    Т.е. выполнить запрос без компонента
  • Медвежонок Пятачок © (16.12.08 10:09) [37]
    function MyQuery(inSQL: String): Boolean;
    begin
    Result := True;
    end;
  • Сергей М. © (16.12.08 10:11) [38]
    function MyQuery(inSQL: String): Boolean;
    var
     Query: TQuery;
    begin
     Query := TQuery.Create(nil);
     try
    .....
     finally
       Query.Free;
     end;
    end;

  • Медвежонок Пятачок © (16.12.08 10:19) [39]
    не не не, это с компонентом
    :)
  • Сергей М. © (16.12.08 10:22) [40]

    > это с компонентом


    Но не на форме же)
  • Calligraff © (16.12.08 13:31) [41]
    А не подскажешь, как массив TMSGARRAY = array[0..7168] of byte; записать в поле таблицы и каким типом должно быть поле?

    БД MSSQL2000
  • Сергей М. © (16.12.08 13:39) [42]
    Вопросы по работе с СУБД задавай в соотв.конференции.
  • Calligraff © (16.12.08 13:42) [43]
    понял. спасибо
 
Конференция "Сети" » Передача типов через TClientsData [D6, Win2k, WinXP]
Есть новые Нет новых   [134435   +33][b:0][p:0.003]