請問DELPHI中的ClientSocket和ServerSocket的目的大概是什麼 |
答題得分者是:christie
|
faswei
一般會員 發表:4 回覆:3 積分:1 註冊:2010-04-02 發送簡訊給我 |
|
christie
資深會員 發表:30 回覆:299 積分:475 註冊:2005-03-25 發送簡訊給我 |
Delphi: ServerSocket,ClientSocket 範例
2008-05-09 16:20 Delphi TServerSocket,TClientSocket实现传送文件代码 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: TObject; Socket: 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: TObject; Socket: 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: TObject; Socket: 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: TObject; Socket: 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. 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/genispan/archive/2008/10/23/3132417.aspx --
------
What do we live for if not to make life less difficult for each other? |
faswei
一般會員 發表:4 回覆:3 積分:1 註冊:2010-04-02 發送簡訊給我 |
|
P.D.
版主 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |