Socket传输文件的问题(100分)

  • 主题发起人 主题发起人 hxl126
  • 开始时间 开始时间
H

hxl126

Unregistered / Unconfirmed
GUEST, unregistred user!
MDI程序启动的时候,连到服务器检查是否有更新,如果有就通过TClientSocket向服务器发送请求传输文件,请问各位,为什么设置好ClientSocket的属性, 在Form的OnCreate事件中书写如下代码,
ClientSocket.Open;
ClientSocket.SendText(sMessage);
sMessage没能发出去.
上面两条代码放在同意Button的OnClick事件中也是没反应,分别放在两个Button的事件中就能向服务发送sMessage信息.
请问要怎么处理? MDI启动时能自动更新文件
 
因为 .clientsocket.open 的时候 不一定就是 已经 打开,你可以做一个
循环检测端口就绪,然后发送.好像是跟什么阻塞/非阻塞有点关系.仿佛网络程序很多都要
等待说.
 
ClientSocket的设为ctNonBlocking

检查端口是否就绪
while Not TClientSocket.Connected do
begin
;
end;
这样检查好象不行,请问要怎么写才是正确?
 
在你open 后, TClientSocket 有个OnConnect 事件的, 在里面写上相应的代码就可以。 同时OnError 事件也写上相应错误处理的代码
 
unit uUpdateFiles;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, jpeg, ExtCtrls, StdCtrls, ScktComp, ADODB, UWater;

