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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема с передачей через буфер сокета 
V
    Опции темы
VanHelsing
Дата 21.9.2008, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Код модуля сервера:
Код

unit UServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TServerChat=class(TServerSocket)
  public
    constructor Create(AOwner: TComponent); override;
    procedure MyConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyError(Sender: TObject; Socket: TCustomWinSocket;
                ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure MyDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyServerRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyServerWrite(Sender: TObject; Socket: TCustomWinSocket);
  end;  

type
TStructChat=record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string;//ник клиента
  IPClient:string;//Ip-адрес клиента
  IPClientDop:string;//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string;//отправляемый текст
  FileName:string;//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;



implementation

uses Unit1;

procedure AddMemoText(Memo1:TMemo;s:string);
begin
  Memo1.Lines.Add(s);
end;

procedure AddListClient(ListBox:TListBox;s:string);
begin
  ListBox.Items.Add(s);
end;

procedure DeleteListClient(ListBox:TListBox;s:string);
var
  i:word;
begin
   i:=0;
   for I := 0 to ListBox.Items.Count - 1 do
    begin
      if ListBox.Items.Strings[i]=s then
       begin
         ListBox.Items.Delete(i);
         exit;
       end;
    end;
end;

var
  SizeClient:word;
  fReceive : boolean;
  rSize : integer;
  msStructS,msStructC : TMemoryStream;
  CompleteSize : integer;
  StructS:array[0..999] of TStructChat;
  StructC:TStructChat;
  s:string;

  constructor TServerChat.Create(AOwner: TComponent);
  begin
  try
  inherited Create(AOwner);
  finally
   OnConnect := MyConnect;
   OnDisconnect := MyDisconnect;
   OnError:=MyError;
   OnClientRead:=MyServerRead;
   OnClientWrite:=MyServerWrite;
   msStructS:=TMemoryStream.Create;
   msStructC:=TMemoryStream.Create;
   SizeClient:=0;
  end;
  end;

 {MyServerRead - аналогично OnClientRead}
 procedure TServerChat.MyServerRead(Sender: TObject; Socket: TCustomWinSocket);
 var
   IpClient:string;
   len,i:integer;
   s1:string;
   p:pointer;
 begin
   {когда клиент посылает данные}
   len:=Socket.ReceiveLength;
   msStructC.Position:=0;
   Socket.ReceiveBuf(msStructC.Memory^,len);
   msStructC.Read(StructC,len);
   StructS[SizeClient].Kod:=StructC.Kod;
   StructS[SizeClient].Nik:=StructC.Nik;
   StructS[SizeClient].IPClient:=StructC.IPClient;
   StructS[SizeClient].IPClientDop:=StructC.IPClientDop;
   StructS[SizeClient].Text:=StructC.Text;
   StructS[SizeClient].FileName:=StructC.FileName;
   StructS[SizeClient].Size:=StructC.Size;
   StructS[SizeClient].Flag:=StructC.Flag;   
end.

Код модуля клиента:
Код

unit UClient_C;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ScktComp;

type
  TClient = class (TClientSocket)
    public
      procedure CConnect(Sender: TObject; Socket: TCustomWinSocket);
      procedure CDisconnect(Sender: TObject; Socket: TCustomWinSocket);
      procedure CError(Sender: TObject; Socket: TCustomWinSocket;
                       ErrorEvent: TErrorEvent; var ErrorCode: Integer);
      procedure CRead(Sender: TObject; Socket: TCustomWinSocket);
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
  end;

type
TstructChat=record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string;//ник клиента
  IPClient:string;//Ip-адрес клиента
  IPClientDop:string;//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string;//отправляемый текст
  FileName:string;//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

var
  StructC:TStructChat;
  msClient,msServer:TMemoryStream;

implementation

uses UCLient;

{ TClient }

constructor TClient.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  OnError := CError;
  OnConnect := CConnect;
  OnDisconnect := CDisconnect;
  OnRead := CRead;
  msClient:=TMemoryStream.Create;
  msServer:=TMemoryStream.Create;
end;

destructor TClient.Destroy;
begin
   msClient.Free;
   msServer.Free;
  inherited;
end;

procedure TClient.CConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  a:integer;
begin
   StructC.Kod:=1;
   StructC.Nik:=FClient.Edit1.Text;
   StructC.IPClient:=ClientSocket.Socket.LocalHost;
   StructC.IPClientDop:='';
   StructC.Text:='';
   StructC.FileName:='';
   StructC.Size:=0;
   StructC.Flag:=false;
   msClient.Write(StructC,sizeof(StructC));
   a:=msClient.Size;
   ClientSocket.Socket.SendBuf(msClient.Memory^,a); 
end;
end.

При подключении клиента к серверу происходит ошибка, которая разрывает соединение. При пошаговом запуске программа останавливается на строке
Код

 msStructC.Read(StructC,len);

Скажите пожалуйста что неправильно? 


--------------------
PM MAIL   Вверх
Matematik
Дата 21.9.2008, 21:05 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



msClient.Write(StructC,sizeof(StructC));

string - это указатель на данные
соотв. sizeof(StructC) будет 1+4+4+4+4+4+4+1 = 26 байт
передаешь только указатель

Тут несколько путей, например, вместо string сделать массив array[1..255{размер для примера}] of char;, вместо record - packet record
Соотв. будут проблемы -передаваться лишние данные и(или) не хватит массива на большую стоку
PM MAIL WWW ICQ   Вверх
BaD_SeCt0R
Дата 21.9.2008, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Lazy Coder
**


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

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



Только не
Цитата(Matematik @  21.9.2008,  21:05 Найти цитируемый пост)
packet record
, а packed record


--------------------
Кто владеет информацией - владеет миром. (С) Френсис Бэкон.
PM MAIL ICQ   Вверх
VanHelsing
Дата 22.9.2008, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Цитата

string - это указатель на данные
соотв. sizeof(StructC) будет 1+4+4+4+4+4+4+1 = 26 байт
передаешь только указатель
Тут несколько путей, например, вместо string сделать массив array[1..255{размер для примера}] of char;, вместо record - packet record
Соотв. будут проблемы -передаваться лишние данные и(или) не хватит массива на большую стоку

Не совсем понял что это дает. Получается просто один тип поменять на другой? smile 


--------------------
PM MAIL   Вверх
Matematik
Дата 22.9.2008, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



Клиент передает не строку, а указатель, где строка лежит в памяти клиента.
Сервер берет этот указатель и пытается прочитать строку у себя в памяти, и естественно выдает ошибку.
PM MAIL WWW ICQ   Вверх
VanHelsing
Дата 23.9.2008, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Ну допустим изменю структуру:
Код

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:array[1..20] of char;//ник клиента
  IPClient:array[1..19] of char;//Ip-адрес клиента
  IPClientDop:array[1..19] of char;//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:array[1..255] of char;//отправляемый текст
  FileName:array[1..20] of char;//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

Искал информацию, но безуспешно. В чем разница? Передавать указатель на string или char? А packed record просто оптимизирует память. Это единственный вариант? Просто если использовать массив Char, то возникает дополнительная трудность с преобразованием.


--------------------
PM MAIL   Вверх
Matematik
Дата 23.9.2008, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



> В чем разница?

В одном случае передается строка (именно блок символов), в другом - нет.

Совсем забыл:
вместо Array[1..5] of Char можно писать string[5], так даже проще будет


PM MAIL WWW ICQ   Вверх
VanHelsing
Дата 24.9.2008, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Я переделал. Клент:
Код

unit UClient1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp, StdCtrls;

type
  TForm1 = class(TForm)
    ClientSocket1: TClientSocket;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string[20];//ник клиента
  IPClient:string[22];//Ip-адрес клиента
  IPClientDop:string[22];//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string[255];//отправляемый текст
  FileName:string[30];//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

var
  Form1: TForm1;
  structC:TstructChat;
  msstream:TMemoryStream;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  structC.Kod:=1;
  structC.Nik:='prizrak';
  structC.IPClient:='127.0.0.1';
  structC.IPClientDop:='';
  structC.Text:='';
  structC.FileName:='';
  structC.Size:=0;
  structC.Flag:=false;
  msstream.Write(structC,sizeof(structC));
  ClientSocket1.Socket.SendBuf(msstream,sizeof(structC));
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  msstream.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ClientSocket1.Host:='127.0.0.1';
  ClientSocket1.Active:=true;
  msstream:=TMemoryStream.Create;
end;

end.

Сервер:
Код

unit UServer1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ScktComp;

type
  TForm1 = class(TForm)
    ServerSocket1: TServerSocket;
    procedure FormCreate(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string[20];//ник клиента
  IPClient:string[22];//Ip-адрес клиента
  IPClientDop:string[22];//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string[255];//отправляемый текст
  FileName:string[30];//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

var
  Form1: TForm1;
  structS:TstructChat;
  msS:TMemoryStream;

implementation

{$R *.dfm}

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  msS.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ServerSocket1.Active:=true;
  ServerSocket1.Open;
  msS:=TMemoryStream.Create;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  i:integer;
begin
   i:=0;
   i:=Socket.ReceiveLength;
   Socket.ReceiveBuf(msS.Memory^,i);
   msS.Read(structS,i);
end;

end.

Все равно выскакивает таже ошибка. Пробовал писать в значения тип char, все равно не получается.  Даже не знаю что сделать. smile 


--------------------
PM MAIL   Вверх
Matematik
Дата 24.9.2008, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



Подозреваю что тут
Код

Socket.ReceiveBuf(msS.Memory^,i);

переменная msS.Memory равна nil.
Память надо выделять под буфер:
Код

msS.Size := 0 {что-то там};


PM MAIL WWW ICQ   Вверх
VanHelsing
  Дата 25.9.2008, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Matematik большое спасибо, но получилось не все.
Сервер:
Код

unit UServer;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ScktComp;

type
  TServerChat=class(TServerSocket)
  public
    constructor Create(AOwner: TComponent); override;
    procedure MyConnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyError(Sender: TObject; Socket: TCustomWinSocket;
                ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    procedure MyDisconnect(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyServerRead(Sender: TObject; Socket: TCustomWinSocket);
    procedure MyServerWrite(Sender: TObject; Socket: TCustomWinSocket);
  end;  

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string[20];//ник клиента
  IPClient:string[15];//Ip-адрес клиента
  IPClientDop:string[15];//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string[255];//отправляемый текст
  FileName:string[30];//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

var
  SizeClient:word;
  fReceive : boolean;
  rSize : integer;
  msStructS,msStructC : TMemoryStream;
  CompleteSize : integer;
  StructS:array[0..999] of TStructChat;
  StructC:TStructChat;
  s,s1:string;

implementation

uses Unit1;

procedure AddMemoText(Memo1:TMemo;s:string);
begin
  Memo1.Lines.Add(s);
end;

procedure AddListClient(ListBox:TListBox;s:string);
begin
  ListBox.Items.Add(s);
end;

procedure DeleteListClient(ListBox:TListBox;s:string);
var
  i:word;
begin
   i:=0;
   for I := 0 to ListBox.Items.Count - 1 do
    begin
      if ListBox.Items.Strings[i]=s then
       begin
         ListBox.Items.Delete(i);
         exit;
       end;
    end;
end;



  constructor TServerChat.Create(AOwner: TComponent);
  begin
  try
  inherited Create(AOwner);
  finally
   OnConnect := MyConnect;
   OnDisconnect := MyDisconnect;
   OnError:=MyError;
   OnClientRead:=MyServerRead;
   OnClientWrite:=MyServerWrite;
   msStructS:=TMemoryStream.Create;
   msStructC:=TMemoryStream.Create;
   SizeClient:=0;
  end;
  end;

 {MyConnect - аналогично OnConnect}
 procedure TServerChat.MyConnect(Sender: TObject; Socket: TCustomWinSocket);
 begin
   {событие когда клиент подключается}
 end;

 {MyOnError - аналогично OnError}
 procedure TServerChat.MyError(Sender: TObject; Socket: TCustomWinSocket;
                ErrorEvent: TErrorEvent; var ErrorCode: Integer);
 begin
   {событие возникает когда происходит ошибка}
 end;

 {MyDisconnect - аналогично OnDisconnect}
 procedure TServerChat.MyDisconnect(Sender: TObject; Socket: TCustomWinSocket);
 begin
   {событие происходит когда клиент отключается}
 end;

 {MyServerRead - аналогично OnClientRead}
 procedure TServerChat.MyServerRead(Sender: TObject; Socket: TCustomWinSocket);
 var
   IpClient:string;
   len,i:integer;
 begin
   {когда клиент посылает данные}
   len:=Socket.ReceiveLength;
   msStructC.Size:=len;
   Socket.ReceiveBuf(msStructC.Memory^,len);
   msStructC.Read(StructC,len);
   {ShowMessage(IntToStr(len));}
   StructS[SizeClient].Kod:=StructC.Kod;
   StructS[SizeClient].Nik:=StructC.Nik;
   StructS[SizeClient].IPClient:=StructC.IPClient;
   StructS[SizeClient].IPClientDop:=StructC.IPClientDop;
   StructS[SizeClient].Text:=StructC.Text;
   StructS[SizeClient].FileName:=StructC.FileName;
   StructS[SizeClient].Size:=StructC.Size;
   StructS[SizeClient].Flag:=StructC.Flag;
   IpClient:=StructS[SizeClient].IPClient;
   case (StructS[SizeClient].Kod) of
   1:
    begin
      for i := 0 to ServerChat.Socket.ActiveConnections-1 do
      begin
         if (ServerChat.Socket.Connections[i].LocalHost<>StructS[SizeClient].IPClient) then
         begin
           StructC.Kod:=1;
           StructC.Nik:=StructS[SizeClient].Nik;
           StructC.IPClient:=StructS[SizeClient].IPClient;
           StructC.IPClientDop:='';
           StructC.Text:='';
           StructC.FileName:='';
           StructC.Size:=0;
           StructC.Flag:=false;
           msStructC.Write(StructC,sizeof(StructC));
           ServerChat.Socket.Connections[i].SendBuf(msStructC,sizeof(StructC));
         end;
      end;
      s1:='Подключился '+StructS[SizeClient].Nik;
      AddMemoText(Form1.MLog,s1);
      s1:='IP адрес подключившегося  '+StructS[SizeClient].IPClient;
      AddMemoText(Form1.MLog,s1);
      AddListClient(Form1.ListBox1,StructS[SizeClient].Nik);
      msStructC.Free;
    end;
    2:
     begin
      for i := 0 to ServerChat.Socket.ActiveConnections-1 do
      begin
         if (ServerChat.Socket.Connections[i].LocalHost<>StructS[SizeClient].IPClient) then
         begin
           StructC.Kod:=2;
           StructC.Nik:=StructS[SizeClient].Nik;
           StructC.IPClient:=StructS[SizeClient].IPClient;
           StructC.IPClientDop:='';
           StructC.Text:='';
           StructC.FileName:='';
           StructC.Size:=0;
           StructC.Flag:=false;
           msStructC.Write(StructC,sizeof(StructC));
           ServerChat.Socket.Connections[i].SendBuf(msStructC,sizeof(StructC));
         end;         
      end;
      s1:='Отключился '+StructS[SizeClient].Nik;
      AddMemoText(Form1.MLog,s1);
      s1:='IP адрес отключившегося  '+StructS[SizeClient].IPClient;
      AddMemoText(Form1.MLog,s1);
      DeleteListClient(Form1.ListBox1,StructS[SizeClient].Nik);
      msStructC.Free;
    end;
   end;
    SizeClient:=SizeClient+1;
 end;
end.

Клиент:
Код

unit UClient_C;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ScktComp;

type
  TClient = class (TClientSocket)
    public
      procedure CConnect(Sender: TObject; Socket: TCustomWinSocket);
      procedure CDisconnect(Sender: TObject; Socket: TCustomWinSocket);
      procedure CError(Sender: TObject; Socket: TCustomWinSocket;
                       ErrorEvent: TErrorEvent; var ErrorCode: Integer);
      procedure CRead(Sender: TObject; Socket: TCustomWinSocket);
      constructor Create(AOwner: TComponent); override;
      destructor Destroy; override;
  end;

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string[20];//ник клиента
  IPClient:string[15];//Ip-адрес клиента
  IPClientDop:string[15];//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string[255];//отправляемый текст
  FileName:string[30];//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

var
  StructC:TStructChat;
  msClient,msServer:TMemoryStream;

implementation

uses UCLient;

{ TClient }

constructor TClient.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  OnError := CError;
  OnConnect := CConnect;
  OnDisconnect := CDisconnect;
  OnRead := CRead;
  msClient:=TMemoryStream.Create;
  msServer:=TMemoryStream.Create;
end;

destructor TClient.Destroy;
begin
   msClient.Free;
   msServer.Free;
  inherited;
end;

procedure TClient.CConnect(Sender: TObject; Socket: TCustomWinSocket);
var
  a:integer;
begin
   StructC.Kod:=1;
   StructC.Nik:=FClient.Edit1.Text;
   StructC.IPClient:=ClientSocket.Socket.LocalHost;
   StructC.IPClientDop:='';
   StructC.Text:='';
   StructC.FileName:='';
   StructC.Size:=0;
   StructC.Flag:=false;
   msClient.Write(StructC,sizeof(StructC));
   a:=msClient.Size;
   ClientSocket.Socket.SendBuf(msClient.Memory^,a); 
end;
end.

Ошибки больше вылазит, но данные все равно не передаются. В итоге после записи в структуру записи чей тип равен типу string[], равны пустому значению, а поля с цифровым значение передаются? smile 

Это сообщение отредактировал(а) VanHelsing - 27.9.2008, 06:35


--------------------
PM MAIL   Вверх
VanHelsing
Дата 28.9.2008, 19:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Помогите пожалуйста. Правда хочу разобраться! smile 


--------------------
PM MAIL   Вверх
Matematik
Дата 29.9.2008, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 24
Всего: 50



Не знаю, попробуй передавать без MemoryStream, у меня код работает
Код

type
  TForm1 = class(TForm)
    btn1: TButton;
    ClientSocket1: TClientSocket;
    ServerSocket1: TServerSocket;
    procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
    procedure btn1Click(Sender: TObject);
    procedure ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
TstructChat=packed record
  Kod:byte; //данное поле отвечает за код команды
  Nik:string[20];//ник клиента
  IPClient:string[15];//Ip-адрес клиента
  IPClientDop:string[15];//Ip-адрес клиента получателя – используется при отправка файлов и личных сообщениях
  Text:string[255];//отправляемый текст
  FileName:string[30];//имя отправляемого файла
  Size:integer;//размер отправляемого файла
  Flag:boolean;//флаг определяет разрешение на прием-передачу файла
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  // Connect!
  ClientSocket1.Active := True;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket);
var
 structChat : TstructChat;
begin
    with structChat do
    begin
      Kod := 1;
      Nik := 'Nik';
      IPClient := 'IPClient';
      IPClientDop := 'IPClientDop';
      Text := 'text 11111111';
      FileName := 'fileName';
      Size := 123;
      Flag := True;
    end;
    Socket.SendBuf(structChat, SizeOf(structChat)); // отправить
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
 structChat : TstructChat;
begin
  // читать только если пришли все данные
  // теоритически! возможно деление пакета
  if Socket.ReceiveLength<SizeOf(structChat) then
    Exit;
  Socket.ReceiveBuf(structChat, SizeOf(structChat));
  //-----------------------------------------------------
  structChat.Kod := structChat.Kod + 1;
  //-----------------------------------------------------
  // в бесконечный цикл
  Socket.SendBuf(structChat, SizeOf(structChat)); 

end;

procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
 structChat : TstructChat;
begin
  if Socket.ReceiveLength<SizeOf(structChat) then
    Exit;
  Socket.ReceiveBuf(structChat, SizeOf(structChat));
  //-----------------------------------------------------
  structChat.Kod := structChat.Kod + 1;
  //-----------------------------------------------------
  Socket.SendBuf(structChat, SizeOf(structChat));
end;
end.



PM MAIL WWW ICQ   Вверх
VanHelsing
Дата 30.9.2008, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



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

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



Matematik спасибо. Теперь разобрался. Начал все усложнять и зачем-то использовал TMemoryStream.
P.S. надеюсь теперь точно все! smile 


--------------------
PM MAIL   Вверх
Gwire
Дата 10.3.2011, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Пост, конечно, очень старый... Но все же хочется поделится самым простым способом выделения буфера для сокета.

С начала, хочу сказать, что "string" и "array of <тип>" взяты под котроль "Borland memory manager" (для тех кто не знал).
Выденная для них память автоматически освобождается, если ни одна переменная не не указывает на нее. Пример:
Код

var A, B, C: array of Char;
begin
    SetLength(A, 100*1024*1024); // размер памяти увеличится +100Мб. (см. Alt+Ctrl+Del)
    SetLength(B, 100*1024*1024); // +100Мб.
    C:= A;  // +0
    C:= B;  // +0
    B:= A;  // +0
    C:= A;  // -100Mb Память выделеная изначально для B освободилаль
    Finalize(A); //-0 Память еще нужна для B и С
    B[0]:= '#';
    C[0]:= '@';
    Write( B[0] );  // @ 
end;


То что "string"("array of") указатель это не проблема, данные физически начинаются с первого(нулевого) елемента.
Код

var Data: String;
begin
    SetLength( Data, <требуемый размер> ); // Например SizeOf(TstructChat)
    . . .
    Socket.Send( Data[1], Length(Data) );  // =)
    // Можно не парится при выходе из функции память будет освобождена BMM-ом.
    // Ну для успокоения можно написать "Finalize(Data);" (я пишу, но если забыл.. ошибок не возникает)
end;  

Для чтения из сокета - аналогично. SetLength -> Recv -> Finalize

Этот метод очень удобен для данных с неопределеной заренее длиной.

P.S. Если данные стуктурированные ("record" или "packed record") @Data[1] присваеваем в указатель на структуру.
P:= @Data[1]; где P : {например} ^TstructChat; Заполняем или считываем через P^


PM MAIL   Вверх
cat512
Дата 10.3.2011, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

С начала, хочу сказать, что "string" и "array of <тип>" взяты под котроль "Borland memory manager" (для тех кто не знал)

Только под контролем не "Borland memory manager - а" a, самого компилятора! Менеджеру памяти абсолютно пох. есть ли ссылки на какую-то строку или нет. Он выполняет только команды по выделению/освобождению памяти, а также оптимизирует структуру для быстрого доступа к нужным объктам и выделения памяти. Автоматическое управление временем жизни некоторых "объектов", возложенно на компилятор. Он генерит код (rtl), который говорит МП, когда тот должен выделить/освободить память

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

Запрещено:

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

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

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

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

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


 




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


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

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