1.建立两个工程Server及Client
分别放TServerSocket及TClientSocket控件,Demo,Edit控件等。
2.设置TServerSocket name为 SS, ServerType为stNonBlocking,TClientSocket name为cs,ClientType为ctNonBlocking表示异步读写信息。注意ClientType和ServerType要相一致.若为ctBlocking则表示同步读写信息。
3.Socket传送文件的顺蚂型序图
a)Client-->Server MP_QUERY
b)Server-->Client MP_ACCEPT
c) Client-->Server MP_FileProperty
d)Server-->Client MP_NextWillBeData
e)Client-->Server MP_NextWillBeData
f)Server-->Client MP_DATA
g) Client-->Server 发送数据
h) Server接收数据并处理
i)Client-->Server MP_END结束
4.Client端代码-----------------------------------------------------------------------------------------------------------------
unit UnitClient
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, StdCtrls, Buttons, ExtCtrls, ComCtrls
Const
//设置协议标志符
//标志将要发送文件名
MP_QUERY ='aaaaa'
//标志服务器拒绝接收
MP_REFUSE ='bbbbb'
//标志服务器同意接收文件
MP_ACCEPT ='ccccc'
//标志将要传递数据
MP_NEXTWILLBEDATA='ddddd'
//标志改没服务器端准备核物纳接收数据
MP_DATA ='eeeee'
//标志客户端取消了本次发送 *** 作
MP_ABORT ='fffff'
//标志已经发送完毕
MP_END='iiiii'
//标志发送的文件长度
MP_FILEPROPERTY='jjjjj'
//指定每次发送包的大小
iBYTEPERSEND=1024
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog
cs: TClientSocket
Panel1: TPanel
btnSendFile: TBitBtn
edtIPAddress: TEdit
Memo1: TMemo
edtHostName: TEdit
RB1: TRadioButton
RB2: TRadioButton
ProBar: TProgressBar
Btncancel: TBitBtn
Btnexit: TBitBtn
procedure btnSendFileClick(Sender: TObject)
procedure csRead(Sender: TObjectSocket: TCustomWinSocket)
procedure FormCreate(Sender: TObject)
procedure BtncancelClick(Sender: TObject)
procedure BtnexitClick(Sender: TObject)
private
//定义一个发送文件的数据流
fsSend: TFileStream
//设置开始状态位
tStart:Boolean
//标识当前时间
TickCount:Longword
{ Private declarations }
public
{ Public declarations }
end
var
Form1: TForm1
implementation
{$R *.DFM}
//发送文件
procedure TForm1.btnSendFileClick(Sender: TObject)
begin
//关闭套接字连接
cs.Close
//初始化进程条
Probar.Position:=0
if RB1.Checked then
begin
cs.Host:=''
//指定要连接的主机IP地址
cs.Address:=edtIPAddress.Text
end
else
//指定要连接的主机名
cs.Host:=edtHostName.Text
//要连接的主机所用端口号
cs.Port:=2000
//打开套接字连接
cs.Open
//点击发送确认按钮
if OpenDialog1.Execute then
Begin
//发送连接请求
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName)
end
end
//客户端接收来自服务器端的信息
procedure TForm1.csRead(Sender: TObjectSocket: TCustomWinSocket)
var
MsgRecv:string
bufSend:pointer
iLength:Integer
begin
//得到客户端发来的信息
MsgRecv:=Socket.ReceiveText
//取前5位,得到协议标志符
MsgRecv:=copy(MsgRecv,1,5)
//接收到拒绝信息
if MsgRecv=MP_REFUSE then
memo1.Lines.Add('连接请求被拒绝!')
//接收到确认接收信息
else if MsgRecv=MP_ACCEPT then
begin
//为要发送的文件创建文件流
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead)
tStart:=False
//进度条显示
Probar.Max:=fsSend.Size
memo1.Lines.Add('开始发送!')
//获取发送开始时的时间
TickCount:=GetTickCount
//创建文件流并发送文件长度。
Socket.SendText(MP_FILEPROPERTY+inttostr(Trunc(fsSend.Size/iBYTEPERSEND)+1))
end
else if MsgRecv=MP_NEXTWILLBEDATA then
begin
//通知接收端将要传送数据。
Socket.SendText(MP_NEXTWILLBEDATA)
end
else if MsgRecv=MP_DATA then
begin
//接收到确认信息,开始发送数据。
if not tStart then
begin
memo1.Lines.Add('发送数据中... ...')
tStart:=True
end
//还有数据没有发送。
if fsSend.Position<fsSend.Size-1 then
begin
iLength:=fsSend.Size-1-fsSend.Position
//将数据分段发送
if iLength>iBYTEPERSEND then
iLength:=iBYTEPERSEND
GetMem(bufSend,iLength+1)
try
//读取文件流数据
fsSend.Read(bufSend^,iLength)
//发送长度为iLength的数据
Socket.SendBuf(bufSend^,iLength)
//进度条显示
Probar.Position:=fsSend.Position
finally
//释放内存
FreeMem(bufSend,iLength+1)
end
//发送完毕
end else
begin
//通知主机文件传送结束。
Socket.SendText(MP_END)
memo1.Lines.Add('发送完成!')
//获取发送耗时
memo1.Lines.Add('发送耗时'+IntToStr(GetTickCount-TickCount)+'毫秒')
fsSend.Free
end
//取消文件发送过程
end else if MsgRecv=MP_ABORT then
begin
memo1.Lines.Add('中止!')
//文件传送取消
fsSend.Free
end
end
procedure TForm1.FormCreate(Sender: TObject)
begin
Memo1.Clear
end
//取消
procedure TForm1.BtncancelClick(Sender: TObject)
begin
//取消文件发送过程
cs.Socket.SendText(MP_ABORT)
end
procedure TForm1.BtnexitClick(Sender: TObject)
begin
Form1.Close
end
end.
5.Server端代码------------------------------------------------------------------------------------------------
unit UnitServer
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ScktComp, ExtCtrls
Const
//设置协议标志符
//标志将要发送文件名
MP_QUERY ='aaaaa'
//标志服务器拒绝接收
MP_REFUSE ='bbbbb'
//标志服务器同意接收文件
MP_ACCEPT ='ccccc'
//标志将要传递数据
MP_NEXTWILLBEDATA='ddddd'
//标志服务器端准备接收数据
MP_DATA ='eeeee'
//标志客户端取消了本次发送 *** 作
MP_ABORT ='fffff'
//标志已经发送完毕
MP_END='iiiii'
//标志发送的文件长度
MP_FILEPROPERTY='jjjjj'
//指定每次发送包的大小
iBYTEPERSEND=1024
type
TForm1 = class(TForm)
SaveDialog1: TSaveDialog
ss: TServerSocket
Memo1: TMemo
procedure ssClientRead(Sender: TObjectSocket: TCustomWinSocket)
procedure FormCreate(Sender: TObject)
procedure FormDestroy(Sender: TObject)
private
//定义一个接收文件的数据流
fsRecv:TFileStream
//设置开始状态位
tStart:Boolean
//标识当前时间
TickCount:Longword
{ Private declarations }
public
{ Public declarations }
end
var
Form1: TForm1
implementation
{$R *.DFM}
//服务器端接收来自客户端的信息
procedure TForm1.ssClientRead(Sender: TObjectSocket: TCustomWinSocket)
var
msgr,theFileName:string
bufRecv:Pointer
iLength:Integer
begin
//接收到的数据的长度
iLength:=Socket.ReceiveLength
//开辟一块新的内存,用来保存接收到的数据
GetMem(bufRecv,iLength)
try
//接收数据
Socket.ReceiveBuf(bufRecv^,iLength)
//将接收到的数据以字符串的形式存到msgr中
msgr:=StrPas(PChar(bufRecv))
//取前5个字符
msgr:=Copy(msgr,1,5)
if msgr=MP_QUERY then
begin
//去掉字符串前后的空格和控制字符
msgr:=Trim(StrPas(PChar(bufRecv)))
//第5个字符后面的字符串为文件名
theFileName:=ExtractFileName(Copy(msgr,6,Length(msgr)))
SaveDialog1.Title:='请选择或输入接收到的数据保存到的文件名:'
SaveDialog1.FileName:=theFileName
//点击确认保存按钮
if SaveDialog1.Execute then
begin
//为需保存的文件创建文件流
fsRecv:=TFileStream.Create(SaveDialog1.FileName,fmCreate)
//如果同意接收数据。
memo1.Lines.Add ('开始接收!')
TickCount:=GetTickCount
//发送同意接收文件的信息
Socket.SendText(MP_ACCEPT)
tStart:=False
end
else
//发送拒绝接收文件的信息
Socket.SendText(MP_REFUSE)
end
else if msgr=MP_FILEPROPERTY then
begin
//接收文件长度并说明主机可以接收数据了
Socket.SendText(MP_NEXTWILLBEDATA)
end
else if msgr=MP_NEXTWILLBEDATA then
begin
//要求发送端发送数据
Socket.SendText(MP_DATA)
end else if msgr=MP_END then
begin
memo1.Lines.Add ('文件传送完成!')
memo1.Lines.Add ('接收耗时'+IntToStr(GetTickCount-TickCount)+'毫秒')
fsRecv.Free
end
//接收到文件传送取消信息
else if msgr=MP_ABORT then
begin
memo1.Lines.Add ('MP_ABORT')
Socket.SendText(MP_ABORT)
fsRecv.Free
end
else
begin
if not tStart then
begin
memo1.Lines.Add('接收数据...')
tStart:=True
end
//将接收缓冲区数据写入文件
fsRecv.WriteBuffer(bufRecv^,iLength)
//通知客户端继续发送数据
Socket.SendText(MP_DATA)
end
finally
//释放内存
FreeMem(bufRecv,iLength)
end
end
procedure TForm1.FormCreate(Sender: TObject)
begin
Memo1.Clear
//设置的监听端口
ss.Port:=2000
//开始监听
ss.Open
end
procedure TForm1.FormDestroy(Sender: TObject)
begin
ss.Close
end
end.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)