高手请进:用ClientSocket和serversocket网络传送文件内容不对!(100分)

  • 主题发起人 主题发起人 powersite
  • 开始时间 开始时间
P

powersite

Unregistered / Unconfirmed
GUEST, unregistred user!
[:(!]
代码:
我用ClientSocket和serversocket网络传送文件,两边都用stNonBlocking方式,server端用SendStream发送一个17K的文件,发送正常。但在Client端接收多次触发事件检查却发现前面的两次8K数据都是正常。但第三次却有问题,检查ReceiveLength发现超出正常正确数字4K多,因此用ReceiveBuff接收不正确。后用SendBuff也不一样的故障,请教,不胜感激!
 
接受端是用ReadStream?
可以先用文本文件试试。
 
谢谢jsxjd,但ClientSocket只有ReadBuff而并没有ReadStream。我查了一下,ReadStream是TNMUDP的。
 
1.传输单个文件的方法
原理说明:发送方首先发送文件大小,接收方创建一个Stream,准备接收,发送准备好信
息,发送方发送整个流,如果流比较大,系统会自动分包发送,所以在客户端要做一个拼
接处理。即判断接收后的Stream的大小,如果小于文件大小,则继续接收,否则接收完成。
//********************************************************
private
stream : TMemoryStream; //定义内存流,其实用文件流也可以
size,count : integer; //文件大小
end;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address := Edit1.Text;
ClientSocket1.Active := True;
end;

procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected to '+Socket.RemoteAddress;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
stream := TMemoryStream.Create;
if OpenDialog1.Execute then
begin
stream.LoadFromFile(OpenDialog1.FileName);
size := stream.Size; //获得文件大小
count := 0;
ClientSocket1.Socket.SendText(inttostr(size)); //先发送大小
end;
end;

procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
rcvtxt : string;
buf : array [1..2048] of char;
left : integer;
begin
rcvtxt := Socket.ReceiveText;
left := size - count; //未读字节数
if AnsiPos('go',rcvtxt)=1 then //收到响应则发
begin
if sizeof(buf)<left then //若满一块则读一块
begin
stream.Read(buf,sizeof(buf));
Socket.SendBuf(buf,sizeof(buf));
count := count + sizeof(buf);
end
else //不满则发剩余的
begin
stream.Read(buf,left);
Socket.SendBuf(buf,left);
end;
end;
end;


Server端(收方)

private
Tof : file;
size,count :integer;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.CutFirst(denstr: string;scrstr: string);
var
len :integer;
begin
len := length(scrstr);
denstr := copy(scrstr,2,(len-1));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Active := True;
StatusBar1.SimpleText := 'Listening...';
end;

procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := 'Connected from '+ Socket.RemoteAddress;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
buf : array [1..2048] of char;
rcvtxt : string;
left,len : integer;
begin
len := Socket.ReceiveLength;
if len<10 then //若长度小于10则认为是文件长度
begin
rcvtxt := Socket.ReceiveText;
size := strtoint(rcvtxt);
count := 0;
if SaveDialog1.Execute then
begin
AssignFile(ToF, SaveDialog1.FileName);
Rewrite(ToF, 1);
end;
Socket.SendText('go'); //响应一块
end
else
begin
left := size - count; //未写的字节数
if sizeof(buf)<left then //满一块则写一块
begin
Socket.ReceiveBuf(buf,sizeof(buf));
BlockWrite(Tof,buf,sizeof(buf));
count := count + sizeof(buf);
Socket.SendText('go');
end
else //否则写剩余字节数
begin
Socket.ReceiveBuf(buf,left);
BlockWrite(Tof,buf,left);
CloseFile(Tof);
end;
end;
end;
********************************************************//
 
我后来用了变通:
r:=False;
while r=false do
begin
r:=Serversocket.socket.connections.sendbuf(Buffer,Size);
if r=false then
Sleep(10);
end;
判断确定已发送之后再发
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部