type
TfrmUpdateFiles = class(TForm)
Image1: TImage;
lblInfo: TLabel;
ClientSocket: TClientSocket;
procedure ClientSocketRead(Sender: TObject
Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure ClientSocketConnect(Sender: TObject
Socket: TCustomWinSocket);
procedure ClientSocketDisconnect(Sender: TObject
Socket: TCustomWinSocket);
private
{ Private declarations }
procedure DealReceiveData(Socket: TCustomWinSocket);
procedure InitSocket(Socket: TClientSocket);
function GetDataLenInfo(Data: String
Size: Integer): String;
function ReceiveFile(FileName: String
FileSize: Integer;
Socket: TCustomWinSocket): Boolean;
public
{ Public declarations }
end;

var
frmUpdateFiles: TfrmUpdateFiles;
DBConnection: TADOConnection;
sFileName: String;
sFileType: String;
sFilePath: String;

implementation

{$R *.dfm}

{ TfrmUpdateFiles }

procedure TfrmUpdateFiles.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
Data: String;
sMessage: String;
begin
Data := sFileName + '|' + sFileType + '|';
sMessage := '0000' + GetDataLenInfo(Data, 8) + Data;
ClientSocket.Socket.SendText(sMessage);
lblInfo.Caption := '正在更新' + sFileName + '文件';
end;

procedure TfrmUpdateFiles.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
Close;
end;

procedure TfrmUpdateFiles.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
DealReceiveData(Socket);
end;

procedure TfrmUpdateFiles.DealReceiveData(Socket: TCustomWinSocket);
var
I: Integer;
Flag: Boolean;
Data: String;
Count: Integer;
FileSize: Integer;
FileName: String;
Head: array[0..13] of char;
Body: array[0..49] of char;
begin
Data := '';
Count := Socket.ReceiveBuf(Head, 14);
if Count = -1 then
begin
ClientSocket.Close;
end;
if Count = 14 then
begin
Flag := (Head[5] + Head[6]) = '00';
if Flag then
begin
for i := 7 to Count - 1 do
Data := Data + Head;
FileSize := StrToInt(Data);
Count := socket.ReceiveBuf(Body, 50);
if Count = 50 then
begin
FileName := sFilePath + sFileType + '/' + sFileName;
ReceiveFile(FileName, FileSize, Socket);
end;
end;
end;
end;

procedure TfrmUpdateFiles.FormClose(Sender: TObject
var Action: TCloseAction);
begin
//FreeAndNil(frmUpdateFiles);
end;

procedure TfrmUpdateFiles.FormCreate(Sender: TObject);
begin
InitSocket(ClientSocket);
ClientSocket.Open

end;

function TfrmUpdateFiles.GetDataLenInfo(Data: String
Size: Integer): String;
var
sLen: String;
begin
sLen := IntToStr(Length(Data));
case Length(sLen) of
0: result := '00000000';
1: result := '0000000' + sLen;
2: result := '000000' + sLen;
3: result := '00000' + sLen;
4: result := '0000' + sLen;
5: result := '000' + sLen;
6: result := '00' + sLen;
7: result := '0' + sLen;
else
raise exception.Create('数据出错');
end;
end;

procedure TfrmUpdateFiles.InitSocket(Socket: TClientSocket);
var
SysVariable: TSysVariable;
IP: String;
Port: Integer;
begin
SysVariable := TSysVariable.Create(DBConnection);
IP := SysVariable.GetVariable('Server');
Port := StrToInt(SysVariable.GetVariable('Port'));
Socket.Host := IP;
socket.Port := Port
end;

function TfrmUpdateFiles.ReceiveFile(FileName: String
FileSize: Integer;
Socket: TCustomWinSocket): Boolean;
var
AStream: TMemoryStream;
buf: array[0..8192 - 1] of byte;
Len, Count: Integer;
begin
try
AStream := TMemoryStream.Create;
Len := 0;
while FileSize > Len do
begin
if Socket.ReceiveLength > 0 then
begin
Count := Socket.ReceiveBuf(buf, SizeOf(buf));
AStream.WriteBuffer(buf, Count);
Len := Len + Count;
if FileSize = Len then
begin
AStream.SaveToFile(FileName);
FreeAndNil(AStream);
end;
end;
end;
result := True;
except
On E: Exception do
begin
result := False;
FreeAndNil(AStream);
end;
end;
end;

end.

我MDI程序启动的时候,查找文件更新列表,然后用如下代码调用:
with FFileInfo do
begin
First;
while Not Eof do
begin
DBConnection := FDBConnection;
sFileName := // 文件名
sFileType := //文件类型; 用做路径,如:dll之类
sFilePath := //文件存放路径
frmUpdateFiles := TfrmUpdateFiles.Create(Self);
frmUpdateFiles.ShowModal;
FreeAndNil(frmUpdateFiles);
Next;
end;
end;
传输第一个文件是正确的,第二文件就出错,请问是什么原因.
文件传输的服务器先传输文件信息,再传输文件。如:
00000000006551Trade.rav
00 1-2为字符命令 00 代表 传输文件命令
00 3-4位 预留两位
00 5-6位 表示反馈信息 00 表示成功 10 表示文件不存在......
00006551 八位表示文件大小
Trade.rav 固定50个字符,表示文件名(不带路径)
 
function TfrmUpdateFiles.ReceiveFile(FileName: String
FileSize: Integer;
Socket: TCustomWinSocket): Boolean;
var
AStream: TMemoryStream;
buf: array[0..8192 - 1] of byte;
Len, Count: Integer;
begin
try
AStream := TMemoryStream.Create
//这里有问题的! 如果你的文件大一点, 网络会进行分包传输, 以后你的接收就是最后一个数据包保存起来。 得不到完整的文件。 所以你的内存流应该定义为private
但开始接收文件的时候进行初始化。
Len := 0;
while FileSize > Len do
begin
if Socket.ReceiveLength > 0 then
begin
Count := Socket.ReceiveBuf(buf, SizeOf(buf));
AStream.WriteBuffer(buf, Count);
Len := Len + Count;
if FileSize = Len then
begin
AStream.SaveToFile(FileName);
FreeAndNil(AStream);
end;
end;
end;
result := True;
except
On E: Exception do
begin
result := False;
FreeAndNil(AStream);
end;
end;
end;

end.
 
我的Socket的是异步模式,为什么每次传输完毕,不管是文件还是一般的信息都会产生一个-1长度的消息,请问是怎么回事?
 
后退
顶部