实验四扫描可控计算机的客户端和服务器端编程设计Word下载.docx
《实验四扫描可控计算机的客户端和服务器端编程设计Word下载.docx》由会员分享,可在线阅读,更多相关《实验四扫描可控计算机的客户端和服务器端编程设计Word下载.docx(30页珍藏版)》请在冰点文库上搜索。
4.在您希望包含WOSA支持吗?
下选中“Windows Sockets[W]”,按“完成”按钮。
你获得了一个工程框架。
图3
对话框中添加控件。
1.首先我们添加的控件是一个静态文本框。
选择工具箱中的静态文本控件(标注为Aa),然后再在对话框工作区按下鼠标左键并向右下移动,当你放开鼠标后,一个静态文本框就产生了,如图4 ,在此控件上右击鼠标,在弹出菜单中选择“属性“,点击属性,出现如1.5 的对话框。
你需要做的就是把”标题“右边白框中的文字改为你要写的文字,这时,你可以看到对话框中的文字已被改写了。
图4
图5
添加如图5这样的三个静态文本框,把“确定”按钮删除(使用“Delete”键),并把“撤销”按钮名字改为“关闭”(因为我们不对这些文本框进行操作,所以它们的ID不需要特别设置)。
在“接收端主机地址”的右边添加一个文本编辑框(标志位ab│),并把它的ID改为IDC_IP,如6
图6
在“接收端TCP端口号“右边添加一个文本编辑框,并把它的ID改为IDC_PORT,如图7 所示。
图7
在“选择所需发送的文件”下面添加一个新的树状控件(
),并把它的名字改为IDC_TREE,
用于引导你寻找到你要发送的文件。
如下图
图8
在可控计算机列表下方创建一个新的静态文本控件,IDC_TEXT_PROGRESS,如下图4.9
图9
在静态文本控件“发送进程”的下方添加一个进程控件(
)
在对话框中添加一个如下所示的按钮,其ID为IDC_PROGRESS
图10
在对话框中“接收端TCP”下方添加一个按钮(
),ID为IDC_SEND,标题为“发送选定文件”。
图11
最后的对话框设计视图应该如下图:
图12
现在,我们要添加代码,以处理对上述控件的响应。
首先把两个文件(DirTreeCtrl.h和DirTreeCtrl.cpp)复制到程序所在的目录(也就是
MyFileSender.dsw所在的目录)然后,双击“FileView”,在“MyFileSenderfiles”处右击鼠标,在弹出菜单中选择“添加文件到工程”,选择DirTreeCtrl.h和DirTreeCtrl.cpp,确定。
这时,此两个文件已经进入了工程。
图13
文件视图中(FileView),点开HeaderFiles(即头文件),找到MyFileSenderDlg.h并打开它。
先在文件的第一行插入下列语句,
#include"
DirTreeCtrl.h"
#include<
sys/timeb.h>
我们在CMyFileSenderDlg类中添加下列成员(代码添加在//Implementation的下一行):
//Implementation
public:
CStringm_strIP;
intm_port;
CStringm_strFilePath;
CDirTreeCtrlm_dir;
voidSendFile();
我们转动SourceFiles(即源文件),打开MyFileSenderDlg.cpp,为了能使得代码和对话框之间实现数据传递,我们必须要在函数CMyFileSenderDlg:
DoDataExchange中添加如下代码。
DDX_Control(pDX,IDC_TREE,m_dir);
DDX_Text(pDX,IDC_IP,m_strIP);
DDX_Text(pDX,IDC_PORT,m_port);
找到对话框的初始化函数OnInitDialog,在该函数的“//TODO:
Addextrainitializationhere”的下一行添加代码
//TODO:
Addextrainitializationhere
m_dir.Initialize();
//初始化目录树
m_port=8888;
m_strIP="
127.0.0.1"
UpdateData(FALSE);
((CProgressCtrl*)(GetDlgItem(IDC_PROGRESS)))->
SetRange(0,20);
GetDlgItem(IDC_PROGRESS)->
ShowWindow(SW_HIDE);
GetDlgItem(IDC_TEXT_PROGRESS)->
图14
我们回到ResourceView(资源视图),
我们还必须在函数CTeacherDlg:
OnSearch()中添加如下代码,以使得当我们按下“开始搜索”按钮后,程序能启动搜索。
双击“Dialog”,再双击IDD_MYFILESENDERDLG”,我们又回到了刚才设计的对话框,我们在对话框中双击“发送选定文件”按钮,在弹出的对话框中,点击OK,我们就来到了OnSend函数体。
图15
我们把下列代码插入到OnSend()函数体中//TODO:
Addyourcontrolnotificationhandlercodehere的下方。
HTREEITEMhItem=m_dir.GetSelectedItem();
//获得目录树中选中的条目
if(!
hItem)
{
MessageBox("
你尚未选择要发送的文件!
!
"
);
return;
}
if(m_dir.GetChildItem(hItem)!
=NULL)
不能发送目录.请选择文件!
m_strFilePath=m_dir.GetFullPath(hItem);
//获得选择的文件名
UpdateData(TRUE);
if(m_port<
0||m_port>
35565)
无效TCP端口号!
SendFile();
图16
最后,我们还需要在OnSend()函数的上一行插入函数voidCMyFileSenderDlg:
SendFile(),以实现文件的发送。
voidCMyFileSenderDlg:
SendFile()
{
structtimebtstart,tend;
SOCKETclientSocket;
//定义服务器端地址信息
structsockaddr_inserv;
//设置服务器地址信息
serv.sin_family=AF_INET;
serv.sin_port=htons(m_port);
//设置需连接的服务器的监听端口(必须与服务器端绑定的监听端口一致)
serv.sin_addr.s_addr=inet_addr((char*)(m_strIP.GetBuffer
(2)));
//此处应设置为服务器端的IP地址
//建立客户端socket
clientSocket=socket(AF_INET,SOCK_STREAM,0);
if(clientSocket==INVALID_SOCKET)
MessageBox("
建立socket出错!
NULL,MB_OK);
//请求与服务器建立TCP连接
if(connect(clientSocket,(structsockaddr*)&
serv,sizeof(serv))==INVALID_SOCKET)
服务器地址错误!
CFilefile;
intret=file.Open(m_strFilePath,CFile:
modeRead|CFile:
typeBinary);
if(ret==0)
读文件出错"
NULL,MB_OK);
CStringfilename=file.GetFileName();
intlength=file.GetLength();
send(clientSocket,filename,filename.GetLength(),0);
charflag[2];
recv(clientSocket,flag,sizeof(flag),0);
send(clientSocket,(char*)&
length,sizeof(length),0);
charbuf[1024]={0};
intnum=0;
intsentBytes=0;
ShowWindow(SW_SHOW);
ftime(&
tstart);
while(true)
memset(buf,0,sizeof(buf));
num=file.Read(buf,sizeof(buf));
if(num==0)break;
send(clientSocket,buf,num,0);
sentBytes+=num;
((CProgressCtrl*)(GetDlgItem(IDC_PROGRESS)))->
SetPos(20*sentBytes/length);
file.Close();
closesocket(clientSocket);
tend);
intelapseTime=tend.time*1000+tend.millitm-tstart.time*1000-tstart.millitm;
CStringreport;
report.Format("
文件发送完毕,在%d毫秒内传输了%d字节,传输速度%dBps"
elapseTime,length,length*1000/elapseTime);
MessageBox(report);
}
OnSend()
第二部分:
文件接收端的创建
3.启动VisualC++。
4.点击菜单左上方的文件-〉新建-〉工程
选择MFCAppWizard[exe],工程名称为MyFileReceiver,如下图,点击“确定”按钮
图17
图18
图19
方法如文件发送模块。
创建如下所示的对话框,添加静态文本(“选择用于接收文件的文件夹”,“设置用于接收文件的TCP端口”),添加一个树状控件(其ID设置为:
IDC_TREE),添加一个在文本“设置用于接收文件的TCP端口”右边的编辑框(其ID为IDC_PORT),删除“确定”按钮,添加一个按钮位于左下方的按钮(ID为IDC_RECEIVE,名称为“启动接收文件”),右下方的按钮(ID为IDCANCEL,名称为:
关闭)
图20
此外,我们要添加代码,以处理对上述控件的响应。
在对话框中双击“启动接收文件“按钮,出现下面的对话框,按下”OK“
图21
这时,你就来到了OnReceive()函数中,把下述代码插入到函数中去。
//TODO:
Addyourcontrolnotificationhandlercodehere
你尚未选择用于接受文件的文件夹!
if(m_dir.GetChildItem(hItem)==NULL)
请选择用于接受文件的文件夹!
1000||m_port>
AfxBeginThread(receiverThread,(LPVOID)this);
然后,在voidCMyFileReceiverDlg:
OnReceive()的上面添加下述代码,其实际是两个函数UINTreceiverThread(LPVOIDp),该函数创建了一个监听套接字,并能够不断地监听来自客户端的连接请求,然后通过Accept函数创建新的套接字,而新的套接字负责跟客户端进行信息的发送和接受(send,recv)以完成文件传输,另一个函数voidReceiveFile(SOCKETsock,CStringfileAddr,intlen)要被receiverThread调用,它的功能是使用类CFile对象来打开一个文件,然后一个一个分组地接收来此文件发送端的数据,依次放入文件,在文件接收结束后它负责把文件关闭以确保文件存入硬盘。
/*----------------------------------------------------------------
函数名:
ReceiveFile
属性:
自定义的成员函数
功能:
通过已建立的套接字循环接收文件内容,保存到指定地点
参数sock——接收数据的套接字
参数fileAddr——文件保存的带路径文件名
参数len——文件长度
------------------------------------------------------------------*/
voidReceiveFile(SOCKETsock,CStringfileAddr,intlen)
{
if(file.Open(fileAddr,CFile:
modeCreate|CFile:
modeWrite|CFile:
typeBinary,NULL)==0)
charbuf[1024]={0};
intnum;
while(len>
0){
num=recv(sock,buf,sizeof(buf),0);
file.SeekToEnd();
file.Write(buf,num);
len-=num;
}
file.Close();
UINTreceiverThread(LPVOIDp)
CMyFileReceiverDlg*pDlg=(CMyFileReceiverDlg*)p;
//定义两个socket变量,一个用来监听,一个用来建立连接和提供服务
SOCKETlistenSocket;
SOCKETdataSocket;
intret;
structsockaddr_inserv,client;
//将分别存储服务器端、客户端的IP地址和端口
listenSocket=socket(AF_INET,SOCK_STREAM,0);
if(listenSocket==INVALID_SOCKET)
pDlg->
MessageBox("
建立监听套接字出错"
return0;
serv.sin_port=htons(pDlg->
m_port);
//设置监听TCP端口
serv.sin_addr.s_addr=htonl(INADDR_ANY);
//默认本服务器的IP地址由主机提供
//将监听socket与服务器地址绑定
if(bind(listenSocket,(LPSOCKADDR)&
serv,sizeof(serv))==SOCKET_ERROR)
绑定服务器错误"
//开始监听
if(listen(listenSocket,5)==SOCKET_ERROR)
监听出错"
closesocket(listenSocket);
pDlg->
文件接受系统已经启动!
//下面的无限循环用于不断接受客户端的连接请求并作出响应
while
(1)
//接到客户端的请求并接受请求,分配新的套接字dataSocket用于跟客户端交流信息
dataSocket=accept(listenSocket,NULL,NULL);
if(dataSocket==INVALID_SOCKET)
{
pDlg->
建立连接出错"
break;
}
charstrRev[128]={0};
recv(dataSocket,strRev,sizeof(strRev),0);
send(dataSocket,"
ok"
2,0);
CStringstr=strRev;
CStringaddr=pDlg->
m_strFilePath+"
\\"
addr=addr+str;
intfLen;
recv(dataSocket,(char*)&
fLen,4,0);
//调用函数,接收文件内容,并保存到指定地点
ReceiveFile(dataSocket,addr,fLen);
closesocket(dataSocket);
//pDlg->
m_dir.SetRedraw();
m_dir.RedrawWindow();
m_dir.ExpandBranch(pDlg->
m_dir.GetSelectedItem());
文件接收完毕!
NULL,MB_OK);
closesocket(listenSocket);
return1;
首先把两个文件(DirTreeCtrl.h和DirTreeCtrl.cpp)拷贝到你的程序所在的目录(也就是
MyFileReceiver.dsw所在的目录)然后,双击“FileView”,在“MyFileReceiverfiles”处右击鼠标,在弹出菜单中选择“添加文件到工程”,选择DirTreeCtrl.h和DirTreeCtrl.cpp,确定。
这时,此两个文件已经进入了你的工程。
文件视图中(FileView),点开HeaderFiles(即头文件),找到MyFileReceiverDlg.h并打开它。
我们在CMyFileReceiverDlg类中添加下列成员(代码添加在//Implementation的下一行):
public:
CStringm_strFileP