课程设计的内容Word文档格式.docx
- 文档编号:3268364
- 上传时间:2023-05-01
- 格式:DOCX
- 页数:24
- 大小:60.24KB
课程设计的内容Word文档格式.docx
《课程设计的内容Word文档格式.docx》由会员分享,可在线阅读,更多相关《课程设计的内容Word文档格式.docx(24页珍藏版)》请在冰点文库上搜索。
6、课程设计评分标准15
7、课程设计参考资料15
1、课程设计的目的和要求
计算机网络课程设计是计算机网络原理课程之后的实践加强环节,通过本设计的训练使学生加深对网络协议的理解,并实践制定通信规则,同时通过实践,进一步掌握套接字编程方法,为大型网络编程打下坚实基础。
通过本次课程设计的学习与实践,使学生能达到知识与技能两方面结合的目标。
(1)熟练掌握网络的基本概念和原理。
(2)熟练掌握网络编程接口Winsock概念及编程原理
(3)掌握基于TCP/IP的Internet编程技术。
(4)掌握软件开发的过程及思想。
2、课程设计的内容
本课程设计的内容是通过对传输层协议TCP和UDP和客户/服务器数据通信的原理及方式的掌握,自选任意一种开发工具,利用Winsock控件编写出指定题目的交互信息的软件。
2.1WindowsSocket编程原理
2.1.1Socket的编程模型
Socket的编程模型如图1所示。
图1Socket的编程模型
字节流套接字(StreamSocket) 是最常用的套接字类型,TCP/IP协议族中的TCP协议使用此类接口。
字节流套接口提供面向连接的、无差错的、发送先后顺序一致的、无记录边界和非重复的网络信息包传输。
其模型如图2所示。
数据报套接字(DatagramSocket) TCP/IP协议族中的UDP协议使用此类接口,它是无连接的服务,它以独立的信息包进行网络传输,信息包最大长度为32KB,传输不保证顺序性、可靠性和无重复性,它通常用于单个报文传输或可靠性不重要的场合。
数据报套接口的一个重要特点是它保留了记录边界。
其模型如图3所示。
原始数据报套接字(RawSocket) 提供对网络下层通讯协议(如IP协议)的直接访问,它一般不是提供给普通用户的,主要用于开发新的协议或用于提取协议较隐蔽的功能。
图2面向连接的SOCKET编程模型
图3面向非连接的SOCKET编程模型
WindowsSockets规范中定义了一个新的数据类型SOCKET,这一类型的定义对于将来WindowsSockets规范的升级是必要的。
这一类型的定义保证了应用程序向Win32环境的可移植性。
因为这一类型会自动地从16位升级到32位。
2.1.2WindowsSocket的启动和终止
应用程序在使用WindowsSocketsDLL之前必须先调用启动函数WSAStartup(),该函数的功能有两点:
一是由应用程序指定所要求WindowsSocketsDLL版本;
二是获得系统WindowsSocketsDLL的一些技术细节。
每一个WSAStartup()函数必须和一个WSACleanup()函数对应,当应用程序终止时,必须调用WSACleanup()将自己从DLL中注销。
函数原型:
intWSAStartup(WORDwVersionRequested,LPWAADATAlpWSAData);
intWSACleanup(void);
函数执行正确返回0,错误返回非0值。
其中参数wVersionRequested用于指定准备加载的Winsock库的版本,lpWSAData参数是指向LPWSADATA结构的指针,该结构包含了加载的库版本有关的信息,它的格式如下:
typedefstructWSAData{
WORDwVersion;
WORDwHighVersion;
...
}
其中wVersion字段为打算使用的Winsock版本,wHighVersion为现有Windsock库中最高版本。
由于该结构与本实验编程关系不大,在此不做详细介绍。
这两个函数的一般用法如下例:
interrno;
WSADATAwsaData;
errno=WSAStartup(MAKEWORD(2,0),&
wsaData);
//使用2.0版本的Socket
2.1.3Socket函数简介
2.1.3.1创建套接字──socket()
应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,其调用格式如下:
SOCKETsocket(intaf,inttype,intprotocol);
该调用要接收三个参数:
af、type、protocol。
参数af指定通信发生的区域,UNIX系统支持的地址族有:
AF_UNIX、AF_INET、AF_NS等,而DOS、WINDOWS中仅支持AF_INET,它是网际网区域。
因此,地址族与协议族相同。
参数type描述要建立的套接字的类型。
若取SOCK_STREAM表示要创建的套接字是流套接字,取SOCK_DGRAM创建的是数据报套接字,取SOCK_RAW表示创建原始套接字。
参数protocol说明该套接字使用的特定协议,如果调用者不希望特别指定使用的协议,则置为0,使用默认的连接模式。
若套接字创建成功则该函数返回所创建的套接字句柄SOCKET,否则产生INVALID_SOCKET错误。
2.1.3.2指定本地地址──bind()
当一个套接字用socket()创建后,存在一个名字空间(地址族),但它没有被命名。
bind()将套接字地址(包括本地主机地址和本地端口地址)与所创建的套接字号联系起来,即将名字赋予套接字,以指定本地半相关。
其调用格式如下:
intbind(SOCKETs,conststructsockaddr*name,intnamelen);
参数s是由socket()调用返回的并且未作连接的套接字描述符(套接字号)。
参数name是赋给套接字s的本地地址,它由structsockaddr结构表示,namelen表明了name的长度。
如果没有错误发生,bind()返回0。
否则返回值SOCKET_ERROR。
sockaddr结构随选择的协议不同而变化,因此一般情况下另一个与该地址结构大小相同的sockaddr_in结构更常用,sockaddr_in结构用来标识TCP/IP协议下的地址,并可以方便地通过强制类型转换将其转换为sockaddr结构,sockaddr_in的格式如下:
structsockaddr_in{
shortsin_family;
/*AF_INET*/
u_shortsin_port;
/*16位端口号*/
structin_addrsin_addr;
/*32位IP地址*/
charsin_zero[8];
/*保留*/
2.1.3.3监听连接──listen()
此调用用于面向连接服务器,表明它愿意接收连接。
listen()需在accept()之前调用,其调用格式如下:
intlisten(SOCKETs,intbacklog);
参数s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。
backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。
如果没有错误发生,listen()返回0。
否则它返回SOCKET_ERROR。
listen()在执行调用过程中可为没有调用过bind()的套接字s完成所必须的连接,并建立长度为backlog的请求连接队列。
调用listen()是服务器接收一个连接请求的四个步骤中的第三步。
它在调用socket()分配一个流套接字,且调用bind()给s赋于一个名字之后调用,而且一定要在accept()之前调用。
2.1.3.4建立套接字连接──connect()与accept()
这两个系统调用用于完成一个完整相关的建立,其中connect()用于建立连接。
无连接的套接字进程也可以调用connect(),但这时在进程之间没有实际的报文交换,调用将从本地操作系统直接返回。
这样做的优点是程序员不必为每一数据指定目的地址,而且如果收到的一个数据报,其目的端口未与任何套接字建立“连接”,便能判断该端口不可操作。
而accept()用于使服务器等待来自某客户进程的实际连接。
connect()的调用格式如下:
intconnect(SOCKETs,conststructsockaddr*name,intnamelen);
参数s是欲建立连接的本地套接字描述符。
参数name指出说明对方套接字地址结构的指针。
对方套接字地址长度由namelen说明。
如果没有错误发生,connect()返回0。
在面向连接的协议中,该调用导致本地系统和外部系统之间连接实际建立。
由于地址族总被包含在套接字地址结构的前两个字节中,并通过socket()调用与某个协议族相关。
因此bind()和connect()无须协议作为参数。
accept()的调用格式如下:
SOCKETaccept(SOCKETs,structsockaddr*addr,intFAR*addrlen);
参数s为本地套接字描述符,在用做accept()调用的参数前应该先调用过listen()。
addr指向客户方套接字地址结构的指针,用来接收连接实体的地址。
addr的确切格式由套接字创建时建立的地址族决定。
addrlen为客户方套接字地址的长度(字节数)。
如果没有错误发生,accept()返回一个SOCKET类型的值,表示接收到的套接字的描述符。
否则返回值INVALID_SOCKET。
accept()用于面向连接服务器。
参数addr和addrlen存放客户方的地址信息。
调用前,参数addr指向一个初始值为空的地址结构,而addrlen的初始值为0;
调用accept()后,服务器等待从编号为s的套接字上接受客户连接请求,而连接请求是由客户方的connect()调用发出的。
当有连接请求到达时,accept()调用将请求连接队列上的第一个客户方套接字地址及长度放入addr和addrlen,并创建一个与s有相同特性的新套接字号。
新的套接字可用于处理服务器并发请求。
四个套接字系统调用,socket()、bind()、connect()、accept(),可以完成一个完全五元相关的建立。
socket()指定五元组中的协议元,它的用法与是否为客户或服务器、是否面向连接无关。
bind()指定五元组中的本地二元,即本地主机地址和端口号,其用法与是否面向连接有关:
在服务器方,无论是否面向连接,均要调用bind();
在客户方,若采用面向连接,则可以不调用bind(),而通过connect()自动完成。
若采用无连接,客户方必须使用bind()以获得一个唯一的地址。
以上讨论仅对客户/服务器模式而言,实际上套接字的使用是非常灵活的,唯一需遵循的原则是进程通信之前,必须建立完整的相关。
2.1.3.5数据传输──send()与recv()
当一个连接建立以后,就可以传输数据了。
常用的系统调用有send()和recv()。
send()调用用于在参数s指定的已连接的数据报或流套接字上发送输出数据,格式如下:
intsend(SOCKETs,constchar*buf,intlen,intflags);
参数s为已连接的本地套接字描述符。
buf指向存有发送数据的缓冲区的指针,其长度由len指定。
flags指定传输控制方式,如是否发送带外数据等。
如果没有错误发生,send()返回总共发送的字节数。
recv()调用用于在参数s指定的已连接的数据报或流套接字上接收输入数据,格式如下:
intrecv(SOCKETs,char*buf,intlen,intflags);
参数s为已连接的套接字描述符。
buf指向接收输入数据缓冲区的指针,其长度由len指定。
flags指定传输控制方式,如是否接收带外数据等。
如果没有错误发生,recv()返回总共接收的字节数。
如果连接被关闭,返回0。
2.1.3.6关闭套接字──closesocket()
closesocket()关闭套接字s,并释放分配给该套接字的资源;
如果s涉及一个打开的TCP连接,则该连接被释放。
closesocket()的调用格式如下:
BOOLclosesocket(SOCKETs);
参数s待关闭的套接字描述符。
如果没有错误发生,closesocket()返回0。
2.1.4程序实例
以下程序完成字符串的传输及大写化,程序在VC6.0环境下调试通过。
程序分两个部分,即服务器端和客户端程序,客户端程序负责用户的键盘输入,并将输入的字符串传送到服务器,待收到服务器传回的大写化后的字符串后再将此处理后的字符串显示出来。
服务器程序需事先运行,负责接收客户端的字符串,并将其大写化,然后将处理后的字符串返回客户端。
该例子演示了客户端与服务器端利用WINSOCK进行通信的实际过程。
两个程序可在一台计算机上运行,首先编译连接服务器程序并运行,再编译连接客户端程序并运行(注意运行客户端程序时服务器端程序不能关闭),服务器的IP地址可选用本机地址,即127.0.0.1,端口号可任意选择,以不与本机其他程序冲突为原则(本例中用的是7000)。
以下是服务器端的程序源码:
#include"
winsock.h"
stdio.h"
#pragmacomment(lib,"
WS2_32"
)
voidmain()
{
WSADATAwsaData;
SOCKETsock,newsock;
structsockaddr_inserver;
structsockaddr_intcpaddr;
charbuf[1024];
intrval,len;
interrno;
errno=WSAStartup(MAKEWORD(2,0),&
if(errno!
=0){
perror("
cannotinit"
);
exit
(1);
}
/*建立套接字*/
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==INVALID_SOCKET){
openingstreamsocket"
WSACleanup();
/*指定端口和IP*/
memset((char*)&
server,0,sizeof(structsockaddr_in));
server.sin_family=AF_INET;
server.sin_port=htons(7000);
/*端口*/
server.sin_addr.S_un.S_addr=inet_addr("
127.0.0.1"
/*本机*/
errno=bind(sock,(structsockaddr*)&
server,sizeof(server));
if(errno!
=0){
closesocket(sock);
bindingstreamsocket"
printf("
%d\n"
(errno=WSAGetLastError()));
/*开始接收连接*/
errno=listen(sock,5);
listenerror\n"
len=sizeof(structsockaddr);
while
(1){
newsock=accept(sock,(structsockaddr*)&
tcpaddr,(int*)&
len);
if(newsock==INVALID_SOCKET)
perror("
accept"
else{
do{
memset(buf,0,sizeof(buf));
rval=recv(newsock,buf,1024,0);
if(rval==SOCKET_ERROR){
readingstreammessage"
closesocket(newsock);
closesocket(sock);
WSACleanup();
exit
(1);
}
if(rval==0)
printf("
endingconnection\n"
else{
-->
%s\n"
buf);
strupr(buf);
send(newsock,buf,strlen(buf),0);
}while(rval!
=0);
closesocket(newsock);
};
以下是客户端程序源码:
ws2_32"
SOCKETsock;
intlen;
//调用WindowsSocketsDLL
server.sin_addr.S_un.S_addr=inet_addr("
errno=connect(sock,(structsockaddr*)&
if(errno==SOCKET_ERROR){
connecttoserver"
/*开始发送*/
Pleaseinputthemessageyouwanttosend...\n<
--"
gets(buf);
while(strcmp(buf,"
bye"
)!
len=strlen(buf);
errno=send(sock,buf,len,0);
=len){
senderror"
errno=recv(sock,buf,1024,0);
receiveerror"
buf);
<
2.2设计题目及要求
文件传输系统
软件名:
MYFTP(分服务器端和客户端两部分)
功能:
实现类似FTP的功能(在FTP服务器与客户端之间传送文件)。
编程语言及工具:
自选(VB、JAVA、C#、Delphi、VC)
描述:
服务器端:
1.指定一个目录作为FTP目录(之后所有的文件操作均在此目录下进行),
2.接收客户端的命令请求并提供相应的服务。
客户端:
完成与FTP用户的人机界面,以命令的方式向服务器请求服务,主要的命令有:
1.CONNECTIP地址端口号
指定FTP服务器的IP地址和端口号,连接到服务器。
响应:
连接成功/失败。
2.LOGIN用户名
用户登录(假设在服务器端有用户管理功能)
响应:
若用户不存在,提示“无此用户”;
若用户存在,提示“密码:
”;
用户输入密码后,若正确提示“登录成功”;
若不成功,提示“密码错”。
3.DIR
显示FTP服务器的FTP目录的文件列表(假设无子目录)
目录列表(只要文件名即可)。
4.GET文件名
将FTP目录下的文件下载到本地
传送成功/失败/无此文件。
5.PUT文件名
将本地文件上传到FTP目录
6.HELP
显示MYFTP软件的功能(此命令与网络通信无关)
7.BYE
退出MYFTP软件
选做:
将此软件做成图形界面。
例:
C:
\>
MYFTP
->
CONNECT127.0.0.18000
--CONNECTOK
LOGINABC
--PASSWORD:
******
--USE
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 课程设计 内容
![提示](https://static.bingdoc.com/images/bang_tan.gif)