服务器端:
unitServerFrm;
interface

uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,ComCtrls,StdCtrls,ExtCtrls,WinSock;
type
TfrmMain
=
class
(TForm)
Panel1:TPanel;
Label1:TLabel;
edtPort:TEdit;
Panel2:TPanel;
stabar:TStatusBar;
SaveDialog:TSaveDialog;
btnListen:TButton;
btnReceive:TButton;
btnStop:TButton;
btnExit:TButton;
procedureFormCreate(Sender:TObject);
procedurebtnExitClick(Sender:TObject);
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedurebtnListenClick(Sender:TObject);
procedurebtnReceiveClick(Sender:TObject);
procedurebtnStopClick(Sender:TObject);
private

...
{Privatedeclarations}
public

...
{Publicdeclarations}
StopTrans:Boolean;
//
是否停止传送开关
InTrans:Boolean;
//
表示正在接收文件
Server:TSocket;
//
定义服务器端的socket句柄
//
自定义过程接收文件
procedureRecvFile(FileName:String);
end;
var
frmMain:TfrmMain;
const
BlockLen
=
1024
*
4
;
implementation

...
{$R*.dfm}

proceduretfrmmain.RecvFile(FileName:String);
var
Ftrans:fileofByte;
Recelen:Integer;
Blockbuf:array[
0
..BlockLen
-
1
]ofByte;
RecvSocket:TSocket;
ra:Sockaddr_in;
ra_len:integer;
begin
ra_len:
=
sizeof
(ra);
Recvsocket:
=
accept(server,@ra,@ra_len);
assignFile(Ftrans,filename);
rewrite(ftrans);
stoptrans:
=
false
;
intrans:
=
true
;
recelen:
=
recv(recvsocket,Blockbuf,BlockLen,
0
);
while
(recelen
>
0
)and(notStopTrans)
do
begin
BlockWrite(Ftrans,Blockbuf[
0
],BlockLen);
application.ProcessMessages;
recelen:
=
recv(recvsocket,Blockbuf,Blocklen,
0
);
if
stoptransthen
begin
CloseFile(Ftrans);
CloseSocket(RecvSocket);
InTrans:
=
False;
MessageBox(Handle,
'
停止传输!
'
,
'
提示
'
,MB_OK);
EXIT;
END;
END;
//
关闭文件,接收的SOCKET
CloseFile(Ftrans);
Closesocket(recvsocket);
InTrans:
=
False;
if
(Recelen
=
SOCKET_ERROR)then
messagebox(handle,
'
传输异常终止!
'
,
'
提示
'
,MB_OK)
ELSE
MESSAGEBOX(HANDLE,
'
客户端已经关闭连接1,文件可能已经传送完毕了!
'
,
'
提示
'
,MB_OK);
end;
procedureTfrmMain.FormCreate(Sender:TObject);
var
aWSAData:TWSAData;
begin
if
WSAStartup($
0101
,aWSAData)
<>
0
then
raiseException.Create(
'
不能启动WinSock动态链接库
'
);
messageBox(Handle,aWSAdata.szDescription,
'
WinSock动态链接库版本
'
,mb_ok);

