局域网文件传输 1个服务器 对应多个客户端(30左右);
怎么设计?大家有什么好的建议。
(目前我用TServersocket TclientSocket)实现了 但是速度很差、而且大文件(500多K)就会掉包。)
我分析了一下:
1、客户端发送得慢。TclientSocket的堆栈里面堆满来不急发的速度。所以丢失数据。
2、服务器端只是在ClientRead里面处理忙不过来。接受的堆栈堆满了速度。所以丢失
上面是我个人猜测。我也不知道他们堆栈有没有大小的。
我的代码:
客户端:Const SendLength=3000;
const SFilenameLength=40;
Const TotalSlength=3042;
//
Function FindFirst_FM:boolean;
var
sr:TSearchRec;
Attr:Integer;
s:string;
begin
result:=false;
s:='CFileSend\*.jpg';
Attr:=FaAnyFile;
if FindFirst(s,Attr,sr)=0 then
begin
FindClose(sr);
SendFileName:=sr.name;
form1.memo1.lines.add('Find File to Send:'+sr.name);
result:=true;
end;
end;
//启动线程后线程处理:
procedure TThreadClient.Execute;
var Fr,fw:TFileStream;
size:int64;
buf:array[1..TotalSlength] of char;
SendTimes:integer;
Pbuf:^CSendRecord;
handle:thandle;
realPos:int64;
respart:integer;
begin
while not Terminated do
begin
sleep(1000);
if FindFirst_FM then //检测文件
begin
//发文件
//文件分割
Fr:=TFileStream.Create('CFileSend\'+SendFileName,fmOPenRead);
fr.Position:=0;
size:=Fr.Size;
sendTimes:=size div sendlength;
respart:=size mod sendlength;
while sendTimes>0 do
begin
form1.c1.Socket.
realPos:=fr.Position;
fillchar(buf,TotalSlength,0);
buf[1]:='b';
buf[2]:='b';
move(sendfilename[1],buf[3],length(sendfilename));
Fr.ReadBuffer(buf[SFilenameLength+3],SendLength);
form1.c1.Socket.SendBuf(buf[1],TotalSlength);
dec(sendtimes);
sleep(300);
end;
if respart>0 then
begin
fillchar(buf,TotalSlength,0);
buf[1]:='b';
buf[2]:='b';
move(sendfilename[1],buf[3],length(sendfilename));
Fr.ReadBuffer(buf[SFilenameLength+3],respart);
form1.c1.Socket.SendBuf(buf[1],TotalSlength);
end;
fr.Free;
//备份文件
copyfile(PAnsiChar('CFileSend\'+sendfilename),PAnsiChar('CFileSendHis\'+sendfilename),true);
//删除文件
deletefile('CFileSend\'+sendfilename);
end;
end;
end;
//服务器端
procedure TForm1.s1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var strrec:string;
ip:string;
cid:integer;
size:int64;
buf:array[1..TotalSLength] of char;
fw:TFileStream;
recfilename:string;
OperateSign:string;
handle:Thandle;
begin
fillchar(buf,TotalSLength,0);
ip:=socket.RemoteAddress;
socket.ReceiveBuf(buf[1],TotalSLength);
OperateSign:=buf[1]+buf[2];
if OperateSign='aa'then//aa表示客户端退出前发的信息。
begin
deletecm(ip);
memo1.Lines.Add(ip+': closed!');
end
else if OperateSign='bb'then //bb表示传输的是文件
begin
recfilename:=copy(buf,3,SendFLength+2);
if fileexists('SFileRec\'+recfilename) then
else
begin
handle:=filecreate('SFileRec\'+recfilename);
fileclose(handle);
end;
fw:=TFileStream.Create('SFileRec\'+recfilename,fmOpenWrite);
size:=fw.size;
fw.position:=size;
fw.WriteBuffer(buf[SendFLength+3],FSendLength);
fw.Free;
end;
怎么设计?大家有什么好的建议。
(目前我用TServersocket TclientSocket)实现了 但是速度很差、而且大文件(500多K)就会掉包。)
我分析了一下:
1、客户端发送得慢。TclientSocket的堆栈里面堆满来不急发的速度。所以丢失数据。
2、服务器端只是在ClientRead里面处理忙不过来。接受的堆栈堆满了速度。所以丢失
上面是我个人猜测。我也不知道他们堆栈有没有大小的。
我的代码:
客户端:Const SendLength=3000;
const SFilenameLength=40;
Const TotalSlength=3042;
//
Function FindFirst_FM:boolean;
var
sr:TSearchRec;
Attr:Integer;
s:string;
begin
result:=false;
s:='CFileSend\*.jpg';
Attr:=FaAnyFile;
if FindFirst(s,Attr,sr)=0 then
begin
FindClose(sr);
SendFileName:=sr.name;
form1.memo1.lines.add('Find File to Send:'+sr.name);
result:=true;
end;
end;
//启动线程后线程处理:
procedure TThreadClient.Execute;
var Fr,fw:TFileStream;
size:int64;
buf:array[1..TotalSlength] of char;
SendTimes:integer;
Pbuf:^CSendRecord;
handle:thandle;
realPos:int64;
respart:integer;
begin
while not Terminated do
begin
sleep(1000);
if FindFirst_FM then //检测文件
begin
//发文件
//文件分割
Fr:=TFileStream.Create('CFileSend\'+SendFileName,fmOPenRead);
fr.Position:=0;
size:=Fr.Size;
sendTimes:=size div sendlength;
respart:=size mod sendlength;
while sendTimes>0 do
begin
form1.c1.Socket.
realPos:=fr.Position;
fillchar(buf,TotalSlength,0);
buf[1]:='b';
buf[2]:='b';
move(sendfilename[1],buf[3],length(sendfilename));
Fr.ReadBuffer(buf[SFilenameLength+3],SendLength);
form1.c1.Socket.SendBuf(buf[1],TotalSlength);
dec(sendtimes);
sleep(300);
end;
if respart>0 then
begin
fillchar(buf,TotalSlength,0);
buf[1]:='b';
buf[2]:='b';
move(sendfilename[1],buf[3],length(sendfilename));
Fr.ReadBuffer(buf[SFilenameLength+3],respart);
form1.c1.Socket.SendBuf(buf[1],TotalSlength);
end;
fr.Free;
//备份文件
copyfile(PAnsiChar('CFileSend\'+sendfilename),PAnsiChar('CFileSendHis\'+sendfilename),true);
//删除文件
deletefile('CFileSend\'+sendfilename);
end;
end;
end;
//服务器端
procedure TForm1.s1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var strrec:string;
ip:string;
cid:integer;
size:int64;
buf:array[1..TotalSLength] of char;
fw:TFileStream;
recfilename:string;
OperateSign:string;
handle:Thandle;
begin
fillchar(buf,TotalSLength,0);
ip:=socket.RemoteAddress;
socket.ReceiveBuf(buf[1],TotalSLength);
OperateSign:=buf[1]+buf[2];
if OperateSign='aa'then//aa表示客户端退出前发的信息。
begin
deletecm(ip);
memo1.Lines.Add(ip+': closed!');
end
else if OperateSign='bb'then //bb表示传输的是文件
begin
recfilename:=copy(buf,3,SendFLength+2);
if fileexists('SFileRec\'+recfilename) then
else
begin
handle:=filecreate('SFileRec\'+recfilename);
fileclose(handle);
end;
fw:=TFileStream.Create('SFileRec\'+recfilename,fmOpenWrite);
size:=fw.size;
fw.position:=size;
fw.WriteBuffer(buf[SendFLength+3],FSendLength);
fw.Free;
end;
解决方案 »
- 获取子窗体名加载到MainMenu
- 如何自定义颜色
- 请问哪有现成的餐饮代码下载
- 还有人吗?我还没睡,有没有人陪我啊?放分罗!!
- 欢迎各位传经送宝,问一下StringGrid关联数据库的问题..........
- 在线等,100分,立结TListBox滚动问题!
- ADO支持filteroptions吗?,please help me !!!!在ADOQUERY中如何filter中出现了filteroption are not supported?(
- 十万火急
- 如何判断数据库一个字段是否存在?
- 关于数据库统计速度
- SOS,调用别人的接口函数时出错,急急急
- CreateOleObject后,调用函数传递字节数组,报错,不支持此接口
var strrec:string;
ip:string;
cid:integer;
size:int64;
buf:array[1..TotalSLength] of char;
fw:TFileStream;
recfilename:string;
OperateSign:string;
handle:Thandle;
begin
fillchar(buf,TotalSLength,0);
ip:=socket.RemoteAddress;
socket.ReceiveBuf(buf[1],TotalSLength);
OperateSign:=buf[1]+buf[2];
if OperateSign='aa'then//aa表示客户端退出前发的信息。
begin
deletecm(ip);
memo1.Lines.Add(ip+': closed!');
end
else if OperateSign='bb'then //bb表示传输的是文件
begin
recfilename:=copy(buf,3,SendFLength+2);
if fileexists('SFileRec\'+recfilename) then
else
begin
handle:=filecreate('SFileRec\'+recfilename);
fileclose(handle);
end;
//你每次都是重新打开文件,效率非常低
fw:=TFileStream.Create('SFileRec\'+recfilename,fmOpenWrite);
size:=fw.size;
fw.position:=size;
fw.WriteBuffer(buf[SendFLength+3],FSendLength);
fw.Free;
end;
然后先把读到的文件数据存在buf中 等传完了一次性写入文件。但是效果好像更慢了。我为什么服务器要做校验 、做返回。然后再让客户端再传 就是因为。不这个搞传过来的图片跟原来的图片相差太远了。
局域网传输速度更定是很快的。但是肯定有速度丢失了。我猜测试 socket传输的buffer 太小了。
好像一次读取最多才8000多个byte .只是猜测。因为我也不知道服务器socket控件 接受数据的区域到底有多打。
然后先把读到的文件数据存在buf中 等传完了一次性写入文件。但是效果好像更慢了。我为什么服务器要做校验 、做返回。然后再让客户端再传 就是因为。不这个搞传过来的图片跟原来的图片相差太远了。
局域网传输速度更定是很快的。但是还是有数据丢失了。我猜测是 服务器socket接受信息的buffer 太小了。
好像一次读取最多才8000多个byte .只是猜测。因为我也不知道服务器socket控件 接受数据的区域到底有多大
-----------------
默认缓冲区是 8096
begin
AThread.ReadBuffer...;
//处理数据
end;TServerSocket是默认采用消息的,没有用多线程,因此客户端多的时候,性能非常成问题,我试了一下,把ServerType改成stThreadBlocking,TServerSocket的性能也不高。