谁帮我把这个问题搞定,我分全给他了,再加上真心的感谢(200分)

  • 主题发起人 主题发起人 yourkeychen
  • 开始时间 开始时间
如果实在麻烦,你生成的txt发一个email过去行不行?
 
用TServerSocket和TClientSocket做的简单的发送接受例程:
发送:
var
buffer: string; // 保存要发送的文件内容
currentpos: cardinal = 0; // 当前发送起始位置,这两个变量为全局变量
restlen: Integer = 0; // 剩余需要发送的长度

procedure TForm1.SendFile(const filename: string);
var
fid: integer;
begin
fid := fileopen(filename, fmOpenRead or fmShareDenyNone);
if fid > 0 then
begin
setlength(buffer, fileseek(fid, 0, 2));
fileseek(fid, 0, 0);
fileread(fid, buffer[1], length(buffer)); // 读取文件到内存
fileclose(fid);
currentpos := cardinal(buffer)-4; // 设定发送起始位置,初始值为buffer的地址-4(delphi的string类型起始地址-4的位置
// 正好存储了string的长度,我们将长度一起发以便server判断是否接受完整
restlen := length(buffer)+4; // 剩余需要发送的长度
clientsocket1.onwrite := continuesendfile;
clientsocket1.onerror := sendfilestop;
continuesendfile(self, clientsocket1.socket); // 首次发送
end;

procedure TForm1.ContinueSendFile(Sender: TObject; Socket: TCustomWinSocket);
var
l: Integer;
begin
if restlen > 0 then
repeat // 循环发送直到填满发送缓冲区或全部发完
l := socket.sendbuf(pbyte(currentpos)^,restlen);
if l > 0 then
begin
inc(currentpos,l);
dec(restlen, l);
end;
until (l<0) or (restlen=0);
end;

procedure TForm1.SendFileStop(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
restlen := 0; // 终止发送
ErrorCode := 0; // 防止弹出错误窗口
end;

接收:
var
buffer: string;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
fid: integer;
begin
buffer := buffer + socket.receivetext;
if (length(buffer)>4) and (length(buffer)=pinteger(integer(buffer))^+4) then //接收完成
begin
fid := filecreate('received.txt');
filewrite(fid,pbyte(integer(buffer)+4)^, pinteger(integer(buffer))^);
fileclose(fid);
buffer := '';
end;
end;
 
我现在的问题不是如何接收的问题,是单独的接收我已经可以接收了,但是在这个程序中,我在接收目录信息之前还会接收身份验证信息,身份验证信息已经可以正确接收并识别了,但是在它之后的目录信息却总是和它合在一起发送,导致我后面的目录信息无法正确接收。
我如何在接收目录信息的时候去除前面已经接收的验证信息,让他们分开?怎么才能正确识别目录信息而不是验证信息?
 
每个数据段前加个长度一起发不就ok了? 看来我上面的代码白写了。你根本没看。
 
To:Another_eYes,
  你的代码我看了,我不是很懂,明白大概意思
你的clientsocket1.onwrite和onerror是什么?是自己的过程或函数?
我不是打开文件的方式来传送,是程序自己一连接成功了就传,它其他信息混在一起了,我不是单独只发送文件。如果是单独发文件好像是正确了。就是混在一起了,我不知道如何加它的长度,如果识别。我现在的程序只判断了一次,只收了一个包,就没在接收了。25个前面的验证字串,1460个文件内容,这只是发送的一次长度,应该有很多个1460包的,我结果只收到了一个。我真的不是很,可不可以帮我写的清楚一点,就是在程序中即要判断其他信息的收发,又要判断这个文件的收发。因为单独的每一个我好像都知道了,但混在一起,我就真的不知道如何处理。
  不好意思,我太菜了,烦你再费费心了。
 
TClientSocket.OnWrite, TClientSocket.OnError这两个是TClientSocket的事件句柄,TClientSocket.OnError事件是发送/接受出错(除了缓冲区满这个错之外)时触发的。其中的ErrorCode指明出错原因(即api: WSAGetLastError的返回值)。

TClientSocket.OnWrite事件是当你发送数据而底层缓冲区已满致使你发送失败后等底层缓冲区有空闲字节时触发的(以便你可以重发上次失败的数据)。
这样所以你可以通过写TClientSocket.OnWrite事件将大块数据发送出去而不必关心底层缓冲区的大小(那玩意只有8k)。

至于服务器端怎么区分客户端发来的数据,我说一个简单的例子吧:
假设,客户端连接后首先传送文件名,文件创建时间,然后再发送文件内容,服务器端根据收到的文件名和创建时间建立这个文件,并且客户端是一次混合发送所有信息的,
为了便于服务器端区分文件名,创建时间和文件内容,可以这样规定客户端得发送格式:
第0-3字节(4字节):文件名长度
第4~11字节(8字节):文件创建时间--TFimeTime格式(windows的文件日期格式)
第12~19字节(8字节):文件最后访问时间--TFileTime格式
第20~27字节(8字节):文件最后修改时间--TFileTime格式
第28~n-1字节(n字节):文件名(包含路径)
第n~n+3字节(4字节):文件具体内容长度
第n+4~结束:文件具体内容

客户端只要按照上述格式将数据发送出去,服务器端则可以根据接收到的缓冲区按上述格式分析是否接收全所有数据(只要根据其中的长度和实际接收到的长度即可计算出),如果没有收全则将本次收到的数据包添加到自己开的一块缓冲区中然后等待下一次接受(写服务器控件的OnClientRead事件即可,每次有数据到达会自动调用),如果收满则根据格式定义中的信息创建文件即完成了整个任务。
 
直接用压缩控件压缩目录,传送,然后还原,不行吗?
 
对,用压缩控件压缩目录为为文件,发送到客户端,然后解开。
这样作的好处是:1、压缩后数据量变小,有利于网络传输。2、展开时不用在处理目录
 
楼上两位,我只要能传了再来考虑文件的大小,不管他多大多小,至少要能正确传输再说。而且我的要的只是目录信息(路径名和文件名),并不要文件本身,所以这个目录不可能很大的。
 
说实话,我还是没有解决这个问题,可能是我太菜了,知道了原理,但我还是没有做出来.
哎...........算了,绝望了...............散分了
 
谢谢大家的参与,这个问题已经解决了,如果有谁需要的话,可以来信索取。
版主帮我把分回收,我自己已经找人搞定了。
 
我來了!!!!!!!!!!!!!!!!!!!!!!!!
絕對不是受賄???
 
接受答案了
 
我分发错了,请Another_eYes,app2001,angelgekko, 到
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2167232
去,我分给你们。不好意思,让你们跑路了。
 
后退
顶部