计算机网络课程设计报告文件传输协议的简单实现.docx
《计算机网络课程设计报告文件传输协议的简单实现.docx》由会员分享,可在线阅读,更多相关《计算机网络课程设计报告文件传输协议的简单实现.docx(27页珍藏版)》请在冰豆网上搜索。
计算机网络课程设计报告文件传输协议的简单实现
计算机网络课程设计报告文件传输协议的简单实现
课程设计
课程名称计算机网络课程设计题目名称文件传输协议的简单设计与实现学生学院专业班级____
学号
学生姓名_______________指导教师___________
2010年1月5日
设计摘要
关键词:
SOCKET编程,FTPclient/server程序
摘要:
本课程设计包含了文件传输协议的简单设计与实现。
文件传送是各种计算机网络实现的基本功能,文件传送协议是一种最基本的应用层协议按照客户/服务器的模式进行工作,提供交互式的访问,是INTERNET使用最广泛的协议之一。
文件传输协议的简单设计与实现建立在计算机网络实验环境TCP/IP网络体系结构之上,使用socket编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c),实现下述命令功能:
get,put,pwd,dir,cd,,,quit等,利用了已有网络环境设计并实现简单应用层协议。
本设计包括了具体设计任务,基本思路及所涉及的相关理论,设计流程图,调试过程中出现的问题及相应解决办法,实验运行结果,核心程序,个人体会及建议等。
1
1、文件传输协议的简单设计与实现------------------------------18
1.1具体设计任务----------------------------------------------18
1.2基本思路及所涉及的相关理论--------------------------------181.2.1基本思路-------------------------------------------------18
2.2.2相关理论--------------------------------------------18
1.3设计流程图------------------------------------------------191.4实验运行情况----------------------------------------------191.5核心程序--------------------------------------------------22
2.5.1服务器(sever)程序---------------------------------22
2.5.2客户(client)程序----------------------------------291.6心得体会-----------------------------------------------------------------------------37
参考文献--------------------------------------------------------38
2
2、文件传输协议的简单设计与实现
2.1具体设计任务
计算机网络实验环境建立在TCP/IP网络体系结构之上。
各计算机除了安装TCP/IP软件外,还安装了TCP/IP开发系统。
实验室各计算机具备Windows环境中套接字socket的编程接口功能,可为用户提供全网范围的进程通信功能。
本实验要求利用这些功能,设计和实现一个简单的文件传送协议。
用socket编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c),该程序应能实现下述命令功能:
get:
取远方的一个文件
put:
传给远方一个文件
pwd:
显示远主当前目录
dir:
列出远方当前目录
cd:
改变远方当前目录
:
显示你提供的命令
quit:
退出返回
2.2基本思路及所涉及的相关理论
2.2.1基本思路
设计程序使客户端连接的时候,服务器将会向客户端发回一条消息告知它的IP地址,然后关闭连接并继续接收端口的连接。
建立各个命令功能对应的函数,发送请求,等待服务器端的服务。
服务器端初始化WinSock,创建SOCKET,获取主机信息,并对客户端进行会话,发送回复讯息给客户端,响应完毕后关闭连接,释放WinSock。
2.2.2相关理论
文件传送是各种计算机网络都实现的基本功能,文件传送协议是一种最基本的应用层协议按照客户/服务器的模式进行工作,提供交互式的访问,是INTERNET使用最广泛的协议之一。
3
计算机网络实验环境建立在TCP/IP网络体系结构之上。
各计算机除了安装TCP/IP软件外,还安装了TCP/IP开发系统。
实验室各计算机具备Windows环境中套接字socket的编程接口功能,可为用户提供全网范围的进程通信功能。
本设计利用这些功能,设计和实现一个简单的文件传送协议。
用socket编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c)。
2.3设计流程图
2.4实验运行情况
服务器端运行,默认自动启动监听,情况如下图:
4
服务如果关闭监听,效果如下图:
客服端运行,如下图:
输入服务器端的IP和端口号进行连接,效果如图:
5
下面设置文件保存位置,如图:
下面演示上传一个视频文件,然后再下载下来,其中上传过程的进度信息:
上传完成后的效果图:
6
下载文件的进度提示信息:
下载完成后,指定目录下就有了该文件了:
2.5核心程序
2.5.1服务器(server)程序如下usingSystem;
usingSystem.Collections.Generic;usingSystem.Linq;
usingSystem.Text;
usingSystem.Threading;
usingSystem.Net;
usingSystem.Net.Sockets;
usingSystem.IO;
usingSystem.Windows.Forms;
namespaceTCP文件传输_服务器
{
classWorkThread
{
byte[]buffer;
intbufferSize=4096;
Threadmythread;
Sockethandler;
publicWorkThread(SocketworkSocket)
{
handler=workSocket;
buffer=newbyte[bufferSize];
mythread=newThread(BeginCommunication);
}
publicvoidStart()
{
mythread.Start();
}
publicvoidAbort()
{
mythread.Abort();
}
privatevoidBeginCommunication()
{
while(true)//从客户端接收数据,直到连接断开
7
{
try
{
intreCount=handler.Receive(buffer);
stringinsStr=Encoding.BigEndianUnicode.
GetString(buffer,0,reCount);
if(insStr.Substring(0,4)=="name")//收到下文件请求
{
stringfileName=insStr.
Substring(5,insStr.Length-5);
SendFile(fileName,handler);
}
elseif(insStr.Substring(0,4)=="boot")//收到获取根目录请求
{
stringlistStr=GetFileNames("F:
",false);
SendString(handler,listStr);
}
elseif(insStr.Substring(0,4)=="path")//收到获取指定目录内容请求
{
stringpath=insStr.Substring(5,insStr.Length-5);
stringlistStr=GetFileNames(path,false);
SendString(handler,listStr);
}
elseif(insStr.Substring(0,4)=="Queu")//获取下载文件夹请求,回复完整文件名列表
{
stringpath=insStr.Substring(5,insStr.Length-5);
stringlistStr=GetFileNames(path,true);
SendString(handler,listStr);
}
elseif(insStr.Substring(0,4)=="upld")//收到上传文件请求
{
stringreFileName=insStr.Substring(5,insStr.Length-5);
LoadFile(reFileName,handler);
}
elseif(insStr.Substring(0,4)=="quit")//收到断开连接命令
{
8
HostQuit();
break;
}
}
catch{HostQuit();break;}
}
}
privatevoidLoadFile(stringreFileName,Sockethandler)
{
try
{
FileStreamfs=newFileStream(reFileName,FileMode.Create,FileAccess.Write);
handler.Receive(buffer,8,SocketFlags.None);//接收文件大小
longfilesize=BitConverter.ToInt64(buffer,0);
longreceiveCount=0;
while(receiveCount{
intreadcount=handler.Receive(buffer,bufferSize,SocketFlags.None);
fs.Write(buffer,0,readcount);
receiveCount+=readcount;
}
fs.Close();
}
catch
{
HostQuit();
}
}
privatevoidSendFile(stringfileNmae,Sockethandler)
{
try
{
FileStreamfs=newFileStream(fileNmae,FileMode.Open,FileAccess.Read);
longsize=fs.Length;
byte[]bysize=BitConverter.GetBytes(size);
handler.Send(bysize,8,SocketFlags.None);//发送文件大小
BinaryReaderbr=newBinaryReader(fs);
intsendcount=0;
9
while(sendcount{
intreadcount=br.Read(buffer,0,bufferSize);
sendcount+=readcount;
handler.Send(buffer,readcount,SocketFlags.None);
}
}
catch
{
HostQuit();
}
}
privatevoidHostQuit()
{
GlobalValues.canControl.WaitOne();
GlobalValues.canControl.Release();
if(handler.Connected==true)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
privatevoidSendString(Sockethandler,stringlistStr)
{
byte[]list=Encoding.BigEndianUnicode.GetBytes(listStr);
byte[]listcountbuffer=
BitConverter.GetBytes(Convert.ToInt64(list.Length));
try
{
handler.Send(listcountbuffer,8,SocketFlags.None);//发送列表大小
intsendcount=0;
while(sendcount{
if(sendcount+bufferSize{
inti=handler.Send(list,sendcount,bufferSize,SocketFlags.None);
sendcount+=i;
}
else
{
inti=handler.Send(list,sendcount,list.Length-
10
sendcount,SocketFlags.None);//发送最后一次
sendcount+=i;
}
}
}
catch(Exceptione)
{
MessageBox.Show("连接断开.");
}
}
//fileOnly=true则获取指定目录及子目录内所有文件信息,fileOnly=false则获取指定目录文件信息及文件夹信息
privatestringGetFileNames(stringpath,boolfileOnly)
{
stringlistStr=string.Empty;
DirectoryInfodrct=newDirectoryInfo(path);
foreach(FileSystemInfofsiindrct.GetFileSystemInfos())
{
if(fsiisFileInfo)
{
//文件
FileInfofi=(FileInfo)fsi;
listStr+=fi.FullName;
listStr+="\n";
if(fi.Length<1024)
{
stringsizeStr=fi.Length.ToString()+"字节";
listStr+=sizeStr;
}
elseif(fi.Length<1024*1024)
{
doubletemp=Convert.ToDouble(fi.Length)/1024;
stringsizeStr=string.Format("{0:
F1}",temp)+"KB";
listStr+=sizeStr;
}
elseif(fi.Length<1024*1024*1024)
{
doubletemp=Convert.ToDouble(fi.Length)/1024/1024;
stringsizeStr=string.Format("{0:
F1}",temp)+"MB";
listStr+=sizeStr;
11
}
else
{
doubletemp=Convert.ToDouble(fi.Length)/1024/
1024/1024;
stringsizeStr=string.Format("{0:
F1}",temp)+
"GB";
listStr+=sizeStr;
}
listStr+="\n";
listStr+=fi.LastWriteTime.ToString("yyyy-MM-dd
hh:
mm:
ss");
listStr+="\n";
}
elseif(fsiisDirectoryInfo)
{
if(fileOnly)
{
listStr+=GetFileNames(fsi.FullName,true);
}
else
{
//文件夹
DirectoryInfodi=(DirectoryInfo)fsi;
listStr+=di.FullName;
listStr+="\n";
listStr+="dir";
listStr+="\n";
listStr+=di.LastWriteTime.ToString("yyyy-MM-dd
hh:
mm:
ss");
listStr+="\n";
}
}
}
returnlistStr;
}
}
}
public服务器()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls=false;
stringHostName=Dns.GetHostName();//得到主机名
IPHostEntryIpEntry=Dns.GetHostEntry(HostName);//得到主机IP
12
stringstrIPAddr=IpEntry.AddressList[0].ToString();
tsTxb_IPAdd.Text=strIPAddr;
hostIPAddress=IPAddress.Parse(strIPAddr);
Server=newIPEndPoint(hostIPAddress,
Convert.ToInt32(tsTxb_Port.Text));
sock=newSocket(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp);
sock.Bind(Server);
sock.Listen(10);
stringstr="正在监听端口"+tsTxb_Port.Text+"...";
tsLbl_Status.Text="状态:
"+str;
AcceptTh=newThread(ThAccept);
AcceptTh.Start();//开始监听端口
}
//下面是监听和停止监听的按钮事件
privatevoidbtn_Start_Click(objectsender,EventArgse)
{
tsBtn_Start.Enabled=false;
tsBtn_Stop.Enabled=true;
Server=newIPEndPoint(hostIPAddress,Convert.ToInt32(tsTxb_Port.Text));
sock=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
sock.Bind(Server);
sock.Listen(10);
stringstr="正在监听端口"+tsTxb_Port.Text+"...";
tsLbl_Status.Text="状态:
"+str;
AcceptTh=newThread(ThAccept);
AcceptTh.Start();
}
privatevoidbtn_stop_Click(objectsender,EventArgse)
{
tsBtn_Start.Enabled=true;
tsBtn_Stop.Enabled=false;
try
{
sock.Shutdown(SocketShutdown.Both);
}
catch{}
sock.Close();
tsLbl_Status.Text="状态:
已停止监听";
}
13
2.5.2客户(client)程序
//MyThread.cs中的实现
usingSystem;
usingSystem.Collections.Generic;usingSystem.Linq;
usingSystem.Text;
usingSystem.IO;
usingSystem.Net.Sockets;
usingSystem.Threading;
usingSystem.Windows.Forms;
namespace客户端_TCP文件传输
{
publicclassmyThread
{
ThreaddownloadTh;
ThreaduploadTh;
SocketwordSocket;
stringfileName;
stringsavePath;
byte[]buffer;
constintbufferSize=4096;
ToolStripProgressBartspBar;
ToolStripStatusLabelspeed;
intstartTime=0;
longreceivecount=0;
longsendCount=0;
intupOrDown=1;//指示上传或下载
System.Windows.Forms.Timertimer1=newSystem.Windows.Forms.Timer();
publicmyThread(SocketworkSock,stringFileName,stringSavePath,
refToolStripProgressBarTspBar,refToolStripStatusLabelSpeed)
{
wordSocket=workSock;
fileName=FileName;
savePath=Sa