关于流的问题(100分)

  • 主题发起人 主题发起人 jstkof
  • 开始时间 开始时间
J

jstkof

Unregistered / Unconfirmed
GUEST, unregistred user!
我想把文件从一台机器传到另一台机器,用clientsocket和serversocket应该怎么写?
另外,请大家看一下为什么下面的代码不起作用呢?(我想拷贝文件s1到s2,不想用
copyfrom,因为socket好像没有copyfrom方法)
var
s1,s2:TFileStream;
begin
if opendialog1.Execute then
begin
s1:=TFileStream.Create(opendialog1.filename,fmopenread);
try
if opendialog1.Execute then
begin
s2:=TFileStream.Create(opendialog1.filename,
fmopenwrite or fmCreate);
try
//s2.CopyFrom(s1,s1.size);
s2.read(s1,s1.size);
finally
s2.free;
end;
end;
finally
s1.Free;
end;
end;
end;
 
用循环发送数据的办法!
 
这样:我是用API写的
FileStream.ReadBuffer(Buffer^,Send_Size);
Send_Len:=Send(Send_FileSock,Buffer^,Send_Size,0);
if Send_Len=SOCKET_ERROR then
begin
LogStr:=IntToStr(Thread_ID)+'线程发送中出错...'+TimeToStr(Now);
Synchronize(Record_Message);
break;
end;
Synchronize(ShowProgess);
if File_E-idx+1>=MAXSIZE then //发送数等于预期
Send_Size:=MAXSIZE
else
Send_Size:=File_E-idx+1;
end;
这是个大致的模型 。外层还有个循环,总之处理很复杂!
 
谢谢张教主,不过小弟水平有限,乾坤大挪移只练到第二层,实在看不懂你的代码啊,呵呵。
 
我是用winsock api写的,是多线程中的发送文件部分,你如果要详细的,你把的发送代码部分
给我,我帮你修改。
 
还有,我觉的你的代码很多地方模糊不清,要多看点别人写的代码才好,
 
我是这样写的:
发送部分用TClientsocket:
procedure TForm1.Button3Click(Sender: TObject);
var
source:TFileStream;
buffer:pchar;
count:longint;
begin
opendialog1.Title:='请选择源文件';
if opendialog1.Execute then
begin
source:=TFileStream.create(opendialog1.filename,fmopenread);
try
count:=source.Size;
getmem(buffer,count);
source.Read(buffer^,count);
clientsocket1.Socket.SendBuf(buffer^,count);
freemem(buffer,count);
//clientsocket1.Socket.SendStream(source);
finally
source.free;
end;
end;
end;
接收部分用TServerSocket:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
target:TFileStream;
buffer:pchar;
count:longint;
begin
opendialog1.Title:='请选择目标文件';
if opendialog1.Execute then
begin
target:=TFileStream.Create(opendialog1.filename,
fmopenwrite or fmCreate);
try
count:=socket.ReceiveLength();
getmem(buffer,count);
socket.ReceiveBuf(buffer^,count);
target.Write(buffer^,count);
freemem(buffer,count);
finally
target.free;
end;
end;
end;
传送几百字节的小文件正常,可传送大一点的文件时服务器端要弹出好几次opendialog,
很奇怪。代码有点多,可能比较烦,有劳张教主了。:)
 
:)
1、你应该知道TCP最大的一个数据包里的用户数据只能有64K,这是由IP头的数据长度
字段确定的,所以你的代码根本没有好好理解这一点.......
2、我认为你可以做一个标志,用一个枚举变量,在传文件之前把这个文件的长度传过
来,再这样,这个代码是我很久以前写的。
procedure TForm1.ClientSocket2Read(Sender: TObject;
Socket: TCustomWinSocket);
var len:integer;
temp:string;
begin
if stStatue=stgetFile then
begin
Len:=Socket.ReceiveLength;
Temp:=Socket.ReceiveText;
filem.Write(PChar(Temp)^,len); //filem是一个文件流
inc(allLen,len);
if allLen=getfilesize then //allLen是文件长度,你先传送过来
ShowMessage('文件接受完毕!');
end;
 
可以把发送部分的代码也给我吗?谢谢
 
使用缓冲区.
xxxx : array of byte;
 
const
MAX_LEN=2048;

var
iSen:integer; //iSen发送出去的长度
iSize:integer; //文件长度 最好是全局变量
buf:array[1..MAXLEN]of char;
senlen:integer; //每次应该发送的长度
ret:integer; //实际发送的文件长度
filen:TFileStream; //最好是全局变量

iSen:=0;
while iSen<iSize do
begin
FillChar(buf,MAX_LEN,0);
if iSize-iSen>MAX_LEN then senlen:=MAX_LEN
else senLen:=iSize-iSen;
filen.Position:=iSen;
filen.Read(buf,senLen);
ret:=ClientSocket1.Socket.SendBuf(buf,senLen);
inc(iSen,ret);
end;
 
不想编太多的代码的话就请用TurboPower中Async Professional,只要使用
APDWinSock和Zmodem协议的控件就可以进行互连网/局域网传输文件,而且支持
代理服务器。强烈推荐。
 
不要什么都用控件,到了最后发现只会用控件了,其他的包括运算,一点都不会了,[8D]
 
谢谢zwh,控件以后我会用的,不过张无忌说的对,现在我想先搞清楚原理。实际上,我现
在感到困惑的不是怎样分割文件发送出去,而是怎样在每段要发送的数据前面加上数据头以
及怎样在接受时读取它。可能大家会认为很简单,可是我真的不懂。我试过这样:
buffer^:='body'; //buffer是缓冲区
source.read(buffer^,count); //source是文件流TFileStream
可是不行,后面那句要把'body'冲掉。我又想用分开发送的办法:
发送:
1 clientsocket1.socket.sendtext('body');
2 clientsocket1.Socket.SendBuf(buffer^,count);
接收:
var
s:string;
3 s:=serversocket1.Socket.ReceiveText;
4 if s='body' then
5 socket.ReceiveBuf(buffer^,count);
可是仍然不行,接收不到数据,我估计是第3句出了问题。还请各位大虾指点迷津啊
 
你用一个端口发送字符,一个端口发送数据,和FTP一样,
你说的后面和前面和合成一个数据块发送出去确实如此,TCP是基于流的协议
没有数据边界保护
 
谢谢各位大侠,特别是张教主,很热心,分分。
 
多人接受答案了。
 
后退
顶部