Delphi实例分析:远程传输数据和文件
在Windows操作系统的平台上,WinSock是首选的网络编程接口,用于在网络上传输数据和交换信息,它构成了Windows操作系统进行网络编程的基础。对于编写网络应用程序来说,WinSock是一门非常重要的并且必须掌握的知识,虽然现在有很多的工具如FTP程序可以在网络上传输数据和文件,但是通过WinSock编程具有更大的灵活性,因为它不需要关心网络连接的细节问题。然而用WinSock编程却相当复杂,但是在Delphi中我们并不需要直接与WinSock的API函数打交道,因在Delphi中的TClientSocket组件和TServerSocket组件封装了WinSock的大部分API函数,使得对WinSock的编程大大简化。在网络通信协议的面向连接服务中,进行传输数据和交换信息之前,通信双方应该建立一条用于进行数据交换的“链路”,通信双方就是利用这个“链路”进行稳定可靠的数据传输,由于建立通信的双方都处于收发信息的状态,并且保证了数据传输的稳定性,所以在传输较大的文件时,具有较高的效率。而建立“链路”和断掉“链路”都需要消耗一定的时间,所以在传输较小文件时的效率是比较低的。
在这里我们将了解winsock如何实现远程传输数据和文件。在一个局域网内不同的计算机上分别运行服务器端程序和客户端程序。服务器端运行后就启动,socket将建立侦听状态。客户端运行后,在客户端程序中填写服务器IP地址,然后单击“连接”按钮,向服务器端发出一个建立连接的请求,如图1所示。如果通客户端程序过端口成功和服务器端连接,服务器端的状态栏就会有“已和客户端连接”的提示,并准备传输文件,如图2所示。

图1

图2
单击“发送”按钮,在弹出的对话框中选择一个准备发送的文件,然后客户端将文件的大小和其他信息等发送到服务器端,服务器端接受到文件的信息后通知客户端开始传送文件,文件的数据需要多次传递,服务器将文件全部接受并保存。系统运行如图3、图4所示:

图3

