基于TCP的CS模式程序设计文档格式.docx
《基于TCP的CS模式程序设计文档格式.docx》由会员分享,可在线阅读,更多相关《基于TCP的CS模式程序设计文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
(3)发展前景
VMwareWorkstation是一款可运行多种操作系统的虚拟机,方便用户的多种需求,此软件在实现用户需求的同时不会影响电脑原操作系统的使用,这个特点为其在以后的发展道路上有更好的前景。
TCP是传输层的应用协议,可通过多方面来保证数据传输的可靠性,它采用了停止等待方式来回应数据的接收,只有当接收到数据时,用户才发送数据确认报文,同时此协议使用滑动窗口方法来控制网络拥塞,提高数据传输的可靠性。
二.相关原理
(1)TCP/IP体系结构
TCP/IP的中文译名为传输控制协议/网际协议,又叫网络通讯协议,这个协议是Internet最基本的协议,Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。
TCP/IP协议并不完全符合OSI的七层参考模型。
传统的开放式系统互连参考模型,是一种通信协议的七层抽象的参考模型,其中每一层执行某一特定任务。
该模型的目的是使各种硬件在相同的层次上互相通信。
这七层是:
物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
而TCP/IP通讯协议采用了四层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求,如下图所示。
图1计算机网络体系结构
应用层:
应用程序间沟通的层,如简单电子邮件传输(SMTP),文件传输协议(FTP),网络远程访问协议(Telnet)等。
传输层:
在此层中,它提供了节点间的数据传送,应用程序之间的通信服务,主要功能是数据格式化,数据确认和丢失、重传等。
如传输控制协议(TCP),用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被传送并到达接收。
网络层:
负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否正确而接收),如网际协议(IP)。
网络接口层:
接收IP数据包并进行传输,从网络上接收物理帧,抽取IP数据报转交给上一层,对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet)来传送数据。
(2)TCP传输
图2TCP连接中分组交换以及客户端与服务器的状态转换
TCP协议在IP协议之上,提供可靠的传输服务。
这种服务的特点:
可靠、全双工、流式和无结构传输。
TCP协议使用了积极确认和重传送的技术来实现可靠传输。
接收者在收到发送者发送的数据后,必须发送一个相应的确认(ACK)消息,表示他已经收到数据。
发送者保存发送的数据的记录,在发送下一个数据之前等待这个数据的确认消息在他发送这个数据的同时,启动了一个计时器。
在一定时间内没有接收到确认消息,就认为这个数据在传输过程中丢失了,接着就会发送这个数据。
同时TCP实体又采用了滑动窗口协议。
当发送方传送一个数据报到达目的地时,接收方的TCP实体向发送方发送一个数据报,其中包含一个确认序号,它等于希望收到的下一个数据报的顺序号。
建立了一个TCP连接,需要三次握手过程,连接才能成功建立,如图二所示。
握手过程的第一段的代码位设置为SYN,序号为J,表示开始一次握手。
接收方收到此报文断后,向发送方回发一个报文段,代码位为SYN和ACK,序号为K,确认序号为J+1,表示接收方同意建立此连接。
发送者收到此报文段后,发送ACK建立连接,完成三次握手以后,双方就开始正式传送数据。
在通信完成阶段,两方通过四次断开来释放连接,如图二,客户端请求释放连接,发送有效位为FIN,服务器端给一个确认信号,若服务器端没有数据发送,便向客户端发送FIN请求,客户端对此回应,等待2MSL,彻底断开连接。
(3)C/S模式
鉴于此次设计目的,采用Linux环境下使用TCP实现点到点的可靠连接,实现基于TCP/IP协议的面向连接的通信,连接双方分为客户端和服务器端,主要实现过程如图3所示。
图3TCP客户/服务器的套接字连接
TCP套接字编程中,服务器实现的步骤:
(1)使用socket()函数创建套接字。
(2)将创建的套接字绑定到指定的地址结构。
(3)Listen()函数设置套接字为监听模式,使服务器进入被动打开的状态。
(4)接受客户端的连接请求,建立连接。
(5)接收、应答客户端的数据请求。
(6)终止连接。
客户端实现的步骤:
(2)调用connect()函数建立一个与TCP服务器的连接。
(3)发送数据请求,接收服务器的数据应答。
(4)终止连接。
综上所述,TCP/IP应用中的服务器必须先于客户端进程启动,直到对客户端的响应结束或强迫终止。
(4)并发服务器
服务器按处理方式分为迭代服务器和并发服务器,为提高资源利用常采用并发服务器对客户端的请求进行处理,当服务器接收到客户请求时生成一个子进程处理客户请求,而父进程继续接受客户请求,实现多个进程并发进行,并发服务器的工作原理如图4所示。
图4TCP并发服务器
父进程使用fork()函数生成子进程,父、子进程共享父进程在调用fork()之前的所有描述符。
一般情况下,接下来父进程只负责接受客户端的请求,子进程只负责处理客户端的请求。
关闭不需要的描述符可以节省系统资源,又可防止父、子进程同时对共享描述符进行处理,产生不可预计的后果。
此外,由于fork()函数返回后,与监听和已连接描述符相关联的文件表项的访问计数值均加1,父进程调用close()后计数器减1,而描述符只在访问计数器为0的情况下才真正关闭,为了正确关闭连接,当调用fork()函数后父进程关闭不需要的已连接描述符,子进程关闭不需要的监听描述符。
父子进程在接受请求后对描述符的动态操作如图5。
(1)accept返回前双方的状态
(2)accept返回后双方的状态
(3)fork返回后双方的状态
(4)父、子进程关闭相应的套接字后双方的状态
图5父、子进程对描述符的操作
图5中listenfd为监听描述符,connfd为已连接描述符,父进程拥有监听套接字用于接听客户端的连接,子进程的已连接套接字用于处理客户端的请求。
三.总体设计
(1)服务器端等待客户端请求连接,连接成功后,接收客户端信息并显示,然后接收来自客户的信息(字符串),将字符串反转并将结果送回客户端。
服务器可同时处理多个客户端的请求,准确区分每个用户的信息。
图6服务器端的程序流程图
(2)客户端与服务器相连接,用户输入客户的名称并发给服务器,然后向服务器发送字符串,接收服务器返回的经处理的字符串,并显示。
当用户输入bye时断开连接。
四.具体设计
客户端在命令行中应输入欲连接服务器的IP地址或域名(图7),通过gethostbyname()函数获得服务器端的信息,对其进行处理,服务器显示请求连接的客户端的IP地址,如图8所示。
图7客户端命令行格式
图8服务器显示客户端IP
用户给出客户端名称,服务器端显示,如图9所示,服务器端通过用户名来显示信息的来源,并对信息进行处理返回客户端,客户端在屏幕输出,如图10。
图9服务器显示客户端名称
图10服务器对字符串进行反转
客户端可通过输入bye来释放连接(图11),在程序中通过if语句,字符串比较来确定是否释放两者之间的连接。
图11断开连接
服务器可以同时处理多个客户端的请求,并通过用户名准确显示信息的来源,如图12展示出一个服务器同时处理两个客户端进程的过程:
建立连接、数据传送、释放连接。
图12并发服务器的实现
五.结论
基于TCP/IP协议和套接字编程原理为服务器端完成基本数据配置,主要采用套接字编程原理以及VMware的使用,通过调试运行并且经过完善后,实现并发服务器的功能。
在这次课程设计的过程中,对于网络编程有了更深一步的了解。
首先是对于计算机网络基础这方面,对于网络体系中的几种分层方法,每层的作用都由了系统的理解,VMware的使用也更加的熟练,特别是对于Socket编程这一块,套接字的创建、绑定以及使用,基于TCP、UDP的编程以及并发服务器的原理都有了深一步的理解,这次课程设计对于以后进行网络的开发有很大的帮助。
六.附录
(1)服务器端server.c
#include<
stdio.h>
stdlib.h>
string.h>
unistd.h>
sys/types.h>
sys/socket.h>
netinet/in.h>
arpa/inet.h>
#definePORT1234
#defineBACKLOG5
#defineMAXDATASIZE1000
voidprocess_cli(intconnfd,structsockaddr_inclient);
main()
{
intlistenfd,connfd;
pid_tpid;
structsockaddr_inserver;
structsockaddr_inclient;
intlen;
if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("
Creatingsocketfailed."
);
exit
(1);
}
intopt=SO_REUSEADDR;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&
opt,sizeof(opt));
bzero(&
server,sizeof(server));
server.sin_family=AF_INET;
server.sin_port=htons(PORT);
server.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(listenfd,(structsockaddr*)&
server,sizeof(server))==-1)