资源描述
武汉理工大学
计算机网络课程论文
题目
基于C/S的时间同步服务器的实现
作者
学院
专业
学号
指导教师
李方敏
二〇一六年四月十一日
武汉理工大学信息工程学院课程论文诚信声明
本人声明:所呈交的课程论文,是本人在指导老师的指导下,独立开展工作所取得的成果,成果不存在知识产权争议,除文中已经注明引用的内容外,本课程论文不含任何其他个人或集体已经发表或创作过的作品成果。对本文工作做出重要贡献的个人和集体均已在文中以明确方式标明。本人完全意识到本声明的法律结果由本人承担。
本科课程论文作者签名:
二〇一六年四月十一日
摘要
计算机网络,是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。本次计算机网络的论文题目为基于C/S的时间同步服务器的实现。时间服务器是在局域网中作为发布统一时间的服务器,它利用电脑网络把时间信息传递给用户。参照现有的时间服务器的原理以及效果实现一个时间服务器的服务端和客户端。服务器端开放指定的端口发布时间到网络中,其他客户端从网络中获取该时间并将本地时间与之同步。本次设计以Visual Studio 2010为开发平台,从选题背景,方案论证,过程论述,结果分析和结论总结五方面来论述本次设计的观点的过程。
关键词:时间同步; 客户端; 服务端; TCP/IP
目录
一.选题背景 1
1.1 问题提出 1
1.2 软件使用 1
1.3 预期目标 2
二.方案论证 2
三.过程论述 3
3.1 相关原理 3
3.2 设计过程 4
3.3 算法流程图 5
四.结果分析 6
五.结论总结 7
参考文献 9
附录一:程序源代码 10
致谢 14
课程论文成绩评定表 15
计算机网络论文《基于C/S的时间同步服务器的实现》
一.选题背景
1.1 问题提出
对于一个由计算机组成的系统中,其中各个节点计算机都有自己的额系统时间,计算机网络控制系统中各子系统时间段额一致性,是网络控制系统中的核心问题之一,它的准确性对网络控制系统的实时性和准确性有重大影响。但是由于在运行中受到设计缺陷、环境温度变化、电磁干扰、负载等多种因素的影响,计算机的时钟大多是不精确的,随着时间的推移,这种误差逐渐累积,时间的偏差将越来越大。在一些重要的应用中(如实时数据采集、监控、工业控制网络以及电信等),时间的准确性要求更为严格和苛刻,因此时间同步变得尤为重要,并且,实现一个精确地系统时间变得更加重要。时间同步的实现方法,常见的有硬件和软件的方法:硬件同步是通过各仿真节点都连入专用的时钟信号线来完成的,它的精度相对来说比较高,但成本也高,操作相对比较复杂;软件同步方法,是完全利用软件来完成分布式系统中各时钟的同步。对于软件同步的方法,目前常用的时间协议有NTP协议、SNTP协议以及PTP协议等。对于这些时间同步协议的一般实现方法是通过计算机网络等方式通讯实现的,但是由于计算机网络的一些潜在的威胁,如偶然或恶意的原因遭到破环、更改、泄露,是网络系统不能连续可靠性的正常运行,从而导致时间同步系统不能正常的运转。由于资源和时间有限,本次基于C/S的时间同步服务器的实现先采用软件的方法来实现。
1.2 软件使用
基于C/S的时间同步服务器的实现,运用Visual Studio 2010来实现。Visual Studio 2010是微软公司推出的开发环境,是目前最流行的Windows平台应用程序开发环境。Visual Studio 2010的C++编译器现在支持lambda表达式、右值引用(rvaluereferences)、编译时断言(compile- timeassertions)、表达式类型发现(expressiontypediscovery)和C++0X标准的自动类型deduction。Visual Studio 2010的C++编译器有一种模式可以向后兼容Visual Studio 2008的工具和类库。这会给开发者的个人升级提供很大的方便,即使团队中有其他人还不想切换到Visual Studio 2010。在 Visual Studio 的任何版本中都可以创建和使用文本模板,无需任何其他组件。在引入了预处理文本模板的 Visual Studio 2010 中,从应用程序生成任何类型的文本文件已变得更加容易。还通过与生成系统的更好集成,改进了对代码集成的支持,从而使生成的源代码始终会在对源模型进行任何更改后保持更新。Visual Studio 2010是一个功能强大的可视化软件开发工具。Visual Studio 2010对网络编程有socket支持,WinInet支持,MAPI和ISAPI支持等。其中,Windows Sockets API是TCP/IP网络环境里,也是Internet上进行开发最为通用的API。在TCP/IP网络通信环境下,Socket数据传输是一种特殊的I/O,它也相当于一种文件描述符,具有一个类似于打开文件的函数调用Socket()。Socket是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的Socket系统调用。客户随机申请一个Socket(相当于一个想打电话的人可以在任何一台入网电话上拨号呼叫),系统为之分配一个Socket号;服务器拥有全局公认的Socket,任何客户都可以向它发出连接请求和信息请求(相当于一个被呼叫的电话拥有一个呼叫方知道的电话号码)。Socket利用客户/服务器模式巧妙地解决了进程之间建立通信连接的问题。服务器Socket半相关为全局所公认非常重要。读者不妨考虑一下,两个完全随机的用户进程之间如何建立通信?假如通信双方没有任何一方的Socket固定,就好比打电话的双方彼此不知道对方的电话号码,要通话是不可能的。
1.3 预期目标
本次设计以Visual Studio 2010为开发平台,基于C/S的时间同步服务器的实现。时间服务器是在局域网中作为发布统一时间的服务器,它利用电脑网络把时间信息传递给用户。参照现有的时间服务器的原理以及效果实现一个时间服务器的服务端和客户端。服务器端开放指定的端口发布时间到网络中,其他客户端从网络中获取该时间并将本地时间与之同步。给出相关的原理、设计思想和设计过程;画出时间同步服务器端与客户端的算法流程图;实现服务器端和客户端并给出使用说明;测试服务器端与客户端,写出测试结果。
二.方案论证
Client /Server 结构的关系数据库系统因为具有高性能、 高效率、开放、易扩充、可伸缩等优越的特性 ,所以得到了广泛的应用。 在 Client /Serv er 结构的关系数据库应用系统中 ,不乏这样的应用: 要求用户在客户端中插入、修改数据时 ,要在 数据库的相应表中记录这些数据插入、修改的时间以供统计分析使用。为了保证今后按时间进行的统计分析的准确性,各个客户端向数据库服务器 DBM S提供的必须是统一的时间。硬件同步是通过各仿真节点都连入专用的时钟信号线来完成的,它的精度相对来说比较高,但成本也高,操作相对比较复杂;软件同步方法,是完全利用软件来完成分布式系统中各时钟的同步。软件同步相对于硬件同步来说简单、快捷、方便、易用,适合我们学生党来做计算机网络的相关研究,效果比较好,所以此次试验采用Visual Studio 2010为平台,基于C/S的时间同步服务器的实现。
三.过程论述
3.1 相关原理
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
NTP的基本工作原理如下图所示。Device A和Device B通过网络相连,它们都有自己独立的系统时钟,需要通过NTP实现各自系统时钟的自动同步。为便于理解,作如下假设:
l 在Device A和Device B的系统时钟同步之前,Device A的时钟设定为10:00:00am,Device B的时钟设定为11:00:00am。
l Device B作为NTP时间服务器,即Device A将使自己的时钟与Device B的时钟同步。
l NTP报文在Device A和Device B之间单向传输所需要的时间为1秒。
图1 NTP协议工作原理图
l Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)。
l 当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)。
l 当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)。
l 当Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)。
至此,Device A已经拥有足够的信息来计算两个重要的参数:
l NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2秒。
l Device A相对Device B的时间差offset=((T2-T1)+(T3-T4))/2=1小时。
3.2 设计过程
在局域网中有很多应用软件为了协同工作,需要保证客户机上时间统一,方法是客户机从一个时间相对正确的服务器读取时间,以此来校正本地时间。按照C/S模型建立一个时间同步服务器,此系统分为服务器端(Server)和客户端(Client),分别对服务器端和客户端进行算法设计和软件编程,使其各自都能进行编译,能够同时运行,使其服务器端(Server)按照时间协议的要求进行正常运转,向客户端(Client)发送时间同步请求,此时,客户端(Client)正在等待服务器端(Server)发来时间同步请求,待客户端(Client)收到请求之后,按照相应的设计的算法进行时间同步。这就达到了时间同步的目的。
3.3 算法流程图
服务器端Server
客户端 Client
Socket()创建数据报套接字client
Socket()创建数据报套接字client
Close()关闭套接字Server
Send to()发送数据报
Recvfrom()接收客户端请求
在端口等待客户端时间同步请求
Bing()与本地地址绑定
Close()关闭套接字Client
Recvfrom()接收服务器数据报
Send to()发送数据报时间同步请求
服务请求
服务应答
四.结果分析
1.在Visual Studio 2010上单独运行服务器端程序得到如下结果
2.在Visual Studio 2010上继续运行客户端程序得到如下结果
3.继续点击(1)得到如下结果
4.时间同步结果已经在面板上面得到很好的诠释
五.结论总结
由第四部分可以形象地观察出时间同步的全过程,并且本次基于C/S的时间同步服务器的实现很成功。本次设计内容丰富,涉及的知识面较广。在设计前期,通过查找资料为设计准备,使我对所学专业方面的许多知识又温习了一遍,许多以前很模糊、很孤立的部分知识通过这次设计得以贯穿,而且掌握得更加地稳固了;此外,通过这次设计,在软件编程方面,使我了解到了自己的许多不足之处,通过查找参考资料逐渐熟悉了以前有关于C++的编程知识。在之前计算机的级考试的学习过程中,对其有了一些基础的了解和认识。通过这次的设计使我进一步了解了计算机网络的相关知识,以及C/S模式和时间同步服务器的原理的实现,而且了解了VC++6.0的升级版Visual Studio 2010,收获很大。但在设计过程中也出现了不少问题,例如编程上的逻辑问题,但最终都一个模块一个模块认真分析,最终解决了问题,将模块的程序连在一起,最终结果可以成功运行。通过这次设计,我不仅加深了对计算机网络理论的理解,将理论很好地应用到实际当中去,通过分部完成程序将程序分为几个部分完成,然后再将程序整合在一起,每部分可以进行独立编程。这次设计中我也自己认真独立思考,了解了每一步的程序编程,对于时间同步服务器的有关知识有了进一步认识和理解,自己之后需要多多注重锻炼自己的动手能力,讲所学到的知识运用到实际中,加深自己对于知识的理解。学习就是一个了解疑惑,进而解惑的过程。这次设计就是提供了这样一个机会,发现自己知识漏洞,与同学老师探讨进行解惑的的机会。
参考文献
[1]谢希仁.计算机网络(第6版).电子工业出版社,2013.6
[2]陈鸣等.计算机网络实验教程,从原理到实践.机械工业出版社,2007
[3]Tanenbaum,A.S.Computer Networks.机械工业出版社,2011
[4] 罗军舟. TCP/IP协议及网络编程技术.清华大学出版社,2011
附录一:程序源代码
1. 服务器端源程序代码
#pragma comment(lib,"ws2_32.lib")
#include<winsock2.h>
#include<stdio.h>
#include<string.h>
int main()
{
WSADATA wsadata;
int err = WSAStartup(WINSOCK_VERSION,&wsadata);
if(err != 0)
{
printf("WSAStartup() failed :%d\n",WSAGetLastError());
return -1;
}
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == INVALID_SOCKET)
{
printf("socket() failed:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(20000);
localaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
err = bind(sock,(sockaddr *)&localaddr,sizeof(localaddr));
if(err == SOCKET_ERROR)
{
printf("bind() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
err=listen(sock,5);
if(err == SOCKET_ERROR)
{
printf("listen() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
sockaddr_in clientaddr;
int len = sizeof(clientaddr);
while(1)
{printf("--------时间同步服务器欢迎您(电信1305 李晓月)---------\n\n");
printf("等待客户端的对时请求……\n");
SOCKET sockconn = accept(sock,(sockaddr *)&clientaddr,&len);
if(sockconn == INVALID_SOCKET)
{
printf("accept() failed:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
printf("请求时间同步的客户为:%sPort:%d\n",inet_ntoa(clientaddr.sin_addr),clientaddr.sin_port);
char rbuf[1024];
while(1)
{
memset(rbuf,0,1024);
int rb = recv(sockconn,rbuf,1024,0);
if(rb == SOCKET_ERROR)
{
printf("recv() failed:%d\n",WSAGetLastError());
closesocket(sockconn);
break;
}
if(rb == 0)
{
printf("Connection is closed.\n\n\n ");
shutdown(sockconn,SD_SEND);
closesocket(sockconn);
break;
}
printf("服务器受到[%d]的请求:%s\n",rb,rbuf);
SYSTEMTIME st;
GetLocalTime( &st );
printf("服务器时间:%04d-%02d-%02d %02d:%02d:%02d\n",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
int sb = send(sockconn,(char *)&st,sizeof(st),0);
if(sb == SOCKET_ERROR)
{
printf("send() failed:%d\n",WSAGetLastError());
closesocket(sockconn);
WSACleanup();
return -1;
}
printf("发送本地时间成功!!\n");
}
}
closesocket(sock);
WSACleanup();
return 0;
}
2. 客户端源程序代码
#pragma comment(lib,"ws2_32.lib")
#include<winsock2.h>
#include<stdio.h>
#include<string.h>
#include <windows.h>
int main()
{ int m;
do{
WSADATA wsadata;
int err = WSAStartup(WINSOCK_VERSION,&wsadata);
printf("--------时间同步服务器欢迎您(电信1305 李晓月)--------------\n\n");
if(err != 0)
{
printf("WSAStartup() 出错:%d\n",WSAGetLastError());
return -1;
}
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if(sock == INVALID_SOCKET)
{
printf("socket()出错:%d\n",WSAGetLastError());
WSACleanup();
return -1;
}
sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(20000);
serveraddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
err=connect(sock,(sockaddr *)&serveraddr,sizeof(serveraddr));
if(err == SOCKET_ERROR)
{
printf("connect()出错:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
char data[] = "客户端请求时间同步!";
int sb = send(sock,data,strlen(data),0);
if(sb == SOCKET_ERROR)
{
printf("send()出错:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
printf("已经发送请求给服务器 %s\n",data,inet_ntoa(serveraddr.sin_addr));
shutdown(sock,SD_SEND);
SYSTEMTIME st,sp;
GetLocalTime(&sp);
printf("本地时间为:%04d-%02d-%02d%.2d:%.2d:%.2d \n",sp.wYear,sp.wMonth,sp.wDay,sp.wHour,sp.wMinute,sp.wSecond);
while(1)
{
//memset(rbuf,0,1024);
int rb =recv(sock,(char *)&st,sizeof(st),0);
if(rb == SOCKET_ERROR)
{
printf("recv()出错:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return -1;
}
if(rb==0)
{printf("Connection is closed.\n\n");
shutdown(sock,SD_SEND);
closesocket(sock);
break;
}
printf("获取的服务器时间为:%04d-%02d-%02d %.2d:%.2d:%.2d \n", st.wYear,st.wMonth,st.wDay,st.wHour, st.wMinute, st.wSecond);
SetLocalTime(&st);
printf("修改本地时间成功,已与%s时间同步!\n\n",inet_ntoa(serveraddr.sin_addr));
printf("继续请按(1),退出请按(0)\n");
scanf("%d",&m);
}
}
while(m==1);
}
致谢
在这次论文的撰写过程中,我得到了许多人的帮助。
首先我要感谢我的老师给予我的指导、提供给我的支持和帮助,这是我能顺利完成这次设计的主要原因,更重要的是老师帮我解决了许多技术上的难题,让我能把系统做得更加完善。在此期间,我不仅学到了许多新的知识,而且也开阔了视野,提高了自己的设计能力。
同时,在论文指导中,老师严谨的治学态度、丰富渊博的知识、敏锐的学术思维、精益求精的工作态度以及侮人不倦的师者风范是我终生学习的楷模,老师们的高深精湛的造诣与严谨求实的治学精神,将永远激励着我。在此,谨向老师们致以衷心的感谢和崇高的敬意!
另外,感谢校方给予我这样一次机会,让我能够独立地完成一次设计,并在这个过程当中,给予我们各种方便,使我们在这学期快要结课的时候,能够将学到的知识应用到实践中,增强了我们实践操作和动手应用能力,提高了独立思考的能力。
最后,我要向百忙之中抽时间对本文进行审阅,评议的各位老师表示感谢。
课程论文成绩评定表
质量评价指标(在相应栏目打√)
评 价 项 目
论文与设计评价质量
按对应项目打分
工作量和态度(10分)
分析问题能力(10分)
解决问题能力(10分)
内容完整层次分明(10分)
设计、实验正确性(10分)
书写规范(10分)
流程图或拓扑图(10分)
论证充分(10分)
测试结果情况(10分)
总体评价(10分)
评定成绩(100分制)
指导教师签名
年 月 日
16
展开阅读全文