图4
服务器端程序编写:
新建一个项目,并把一个TServerSocket组件放到Form1窗体上,Active设为True;端口Port设为2000,其它属性按默认值。服务器端程序代码如下:
unit Unit1;
interface
uses
Windows,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ComCtrls, DB, DBTables, XPMan;
Const
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA ='4';
MP_DATA ='5';
MP_ABORT
='6';
MP_OVER ='7';
MP_CHAT ='8';
MP_END ='9';
MP_FILEPROPERTY ='0';
iBYTEPERSEND=1024;
type
TForm1 = class(TForm)
Serversocket: TServerSocket;
Query1: TQuery;
GroupBox1: TGroupBox;
Memo1:
TMemo;
XPManifest1: TXPManifest;
StatusBar1: TStatusBar;
Button1: TButton;
procedure
serversocketClientConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure serversocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
procedure serversocketClientError(Sender: TObject; Socket:
TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure Button1Click(Sender: TObject);
procedure
FormCreate(Sender: TObject);
private
fsRecv:TMemoryStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
bReadText:boolean;
implementation
{$R
*.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Serversocket.Port:=2000;//设置侦听端口为2000;
bReadText:= true;
Serversocket.Open;
StatusBar1.SimpleText:=' 就绪 ';
end;
procedure
TForm1.ServersocketClientConnect(Sender: TObject;
Socket:
TCustomWinSocket);
begin
Statusbar1.SimpleText:=' 已和IP地址为
'+Socket.RemoteAddress+' 客户端连接 ';
end;
procedure
TForm1.serversocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
sTemp ,existfile, newfile : string;
bufRecv:Pointer;
iNum:integer;
begin
Memo1.Lines.Add('received size :' + intToStr(Socket.ReceiveLength));
if bReadText then
begin
sTemp:=Socket.ReceiveText;
case sTemp[1] of
MP_QUERY:
begin
Memo1.Lines.Add('receive MP_QUERY');
existfile:=Copy(sTemp,2,Length(STemp)); ;
newfile:=
'c:\Administrator\'+ExtractFileName(existfile);
copyfile(pchar(existfile),pchar(newfile),false);
serversocket.Socket.Connections[0].SendText(MP_ACCEPT);
fsRecv := TMemoryStream.Create;
serversocket.Socket.Connections[0].SendText(MP_REFUSE+'');
end;
MP_FILEPROPERTY:
begin
Memo1.Lines.Add('receive
MP_FILEPROPERTY');
serversocket.Socket.Connections[0].SendText(MP_NEXTWILLBEDATA);
end;
MP_NEXTWILLBEDATA:
begin
Memo1.Lines.Add('receive MP_NEXTWILLBEDATA');
bReadText:=false;
serversocket.Socket.Connections[0].SendText(MP_DATA);
end;
MP_END:
begin
Memo1.Lines.Add('receive
MP_END');
fsRecv.Free;
bReadText:=true;
end;
MP_ABORT:
begin
Memo1.Lines.Add('receive
MP_ABORT');
fsRecv.Free;
bReadText:=true;
end;
MP_CHAT:
begin
Memo1.Lines.Add('receive
MP_CHAT');
end;
end;{of case}
end
else
begin
try
GetMem(bufRecv,
iBYTEPERSEND);
iNum := Socket.ReceiveBuf(bufRecv^, iBYTEPERSEND);
fsRecv.WriteBuffer(bufRecv^, iNum);
finally
FreeMem(bufRecv);
end;{of try}
bReadText:=true;
if iNum = iBYTEPERSEND THEN
begin
serversocket.Socket.Connections[0].SendText(MP_NEXTWILLBEDATA);
end
else
begin
fsRecv.Free;
serversocket.Socket.Connections[0].SendText(MP_END);
end;
end;
end;
procedure TForm1.serversocketClientError(Sender:
TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var
ErrorCode: Integer);
begin
Memo1.Lines.Add('ErrorCode :' +
IntToStr(ErrorCode));
ErrorCode := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i, j: integer;
begin
J :=
serversocket.Socket.ActiveConnections;
Memo1.Lines.Add('ActiveConnectiong is ' + inttostr(j));
end;
end.
客户端程序编写:
新建一个工程,并把一个TClientSocket组件放到Form1窗体上,Port设为2000(端口号可任意设置,要求客户端和服务器端统一),其它属性按默认值。具体客户端程序代码如下:
unit Unit2;
interface
uses
Windows,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ComCtrls, XPMan;
const
MP_QUERY ='1';
MP_REFUSE ='2';
MP_ACCEPT ='3';
MP_NEXTWILLBEDATA='4';
MP_DATA ='5';
MP_ABORT ='6';
MP_OVER ='7';
MP_CHAT ='8';
MP_END ='9';
MP_FILEPROPERTY ='0';
iBYTEPERSEND=1024;
type
TForm1 = class(TForm)
cs: TClientSocket;
OpenDialog1: TOpenDialog;
StatusBar1: TStatusBar;
GroupBox1: TGroupBox;
edtIPAddress: TEdit;
Edit2: TEdit;
btnSendFile: TButton;
btnConnect: TButton;
XPManifest1: TXPManifest;
GroupBox2: TGroupBox;
Label1: TLabel;
edtSize: TEdit;
Memo1: TMemo;
procedure btnConnectClick(Sender: TObject);
procedure
btnSendFileClick(Sender: TObject);
procedure FormCreate(Sender:
TObject);
procedure csRead(Sender: TObject; Socket:
TCustomWinSocket);
private
fsSend:TFileStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure
TForm1.btnConnectClick(Sender: TObject);
begin
cs.Address
:= edtIPAddress.Text;
cs.Port:=2000;
cs.Open;
end;
procedure TForm1.btnSendFileClick(Sender: TObject);
begin
if OpenDialog1.Execute then
Begin
cs.Socket.SendText(MP_QUERY+OpenDialog1.FileName);
end;
end;
procedure TForm1.FormCreate(Sender:
TObject);
begin
edtipaddress.Text:='127.0.0.1';
end;
procedure TForm1.csRead(Sender: TObject;
Socket: TCustomWinSocket);
var
sRecv:string;
iNum:integer;
bufSend:pointer;
begin
sRecv:=Socket.ReceiveText;
Memo1.Lines.Add('sRecv =' + sRecv);
Case sRecv[1] of
MP_REFUSE:ShowMessage('Faint,be
refused!');
MP_ACCEPT:begin
Memo1.Lines.Add('MP_ACCEPT');
fsSend:=TFileStream.Create(OpenDialog1.FileName,fmOpenRead);
edtSize.Text:=IntToStr(fsSend.Size);
edit2.text:='total
count:'+IntToStr(Trunc(fsSend.Size/iBYTEPERSEND)+1);
cs.Socket.SendText(MP_FILEPROPERTY+IntToStr(Trunc(fsSend.Size/iBYTEPERSEND)+1));
fsSend.Seek(0, soFromBeginning);
end;
MP_NEXTWILLBEDATA:begin
Memo1.Lines.Add('MP_NEXTWILLBEDATA');
Socket.SendText(MP_NEXTWILLBEDATA);
end;
MP_DATA:
begin
Memo1.Lines.Add('MP_DATA');
try
GetMem(bufSend, iBYTEPERSEND);
iNum :=
fsSend.Read(bufSend^, iBYTEPERSEND);
cs.Socket.SendBuf(bufSend^,
iNum);
Memo1.Lines.Add('Send Buf finished');
finally
FreeMem(bufSend);
end;{of try}
end;
MP_END:
begin
Memo1.Lines.Add('MP_END');
fsSend.Free;
end;
MP_ABORT:begin
Memo1.Lines.Add('MP_ABORT');
fsSend.Free;
end;
end;
end;
end.
Delphi实例分析:远程传输数据和文件的更多相关文章
- GO语言文件的创建与打开实例分析
本文实例分析了GO语言文件的创建与打开用法.分享给大家供大家参考.具体分析如下: 文件操作是个很重要的话题,使用也非常频繁,熟悉如何操作文件是必不可少的.Golang 对文件的支持是在 os pack ...
- 实例分析ELF文件静态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第4章 静态链接 开发平台: [thm@tanghuimin static_link]$ uname ...
- HTTP的上传文件实例分析
这个是http文件传输的一种格式,当时不知道这种格式,废弃. HTTP的上传文件实例分析 由于论坛不支持Word写文章发帖. 首先就是附件发送怎么搞,这个必须解决.论坛是php的.我用Chrome类浏 ...
- RPC原理及RPC实例分析
在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 1 2 3 4 5 6 public class ...
- Linux系统网络性能实例分析
由于TCP/IP是使用最普遍的Internet协议,下面只集中讨论TCP/IP 栈和以太网(Ethernet).术语 LinuxTCP/IP栈和 Linux网络栈可互换使用,因为 TCP/IP栈是 L ...
- RPC-原理及RPC实例分析
还有就是:RPC支持的BIO,NIO的理解 (1)BIO: Blocking IO;同步阻塞: (2)NIO:Non-Blocking IO, 同步非阻塞; 参考:IO多路复用,同步,异步,阻塞和非阻 ...
- gpgpu-sim卡分配程序设计实例分析
gpgpu-sim卡分配程序设计实例分析 运行代码地址:https://github.com/gpgpu-sim/gpgpu-sim_distribution 一.概述 此文件包含有关安装.生成和运行 ...
- RPC原理及RPC实例分析(转)
出处:https://my.oschina.net/hosee/blog/711632 在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服 ...
- angular源码分析:injector.js文件分析——angular中的依赖注入式如何实现的(续)
昨天晚上写完angular源码分析:angular中jqLite的实现--你可以丢掉jQuery了,给今天定了一个题angular源码分析:injector.js文件,以及angular的加载流程,但 ...
随机推荐
- LCT摘要
介绍.用途 LCT是树链剖分中的一种,又叫实链剖分.动态树,常用于维护动态的树.森林. 维护方式 LCT并不直接维护原树,而是用一堆splay作为辅助树来维护.原树中的一条实链上的点在一棵splay中 ...
- SSH2框架搭建 和 配置文件详解
-----------补充说明----------- 文章中所列出的struts2的2.2jar包已经不是最新的了,这个版本有严重漏洞, 现在最新版本为2.3.15,所以.你懂的http://stru ...
- Demo005 小学四则运算自动生成程序
目录 小学四则运算自动生成程序 0.传送门 1.题目要求 2.功能实现 2.1 总体设计 2.2 用户欢迎界面 2.3 用户功能界面 2.4 屏幕输出 2.5 文本输出 2.6 获取时间 2.7 用户 ...
- [转]Mahout推荐算法API详解
Mahout推荐算法API详解 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeepe ...
- CF1064A 【Make a triangle!】
要让这个三角形合法,只需满足三角形不等式 即$a+b>c$,设$c=max\left\{a,b,c\right\}$,上式转化为$c<a+b$ 如果已经满足,不需消耗代价 否则消耗$c-a ...
- docker 的简单操作
一直说更博,但是一直在delay.... 最近一直用到docker,所以就总结一下吧! docker的介绍 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. ...
- mkfs
mkfs 命令 linux格式化磁盘命令 指令:mkfs 使用权限 : 超级使用者 使用方式 : mkfs [-V] [-t fstype] [fs-options] filesys [blocks ...
- 记一些使用PyQt的问题
本文自用,日常记录,不断更新 环境 1.使用 PyCharm IDE 2.PyQt5 3. 扩展配置 PyUIC转换后的代码处理 PyUIC 用于 将 QtDesigner 生成的 .ui 文件转换为 ...
- ***文件上传控件bootstrap-fileinput的使用和参数配置说明
特别注意: 引入所需文件后页面刷新查看样式奇怪,浏览器提示错误等,可能是因为js.css文件的引用顺序问题,zh.js需要在fileinput.js后面引入.bootstrap最好在filein ...
- Vue开源
Vue开源 - 为移动而生的Vue JS 2组件框架 vonic ★1494 - 快速构建移动端单页应用 eme ★1390 - 优雅的Markdown编辑器 vue-multiselect ★116 ...