如何通过TcpClient,TcpServer把Record和MemoryStream一起发出和接收? ( 积分: 200 )

  • 主题发起人 主题发起人 kingsonchan
  • 开始时间 开始时间
K

kingsonchan

Unregistered / Unconfirmed
GUEST, unregistred user!
如题。
我试过用一个MemoryStream把Record和MemoryStream连到一起发送,但接收总是出错,好像什么都收不到。我想这种情况应该要分两次接收吧,第一次接收Record,第二次接收MemoryStream,在Record里有一值记录MemoryStream的大小。但连Record的记录都收不到。是不是record和MemoryStream不能一起发送呢?如果分开发送,接收时可能不知道该收哪种数据的。而且,那个BytesReceived总是0,好像没什么用。
数据结构:
type TMsgNode=record
sender:string;
msgSendTime:TDatetime;
streamSize:Integer;
end;
如果可以把MemoryStream放到record里也无所谓的。
是不是TcpClient和TcpServer控件的局限呢?如果要用IdTcpServer,IdTcpClient也可以。
谢谢。
 
// 服务端default port 8080
// 客户端发送port 8080
//前两天才写的一个demo,可以发的

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPServer,
IdTCPConnection, IdTCPClient, ExtCtrls, ComCtrls;

type
TfrmClient = class(TForm)
Label1: TLabel;
edtFileName: TEdit;
btnBrowse: TButton;
btnSend: TButton;
cmbIP: TComboBox;
Label2: TLabel;
cmbPort: TComboBox;
Label3: TLabel;
OpenDialog1: TOpenDialog;
IdTCPServer1: TIdTCPServer;
IdTCPClient1: TIdTCPClient;
Bevel1: TBevel;
procedure btnBrowseClick(Sender: TObject);
procedure btnSendClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmClient: TfrmClient;

implementation

{$R *.dfm}

procedure TfrmClient.btnBrowseClick(Sender: TObject);
begin
if OpenDialog1.Execute then
edtFilename.Text := OpenDialog1.FileName;
end;

procedure TfrmClient.btnSendClick(Sender: TObject);
var
ms: TMemoryStream;
begin
IdTCPClient1.Host := cmbIP.Text;
IdTCPClient1.Port := StrToInt(cmbPort.Text);
ms := TMemoryStream.Create;
ms.LoadFromFile(OpenDialog1.FileName);
IdTCPClient1.Connect();
IdTCPClient1.WriteStream(ms);
IdTCPClient1.Disconnect();
ms.Free;

end;

procedure TfrmClient.FormCreate(Sender: TObject);
begin
IdTCPServer1.Active := True;
end;

procedure TfrmClient.IdTCPServer1Execute(AThread: TIdPeerThread);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
AThread.Connection.ReadStream(ms,-1,True);
ms.SaveToFile('D:/DelphiDemo/Socket/Tcp/tt.txt');
OutputDebugString('Save Successful!');
ms.Free;
// AThread.Connection.Disconnect;
end;

end.
 
你这个只是MemoryStream的发送和接收,我试过单独发MemoryStream或者Record都可以正常发送和接收,但如果两者连在一起操作,就不行了。谢谢楼上的答复。
 
在发时,把你的record读入到Memorystream里
比如你发时的Memorystream前32biye记录你的record,后面再读入一段你要发的stream
接收时你分析出来就可以的,
 
// 服务端default port 8080
// 客户端发送port 8080
//注意你定的结构时,你的string类型为定长,
//共同学习中......
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPServer,
IdTCPConnection, IdTCPClient, ExtCtrls, ComCtrls;

type
TfrmClient = class(TForm)
Label1: TLabel;
edtFileName: TEdit;
btnBrowse: TButton;
btnSend: TButton;
cmbIP: TComboBox;
Label2: TLabel;
cmbPort: TComboBox;
Label3: TLabel;
OpenDialog1: TOpenDialog;
IdTCPServer1: TIdTCPServer;
IdTCPClient1: TIdTCPClient;
Bevel1: TBevel;
procedure btnBrowseClick(Sender: TObject);
procedure btnSendClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
private
{ Private declarations }
public
{ Public declarations }
end;

TPerson = record
Name: string[20];
Age: Integer;
end;

var
frmClient: TfrmClient;

implementation

{$R *.dfm}

procedure TfrmClient.btnBrowseClick(Sender: TObject);
begin
if OpenDialog1.Execute then
edtFilename.Text := OpenDialog1.FileName;
end;

procedure TfrmClient.btnSendClick(Sender: TObject);
var
ms,mstmp: TMemoryStream;
per1: TPerson;
begin
IdTCPClient1.Host := cmbIP.Text;
IdTCPClient1.Port := StrToInt(cmbPort.Text);

per1.Name := 'DelphiBBs';
per1.Age := 5;
ms := TMemoryStream.Create;
mstmp := TMemoryStream.Create;

// ms.ReadBuffer(per1,SizeOf(per1));
ms.Write(per1,SizeOf(per1)) ;
mstmp.LoadFromFile(OpenDialog1.FileName);
ms.CopyFrom(mstmp,mstmp.Size);
IdTCPClient1.Connect();
IdTCPClient1.WriteStream(ms);
IdTCPClient1.Disconnect();
ms.Free;
mstmp.Free;

end;

procedure TfrmClient.FormCreate(Sender: TObject);
begin
IdTCPServer1.Active := True;
end;

procedure TfrmClient.IdTCPServer1Execute(AThread: TIdPeerThread);
var
ms: TMemoryStream;
mstmp :TMemoryStream;
per2: TPerson;
begin
ms := TMemoryStream.Create;
mstmp := TMemoryStream.Create;
AThread.Connection.ReadStream(ms,-1,True);
ms.Position := 0;
ms.Read(per2,SizeOf(per2));
mstmp.CopyFrom(ms,ms.Size-Sizeof(per2));
mstmp.SaveToFile('D:/DelphiDemo/Socket/Tcp/tt.txt');
OutputDebugString('Save Successful!');
ms.Free;
mstmp.Free;
// AThread.Connection.Disconnect;
end;


end.
 
上例中per2的数据能够接收到了,但是文件保存的不对。文件大小相同,但内容是乱码,用记事本打开,发现有些相同内容的文字,是不是mstmp的定的位置不对呢?
 
你应该去看看关于 指针,内存,MemoryStream 方面的资料
TcpClient和TcpServer控件完全可以满足你的要求,再检查一下你的程序吧
 
文件保存是除per2的数据,如果你发的是jpg,你把文件就保存为名jpg.说白了,这个mstmp需要你去分析它的结构.如果你保存为tt.jpg,再打开它会以jpg文件类型打开.
所以你可以在Tperson这个结构做个扩展,专门保存文件的扩展名.在接收时,存为这个扩展名的文件.
自己仔细想一下...
 
我发的就是TXT文件,也保存为TXT文件了,这么基本的东西我还是了解的。
 
你把你发送和接受的代码贴出来,一块来看看.
我贴出来的程序,我试了,没有问题的.
 
现在又可以了。哎~~
问一下,Copyfrom和WriteBuf有什么区别?同样的方法能在tcpServer上用吗?IdTCPServer的ReadStream里的-1参数可以读取所有的buf,但tcpServer上好像没有类似的方法吧?还有就是tcpServer上的BytesReceived为什么总是0?
回答后结帖,谢谢大家了。
 
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
http://www.51zhan.com 最好的网址站
 
多人接受答案了。
 
后退
顶部