end;
procedureTfrmMain.btnExitClick(Sender:TObject);
begin
Close;
end;
procedureTfrmMain.FormClose(Sender:TObject;varAction:TCloseAction);
begin
if
InTransthen
if
MessageBox(handle,
'
正在接收文件,停止吗?
'
,
'
提示
'
,MB_YESNO)
=
IDNOthen
abort;
IFSERVER
<>
INVALID_SOCKETTHEN
CLOSESOCKET(SERVER);
//
释放winsock动态链接库所创建的资源
if
WSACleanup
<>
0
then
messagebox(handle,
'
清除Winsock动态链接库错误!
'
,
'
提示
'
,MB_OK)
ELSE
messagebox(handle,
'
清除Winsock动态链接库成功!
'
,
'
提示
'
,MB_OK);
end;
procedureTfrmMain.btnListenClick(Sender:TObject);
var
ca:SOCKADDR_IN;
begin
//
创建服务器端SOCKET
Server:
=
Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
IFserver
=
invalid_socketthen
begin
stabar.SimpleText:
=
'
创建接收SOCKET错误1
'
;
exit;
end;
//
绑定服务器端SOCKET
ca.sin_family:
=
PF_INET;
CA.sin_port:
=
htons(strtoint(trim(edtPort.Text)));
ca.sin_addr.S_addr:
=
INADDR_ANY;
if
bind(server,ca,
sizeof
(ca))
=
socket_errorthen
begin
stabar.SimpleText:
=
'
绑定socket错误,请更改接收端口
'
;
closeSocket(server);
exit;
end
else
stabar.SimpleText:
=
'
绑定接收端socket成功!
'
;
//
开始监听
listen(server,
5
);
btnlisten.Enabled:
=
False;
btnstop.Enabled:
=
true
;
end;
procedureTfrmMain.btnReceiveClick(Sender:TObject);
begin
if
(server
=
INVALID_SOCKET)THEN
BEGIN
MESSAGEBOX(HANDLE,
'
还没有进行监听,请先进行监听!
'
,
'
提示
'
,MB_OK);
EXIT;
END;
IFSaveDialog.ExecuteTHEN
RECVFILE(SaveDialog.FileName);
end;
procedureTfrmMain.btnStopClick(Sender:TObject);
begin
STOPTRANS:
=
TRUE;
IFSERVER
<>
INVALID_SOCKETTHENcLOSESOCKET(SERVER);
//
此处需要说明
server:
=
INVALID_SOCKET;
bTNSTOP.Enabled:
=
fALSE;
BTNlISTEN.Enabled:
=
TRUE;
end;
end.
客户端:
unitClientFrm;
interface

uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,StdCtrls,ComCtrls,WinSock;
type
TfrmMain
=
class
(TForm)
opendfile:TOpenDialog;
Label1:TLabel;
edtIP:TEdit;
Label2:TLabel;
edtPort:TEdit;
StatusBar:TStatusBar;
btnConnect:TButton;
btnSend:TButton;
btnStop:TButton;
btnExit:TButton;
ProgressBar:TProgressBar;
procedureFormCreate(Sender:TObject);
procedurebtnExitClick(Sender:TObject);
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedurebtnConnectClick(Sender:TObject);
procedurebtnSendClick(Sender:TObject);
procedurebtnStopClick(Sender:TObject);
private

...
{Privatedeclarations}
Client:TSocket;
public

...
{Publicdeclarations}
StopTrans:Boolean;
//
是否停止发送的开发
InTrans:Boolean;
//
表示是否正在传送文件
procedureTransFile(FileName:String);
//
传递文件的过程
end;
const
BlockLen
=
1024
*
4
;
//
每次发送的最大数据量
var
frmMain:TfrmMain;
implementation

...
{$R*.dfm}

