局域网文件传输及消息发送.docx
《局域网文件传输及消息发送.docx》由会员分享,可在线阅读,更多相关《局域网文件传输及消息发送.docx(35页珍藏版)》请在冰点文库上搜索。
局域网文件传输及消息发送
《网络程序设计》
课程设计报告书
题目:
局域网文件传输与消息通信
专业:
网络工程
学号:
20091423
学生姓名:
史政法
指导教师:
魏宁
完成日期:
2012年06月06日
一、题目及要求
Window程序设计的基本要求:
1.熟练掌握网络的基本概念和原理;
2.熟练掌握网络编程接口Socket概念及编程原理;
3.掌握基于TCP/IP的Internet编程技术;
4.掌握各种软件开发工具的使用过程及方法。
本实例程序的技术要点是:
●如何从CasyncSocket类派生出自己的WinSock类。
●理解WinSock类与应用程序框架的关系。
●重点学习流式套接字对象的使用。
●处理网络事件的方法。
二、系统概要设计
1、CSocket类的介绍
在MFC中,为了提供面向对象的编程方式而封装了两个WinSock类:
一个是CAsyncSocket类,另一个是CSocket类。
他们的不同点在于前者使用的是非阻塞模式操作,而后者可以支持阻塞模式的I/O操作。
CSocket类是从CAsyncSocket类中继承来的,他为程序员提供了更高级的抽象性。
由于CSocket类和CArchive类一起使用,并且管理了通讯的大多数操作,从而使程序员从网络编程的底层细节中解脱了出来,不必使用CAsyncSocket的一些成员函数和一些WindowsSocketAPI函数来处理通信问题。
共同使用CSocket和CArchive类对象进行编程是最简单的WinSock编程模式。
下面是使用CSocket类进行网络通信的过程
(1)构造CSocket类对象
(2)用CSocket类对象的Create函数创建WindowsSocket,Create()函数会调用Bind()函数将此函数绑定的指定的地址和端口。
(3)Socket创建完毕后,Listen()函数在服务器端进行监听客户的连接请求。
(4)在这一步,服务器端调用Accept()函数对客户端发来的请求进行接受和处理,而客户端则调用Connect()函数向服务器发出连接请求。
(5)在客户端和服务器端的数据传输完成后,应该分别在两边销毁创建的CSocket对象。
2、编程思路和工程实现
用MFCAppWizard新建一个给予对话框的工程,在第三步中添加WindowsSocketS的支持,建立的程序界面如右图:
图1—-程序主对话框中的控件属性
图2—-对话框中的控件对象定义相应的成员变量
编程思路:
首先在对话框中输入要连接的IP地址,然后单击“启动”按钮,要连接的主机也做相同的操作,两边都准备完事后,两台计算机就可以消息和文件的传输了。
单击“启动”按钮时,处理函数启动了监听线程来启动服务,主要的语句如下:
pThreadListen=:
:
AfxBeginThread(_ListenTcpThread,this);
点击“发送消息”按钮时,处理函数启动了消息发送线程来进行消息的传送,语句如下:
pThreadSendMsg=:
:
AfxBeginThread(_SendMsgThread,this);
当点击“传送文件”按钮时,处理函数启动了文件传输线程来进行文件传输,语句如下:
pThreadSendMsg=:
:
AfxBeginThread(_SendFileThread,this);
下面主要介绍一下要用到的三个线程和一个文件接收处理函数。
首先要产生三个线程对象:
CWinThread_ListenTcpThread;
CWinThread_SendFileThread;
CWinThread_SendMsgThread;
三、系统详细设计
1.监听线程函数
UINT_ListenTcpThread(LPVOIDlparam)
{
CFiletranDlg*pDlg=(CFiletranDlg*)lparam;
if(pDlg->StopServer==true)return-1;
CSocketsockSrvr;
pDlg->m_Potr=PORT;//保存当前使用端口,用于关闭
intcreateSucceed=sockSrvr.Create(pDlg->m_Potr);
if(createSucceed==0)
{
AfxMessageBox("_ListenTcpThreadCreate错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
intlistenSucceed=sockSrvr.Listen();//开始监听
if(listenSucceed==0)
{
AfxMessageBox("_ListenTcpThreadListen错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
CSocketrecSo;
SOCKADDR_INclient;
intiAddrSize=sizeof(client);
intacceptSucceed=sockSrvr.Accept(recSo,(SOCKADDR*)&client,&iAddrSize);//接受连接并取得对方IP
if(acceptSucceed==0)
{
AfxMessageBox("_ListenTcpThreadAccept错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
sockSrvr.Close();//关闭
charflag[FLAG]={0};
if(recSo.Receive(flag,FLAG)!
=2)
{
return-1;
}
pDlg->m_type=flag[0];
if(pDlg->m_type=='D')return0;
pThreadListen=:
:
AfxBeginThread(_ListenTcpThread,pDlg);
pDlg->ReceiveFileMsg(recSo,client);
return0;
}
2.传送文件线程函数
UINT_SendFileThread(LPVOIDlparam)
{
CFiletranDlg*pDlg=(CFiletranDlg*)lparam;
if(pDlg->StopServer==true)return-1;
CSocketsockClient;
sockClient.Create();
CStringip;
pDlg->m_YourIp.GetWindowText(ip);
sockClient.Connect(ip,PORT);
//首先发送标记F为文件,2
intend=0;
end=sockClient.Send("F",FLAG);
///////////////////////////////////////////////////////////////////发送标志是否成功
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThreadSend错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
elseif(end!
=2)
{
AfxMessageBox("文件头错误");
return-1;
}
///////////////////////////////////////////////////////////////////
CFilemyFile;
FILEINFOmyFileInfo;
if(!
myFile.Open(pDlg->m_fileName,CFile:
:
modeRead|CFile:
:
typeBinary))
return-1;
myFileInfo.fileLength=myFile.GetLength();//得到文件大小
strcpy(myFileInfo.fileName,myFile.GetFileName());//得到文件名称
sockClient.Send(&myFileInfo,sizeof(myFileInfo));//发送文件信息
pDlg->m_Progress.SetRange32(0,myFileInfo.fileLength);
myFile.Seek(0,CFile:
:
begin);
charm_buf[SIZEFILE]={0};
CStringstrError;
intnum=0;
end=0;
inttemp=0;
for(;;)
{
if(pDlg->FileWork==false)
{
pDlg->FileWork=true;
pDlg->GetDlgItem(IDCANCEL)->EnableWindow(false);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
}
num=myFile.Read(m_buf,SIZEFILE);
if(num==0)break;
end=sockClient.Send(m_buf,num);
temp+=end;
pDlg->m_Progress.SetPos(temp);
if(pDlg->FileStop==true)
{
pDlg->FileStop=false;
pDlg->FileWork=false;
break;
}
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendFileThreadSend错误!
"+pDlg->GetError(GetLastError()));
break;
}
}
pDlg->m_Progress.SetPos(0);
CStringstrLocalName;
pDlg->GetLocalHostName(strLocalName);
CStringstrLocalIP;
pDlg->GetIpAddress(strLocalName,strLocalIP);
if(temp==myFileInfo.fileLength)
AfxMessageBox("文件发送成功");
else
AfxMessageBox("文件发送失败");
myFile.Close();
sockClient.Close();
pDlg->FileWork=false;
pDlg->GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
pDlg->GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(false);
pDlg->GetDlgItem(IDCANCEL)->EnableWindow(true);
pDlg->GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
return0;
}
3.发送消息线程函数
UINT_SendMsgThread(LPVOIDlparam)//TCP发送信息线程
{
CFiletranDlg*pDlg=(CFiletranDlg*)lparam;
if(pDlg->StopServer==true)return-1;
CSocketsockClient;
sockClient.Create();
CStringip,strError;
pDlg->m_YourIp.GetWindowText(ip);
intconn=sockClient.Connect(ip,PORT);
if(conn==0)///////////////////////////////////
{
AfxMessageBox("_SendMsgThreadConnect错误!
"+pDlg->GetError(GetLastError()));
sockClient.ShutDown
(2);
sockClient.Close();
AfxEndThread(1L);
return0;
}
//首先发送标记M为信息,2
intend=0;
end=sockClient.Send("M",FLAG);
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendMsgThreadSend错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
elseif(end!
=2)
{
AfxMessageBox("消息头错误");
return-1;
}
CStringstrMsg=pDlg->message;
end=sockClient.Send(strMsg,strMsg.GetLength());
if(end==SOCKET_ERROR)
{
AfxMessageBox("_SendMsgThreadSend错误!
"+pDlg->GetError(GetLastError()));
return-1;
}
inti=0;
sockClient.Close();
return0;
}
4.文件接收处理函数
intCFiletranDlg:
:
SaveYourFile(CSocket&recSo,SOCKADDR_IN&client)
{
CStringfname;
CFileDialogdlg(false);//另存文件
FILEINFOmyFileInfo;
recSo.Receive(&myFileInfo,sizeof(FILEINFO));
intfileLength=myFileInfo.fileLength;
CStringstrfileIp,strfileName,strfileLength;
strfileIp.Format(inet_ntoa(client.sin_addr));
strfileName.Format(myFileInfo.fileName);
strfileLength.Format("%f",myFileInfo.fileLength/1024.0);
CStringtitle="文件"+strfileName+"大小"+strfileLength+"KB"+"来在"+strfileIp+"是否接受";
dlg.m_ofn.lpstrTitle=title;//标题条
charfileme[500]={0};//必须足够大小
strcpy(fileme,strfileIp+strfileName);
dlg.m_ofn.lpstrFile=fileme;//文件名称
if(dlg.DoModal()==IDOK)
{
fname=dlg.GetPathName();//得到文件名名称、路径
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_SHOW);
}
else
{
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
GetDlgItem(IDCANCEL)->EnableWindow(true);
recSo.Close();
return0;
}
charbuf[SIZEFILE]={0};
CFilef(fname,CFile:
:
modeCreate|CFile:
:
modeWrite);//存文件
m_Progress.SetRange32(0,fileLength);
intn=0;//接受的字节数0表示结束
inttemp=0;
GetDlgItem(IDCANCEL)->EnableWindow(false);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(false);
for(;;)
{
n=recSo.Receive(buf,SIZEFILE);//接受
if(n==0)//0表示结束
break;//接受完毕
f.Write(buf,n);
temp+=n;
m_Progress.SetPos(temp);
if(FileWork==false)FileWork=true;
if(FileStop==true)
{
FileStop=false;
FileWork=false;
break;
}
}
f.Close();
m_Progress.SetPos(0);
if(temp==fileLength)
MessageBox("文件接受成功");
else
MessageBox("文件接受失败");
FileWork=false;
GetDlgItem(IDC_PROGRESS_SEND_FILE)->ShowWindow(SW_HIDE);
GetDlgItem(IDC_BUTTON_STOP)->EnableWindow(false);
GetDlgItem(IDCANCEL)->EnableWindow(true);
GetDlgItem(IDC_BUTTON_DISCONNECT)->EnableWindow(true);
return0;
}
四、课程设计总结
采用多线程方法,利用MFC的CSocket类,可以简单方便的实现计算机用户间的文件传输和消息发送功能。
以上的程序在VisualC++6.0环境编译通过,并且在学校机房内(本机和本机、本机和他机之间)测试能达到基本的要求。
当然我们可以通过继续增加线程来进一步拓展程序的功能。
指导教师评语:
成绩:
指导教师:
年月日
添加的代码:
#include"stdafx.h"
#include"Filetran.h"
#include"FiletranDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
#definePORT34567
#defineSIZEFILE1024
#defineFLAG2
CWinThread*pThreadSendFile;
CWinThread*pThreadListen;
CWinThread*pThreadSendMsg;
CFiletranDlg:
:
CFiletranDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CFiletranDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CFiletranDlg)
m_MsgSend=_T("");
message=_T("");
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
FileWork=FileStop=false;
StopServer=false;
}
voidCFiletranDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFiletranDlg)
DDX_Control(pDX,IDC_PROGRESS_SEND_FILE,m_Progress);
DDX_Control(pDX,IDC_YOURIP,m_YourIp);
DDX_Control(pDX,IDC_MYIP,m_MyIp);
DDX_Text(pDX,IDC_EDIT_MSG,m_MsgSend);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFiletranDlg,CDialog)
//{{AFX_MSG_MAP(CFiletranDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTONCONNECT,OnButtonconnect)
ON_BN_CLICKED(IDC_BUTTON_DISCONNECT,OnButtonDisconnect)
ON_BN_CLICKED(IDC_BUTTON_SEND_FILE,OnButtonSendFile)
ON_BN_CLICKED(IDC_BUTTON_STOP,OnButtonStop)
ON_BN_CLICKED(IDC_BUTTON_SENDMSG,OnButtonSendmsg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOLCFiletranDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpt