一个关于WinSocket的Easy问题 (200分)

  • 主题发起人 主题发起人 NeverMind
  • 开始时间 开始时间
N

NeverMind

Unregistered / Unconfirmed
GUEST, unregistred user!
1.只有在Button点击了两次以后,文件才会传输;
2.在下列源码中我已标识,如果将strReceive的位置放置于if语句上方,则Server方收到Client方发来的文本文件将为乱码。
以上两个问题不解,请大虾们帮帮忙,谢谢了!:-)


Client端:

unit ClientUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls;

type
TClientForm = class(TForm)
EditIP: TEdit;
BtnSend: TButton;
ClientSocket: TClientSocket;
procedure BtnSendClick(Sender: TObject);
procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
m_Size,m_Amount:Integer;
memStream:TMemoryStream;
public
{ Public declarations }
end;

var
ClientForm: TClientForm;

implementation

{$R *.dfm}

procedure TClientForm.BtnSendClick(Sender: TObject);
begin
ClientSocket.Address:=EditIP.Text;
ClientSocket.Open;
memStream:=TMemoryStream.Create;
memStream.LoadFromFile('d:/temp/hello.txt');
m_Size:=memStream.Size;
m_Amount:=0;
ClientSocket.Socket.SendText(IntToStr(m_Size));
end;

procedure TClientForm.ClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
var
strReceive:String;
m_Remain:Integer;
arrBuffer:Array [1..1024] of char;
begin
strReceive:=Socket.ReceiveText;
if strReceive='Action' then
begin
m_Remain:=m_Size-m_Amount;
if (SizeOf(arrBuffer)<m_Remain) then
begin
memStream.Read(arrBuffer,SizeOf(arrBuffer));
Socket.SendBuf(arrBuffer,SizeOf(arrBuffer));
m_Amount:=m_Amount+SizeOf(arrBuffer);
end
else
begin
memStream.Read(arrBuffer,m_Remain);
Socket.SendBuf(arrBuffer,m_Remain);
end;
end;
end;

end.
////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
Server端:
unit ServerUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ScktComp;

type
TServerForm = class(TForm)
ServerSocket: TServerSocket;
StatusBar: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure ServerSocketAccept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
m_Size,m_Amount:Integer;
fileSave:File;
public
{ Public declarations }
end;

var
ServerForm: TServerForm;

implementation

{$R *.dfm}

procedure TServerForm.FormCreate(Sender: TObject);
begin
ServerSocket.Open;
end;

procedure TServerForm.ServerSocketAccept(Sender: TObject;
Socket: TCustomWinSocket);
begin
StatusBar.Panels[0].Text:='已连接至'+Socket.RemoteAddress;
end;

procedure TServerForm.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
arrBuffer:Array [1..1024] of char;
m_Remain,m_Legth:Integer;
strReceive:String;
begin
m_Legth:=Socket.ReceiveLength;
if m_Legth<10 then
begin
strReceive:=Socket.ReceiveText; //*****问题2*****//
AssignFile(fileSave, 'd:/'+'world.txt');
Rewrite(fileSave,1);
m_Amount:=0;
m_Size:=StrToInt(strReceive);
Socket.SendText('Action');
end
else
begin
m_Remain:=m_Size-m_Amount;
if (m_Remain>SizeOf(arrBuffer)) then
begin
Socket.ReceiveBuf(arrBuffer,sizeof(arrBuffer));
BlockWrite(fileSave,arrBuffer,sizeof(arrBuffer));
m_Amount:=m_Amount+sizeof(arrBuffer);
Socket.SendText('Action');
end
else
begin
Socket.ReceiveBuf(arrBuffer,m_Remain);
BlockWrite(fileSave,arrBuffer,m_Remain);
CloseFile(fileSave);
end;
end;
end;

end.
 
看看以前的帖子把,里面讨论过这个问题N次了
把ClientSocket.Socket.SendText(IntToStr(m_Size));
放倒OnConnected事件理就OK了
 
-〉只有在Button点击了两次以后,文件才会传输;
第一次点击时执行到ClientSocket.Open;
不会执行ClientSocket.Socket.SendText(IntToStr(m_Size));
所以一次不会发生传输。应该把它放到OnConnected事件

如果将strReceive的位置放置于if语句上方,则每次有数据read时都要执行,所以会出现乱码。

另外if m_Legth<10 then的判断并不十分准确。

 
踏浪者,能告诉我一个比较好的判断文件长度的方法吗?我知道这个方法不是很好,我试过如果文本文件的长度是1024~1033时,会报错。谢谢!
 
建议不要用判断文件长度的方法--它不是一个满意的方法。
建议自定义一个信息格式,如定义自己的信息头或信息尾,这样判断比较准确规范。
 
踏浪者,能不能近一步说明如何定义这样的信息格式,最好给个例子,好吗?谢谢了!:-)
 
发文件的没试过,不过发字符串时,我会在串的最后加上一个结束标记,这样就能判断什么时候收完了!
 
我的方法是,在字符串头上加上长度,长度位元的长度是因定的,读取的时候,先读取长度.
 
呵呵,例子现在手头没有,看来你的分不好赚哦!你可以搜索一下其他的帖子或Google一下关于网络通讯的东东,我目前只能给两个思路:
1、简单的加个结束标志,通过判断结束标志即可。
2、定义一个信息格式,如: 信息头+信息内容+结束符
信息头形如:ABABAB----代表传文件大小;
CDCDCD----代表传文件实体。
注意:信息头的长度需要固定,如上面都等长。
 
谢谢大家,特别感谢踏浪者!
 
多人接受答案了。
 
后退
顶部