procedureTfrmMain.TransFile(FileName:String);
//
传递文件的过程
var
Ftrans:fileofByte;
Flen:integer;
BlockNum,RemainLen:integer;
BlockBuf:array[
0
..BlockLen
-
1
]ofByte;
i:integer;
SendLen:Integer;
begin
assignFile(Ftrans,filename);
reset(Ftrans);
Flen:
=
FileSize(Ftrans);
BlockNum:
=
FlendivBlockLen;
progressBar.Max:
=
1
+
BlockNum;
RemainLen:
=
FlenmodBlockLen;
StopTrans:
=
False;
InTrans:
=
True;
SendLen:
=
1
;
for
i:
=
0
toBlockNum
-
1
do
begin
if
(StopTrans)or(SendLen
<=
0
)thenBreak;
BlockRead(Ftrans,Blockbuf[
0
],BlockLen);
SendLen:
=
Send(Client,Blockbuf,BlockLen,
0
);
ProgressBar.Position:
=
i;
Application.processMessages;
end;
if
StopTransthen
begin
CloseFile(Ftrans);
InTrans:
=
False;
StatusBar.SimpleText:
=
''
;
MessageBox(Handle,
'
停止传输!
'
,
'
提示
'
,mb_ok);
progressbar.Position:
=
0
;
exit;
end;
if
(SendLen
<=
0
)then
begin
CloseFile(Ftrans);
InTrans:
=
False;
StatusBar.SimpleText:
=
''
;
messagebox(handle,
'
传出异常终止!
'
,
'
提示
'
,MB_OK);
progressBar.Position:
=
0
;
exit;
end;
if
remainLen
>
0
then
begin
BlockRead(Ftrans,BlockBuf[
0
],RemainLen);
SendLen:
=
send(client,BlockBuf,Remainlen,
0
);
if
(sendLen
<=
0
)then
begin
closeFile(Ftrans);
InTrans:
=
False;
StatusBar.SimpleText:
=
''
;
messagebox(handle,
'
传输异常终止!
'
,
'
提示
'
,mb_ok);
progressBar.Position:
=
0
;
exit;
end;
end;
progressBar.Position:
=
ProgressBar.Max;
CloseFile(Ftrans);
InTrans:
=
False;
StatusBar.SimpleText:
=
''
;
messagebox(handle,
'
传输完成!
'
,
'
提示
'
,mb_ok);
progressbar.Position:
=
0
;
end;

procedureTfrmMain.FormCreate(Sender:TObject);
var
aWSAData:TWSAData;
begin
if
WSAStartup($
0101
,aWSAData)
<>
0
then
raiseException.Create(
'
不能启动WinSock动态链接库
'
);
messageBox(Handle,aWSAdata.szDescription,
'
WinSock动态链接库版本
'
,mb_ok);

end;
procedureTfrmMain.btnExitClick(Sender:TObject);
begin
Close;
end;
procedureTfrmMain.FormClose(Sender:TObject;varAction:TCloseAction);
begin
if
InTransthen
if
MessageBox(handle,
'
正在传输文件,停止吗?
'
,
'
提示
'
,MB_YESNO)
=
IDNOthen
abort;
//
释放winsock动态链接库所创建的资源
if
WSACleanup
<>
0
then
messagebox(handle,
'
清除Winsock动态链接库错误!
'
,
'
提示
'
,MB_OK)
ELSE
messagebox(handle,
'
清除Winsock动态链接库成功!
'
,
'
提示
'
,MB_OK);
CloseSocket(Client);
end;
procedureTfrmMain.btnConnectClick(Sender:TObject);
var
ca:SOCKADDR_IN;
hostaddr:u_long;
begin
Client:
=
Socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
IFCLIENT
=
INVALID_SOCKETTHEN
BEGIN
StatusBar.SimpleText:
=
'
为连接远程服务器端创建COSKET错误!
'
;
exit;
end;
ca.sin_family:
=
PF_INET;
CA.sin_port:
=
HTONS(STRTOINT(TRIM(EDTpORT.Text)));
HOSTADDR:
=
INET_ADDR(PCHAR(TRIM(EDTIP.Text)));
//
判断IP是否合法
if
(hostaddr
=
-
1
)then
begin
StatusBar.SimpleText:
=
'
主机IP地址:
'
+
trim(edtip.Text)
+
'
错误
'
;
exit;
end
else
ca.sin_addr.S_addr:
=
hostaddr;
//
连接服务器
本文介绍了一个使用 WinSock 的应用程序实例,该程序包括客户端和服务端两部分,能够实现文件的双向传输。服务端负责监听并接收来自客户端的文件,而客户端则用于选择本地文件并发送到指定的服务端。

5063

被折叠的 条评论
为什么被折叠?



