计算机通信网课程设计手册.docx
《计算机通信网课程设计手册.docx》由会员分享,可在线阅读,更多相关《计算机通信网课程设计手册.docx(23页珍藏版)》请在冰豆网上搜索。
计算机通信网课程设计手册
通信网络系统课程设计手册
河海大学常州校区
目录
课题一:
串口通信1
1、1基本概念1
1、2RS232标准1
1、3串口编程的基本方法2
1、4基于Delphi、net串口类的实现3
课题二:
UDP通信7
2、1UDP协议简介7
2、2、NETUDP编程的基本方法7
2、3基于Delphi、net的UDP发送程序的实现9
课题三:
TCP通信12
3、1TCP协议简介12
3、2、NETTCP编程的基本方法13
3、2、1TcpListener类13
3、2、2TcpClient类13
3、3基于C#、NET的时间服务器的实现13
课题一:
串口通信
随着计算机在工业中的广泛应用,控制局域网络也深入应用到各行各业之中,用串口实现组网是一种较常见且又非常简捷有效的方法。
串口也是仪器仪表设备通用的通信协议,同时,串口通信协议也可以用于获取远程采集设备的数据。
大多数计算机包含两个基于RS232的串口。
1、1基本概念
串口通信的概念非常简单,串口按位(bit)发送和接收数据。
尽管比按字节(byte)传送的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。
对于两个通信的端口,这些参数必须匹配:
a,波特率:
这是一个衡量通信速度的参数。
它表示每秒钟传送的bit的个数。
例如300波特表示每秒钟发送300个bit。
必须注意的是:
波特率和距离成反比,高波特率常常用于放置的很近的仪器间的通信。
b,数据位:
这是衡量通信中实际数据位的参数,标准的值是5、7和8位。
如何设置取决于你想传送的信息。
比如,标准的ASCII码是0~127(7位),那么每个数据包使用7位数据。
c,停止位:
用于表示单个包的最后一位。
典型的值为1,1、5和2位。
由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。
因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。
适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
d,奇偶校验位:
奇偶校验是串口通信中一种简单的检错方式。
有四种检错方式:
偶、奇、高和低。
当然没有校验位也是可以的。
对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。
例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。
如果是奇校验,校验位位1,这样就有3个逻辑高位。
高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。
这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。
1、2RS232标准
现今被广泛运用的通信串口主要有三种,即RS232、RS422和RS485,RS是英文"推荐标准"的首字母缩写,232、422、485是标识号。
计算机串行接口采用RS232标准(如图1、1所示):
规定逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,常用的信号有8个,其中RXD、TXD为收、发数据,可与RS232串行口设备直接进行通讯,RTS、DTR、CD、DSR、CTS、BELL为控制与检测MODEM的信号,在通讯过程中起联络与控制作用,如图1、2所示。
图1、1RS232引脚排列
图1、2RS232引脚功能特性
由于RS232不适合远距离传输,因此后来又提出了RS422和RS485两种标准。
RS422与RS232相比,无论从传输距离还是传输速率上均优于RS232,在1200m的距离传输时,其速率仍可达到100kbps,短距离传输则可达到10Mbps。
它与RS232的最大不同是在其串口上可以挂接多个设备,因此更适合于组网。
在使用时,其接口只有四根线,即TX+,TX-,RX+,RX-,其中TX用于发送,RX则用于接收。
RS422采用的是平衡发送和差分接收的方式,对地线及共模干扰有很强的抑制作用,因此接受的灵敏度很高,检测电压可低至20mV。
还有一种串口是RS485,其实它是RS422的一种特殊形式。
它仅有两根线,即发送和接收各一根;其采用的是半双工结构,任何时候只能有一点处于发送状态,所以它不如RS422灵活。
RS485接口标准是基于考虑在同一线上进行中距离,多接收,多发送而设计产生的数据传送标准,因此,在一条总线上,其允许同时存在32个接收器和32个发送器。
1、3串口编程的基本方法
串行口编程方法主要有三种:
硬件编程法、文件操作法、串口控件法。
1、硬件编程法
直接使用端口的输入、输出(I/O)函数对串行口的控制电路进行编程。
适用于DOS及Windows平台(WindowsMe以前的各版本),但在基于NT技术构建的操作系统(WindowsNT、Windows2000、WindowsXP等)中因不允许用户程序直接操作硬件而不适用。
常用的端口输入、输出函数(指令)有:
汇编语言的IN、OUT指令及软中断调用,C语言的inport()、outport()、inportb()、outportb(),C++的_inp()、_outp()等。
2、文件操作法
文件操作法是将串行口作为系统的一个文件来处理,通过对这个文件的读、写操作引发串口对数据进行收、发动作。
这种方法在DOS、Windows、WindowsNT、Windows2000及WindowsXP等平台下都能正常工作。
在Delphi和VC++中,可用CreateFile()、ReadFile()、WriteFile()等函数将串行口作为文件进行操作。
3、串口控件法
用Delphi、VB及VC++编程时,可用控件对串行口进行编程。
这种方法通用性好,在Windows、WindowsNT、Windows2000及WindowsXP等平台下都能正常工作。
在VB中,使用MSCOMM控件;在VC++下使用MicrosoftCommunicationControl这一ActiveX类控件。
在Delphiwin32下使用SPCOMM控件。
串口控件使用方法请参考相关资料。
1、4基于Delphi、net串口类的实现
下面给出了一个基于Delphi、net2006平台的一个串口通信的类的部分源代码。
只要用串口线将两台PC连接起来,就可以调用该串口类收发数据了。
unitPDP、Common、Comm;
interface
uses
Windows,System、Runtime、InteropServices,
Messages,SysUtils,Classes,
Graphics,Controls,Forms,Dialogs,StdCtrls,ShellAPI,System、ComponentModel,
System、Threading,System、Net,System、Net、Sockets,System、Text;
type
TComm=class
private
{Privatedeclarations}
hComm:
integer;
FPortNum:
integer;//1,2,3,4
BaudRate:
integer;//1200,2400,4800,9600
ByteSize:
byte;//8bits
Parity:
byte;//0-4=no,odd,even,mark,space
StopBits:
byte;//0,1,2=1,1、5,2
ReadTimeout:
integer;//10
FPortName:
String;
lpol:
_OVERLAPPED;
dcbCommPort:
_DCB;
ctoCommPort:
_COMMTIMEOUTS;
procedureClose;
public
{Publicdeclarations}
constructorCreate(APortNum:
Integer);
functionSendMsg(Msg:
String):
Integer;
functionGetMsg(NumBytes:
integer):
string;
destructorDestroy;override;
end;
implementation
//TCOMM类的构造函数,调用时传入COM口的编号如1就可以了。
constructorTComm、Create(APortNum:
Integer);
begin
inheritedcreate;
FPortNum:
=APortNum;
FPortName:
='COM'+FPortNum、ToString;
BaudRate:
=2400;
ByteSize:
=8;
Parity:
=0;
StopBits:
=0;
ReadTimeout:
=100;
try
hComm:
=CreateFile(FPortName,GENERIC_READorGENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
except
showmessage('Unabletoopen'+FPortName+'port!
')
end;
//SETTHECOMMTIMEOUTS、
GetCommTimeouts(hComm,ctoCommPort);
ctoCommPort、ReadTotalTimeoutConstant:
=ReadTimeout;
ctoCommPort、ReadTotalTimeoutMultiplier:
=0;
ctoCommPort、WriteTotalTimeoutMultiplier:
=0;
ctoCommPort、WriteTotalTimeoutConstant:
=0;
SetCommTimeouts(hComm,ctoCommPort);
//SETBAUDRATE,PARITY,WORDSIZE,ANDSTOPBITS、
//THEREAREOTHERWAYSOFDOINGSETTINGTHESEBUTTHISISTHEEASIEST、
//IFYOUWANTTOLATERADDCODEFOROTHERBAUDRATES,REMEMBER
//THATTHEARGUMENTFORBuildCommDCBMUSTBEAPOINTERTOASTRING、
//ALSONOTETHATBuildCommDCB()DEFAULTSTONOHANDSHAKING、
dcbCommPort、DCBlength:
=Marshal、SizeOf(dcbCommPort);
GetCommState(hComm,dcbCommPort);
dcbCommPort、BaudRate:
=BaudRate;
dcbCommPort、Parity:
=Parity;
dcbCommPort、ByteSize:
=ByteSize;
dcbCommPort、StopBits:
=StopBits;
SetCommState(hComm,dcbCommPort);
end;
destructorTComm、Destroy;
begin
Close;
inherited;
end;
procedureTComm、Close;
begin
if(hComm<>INVALID_HANDLE_VALUE)then
begin
CloseHandle(hComm);
end;
end;
//从串口读入消息,返回的是字符串类型。
functionTComm、GetMsg(NumBytes:
integer):
string;
var
BufBytes:
arrayofbyte;
OutBytes:
arrayofbyte;
BytesRead:
cardinal;
i:
integer;
begin
setlength(BufBytes,NumBytes);
try
BytesRead:
=0;
ReadFile(hComm,BufBytes,NumBytes,BytesRead,lpol);
setlength(OutBytes,BytesRead);
forI:
=0toBytesRead-1do
begin
OutBytes[i]:
=BufBytes[i];
end;
except
showmessage('readerror');
end;
Result:
=Encoding、ASCII、GetString(OutBytes);
//showmessage(Result);
//frmSend、Form1、Edit1、Text:
=Result;
end;
//发送消息,传入的参数是字符串格式的消息。
{$UNSAFECODEON}
functionTComm、SendMsg(Msg:
String):
Integer;unsafe;
var
Number:
cardinal;
WriteData:
arrayofbyte;
begin
setlength(WriteData,length(Msg));
WriteData:
=Encoding、ASCII、GetBytes(Msg);
try
WriteFile(hComm,WriteData,length(Msg),Number,lpol);
except
raiseexception、Create('CommWriteError');
end;
Result:
=Number;
end;
end、
课题二:
UDP通信
2、1UDP协议简介
UDP协议是英文UserDatagramProtocol的缩写,即用户数据报协议,主要用来支持那些需要在计算机之间传输数据的网络应用。
包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天,UDP仍然不失为一项非常实用和可行的网络传输层协议。
UDP协议的主要作用是将网络数据流量压缩成数据报的形式。
一个典型的数据报就是一个二进制数据的传输单位。
每一个数据报的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
UDP数据报格式如图2、1所示。
图2、1UDP数据报格式
与我们所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。
根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。
UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。
TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。
与TCP不同,UDP协议并不提供数据传送的保证机制。
如果在从发送方到接收方的传递过程中出现数据报的丢失,协议本身并不能做出任何检测或提示。
因此,通常人们把UDP协议称为不可靠的传输协议。
也许有人会问,既然UDP是一种不可靠的网络协议,那么还有什么使用价值或必要呢?
其实不然,在有些情况下UDP协议可能会变得非常有用,因为UDP具有TCP所望尘莫及的速度优势。
虽然TCP协议中植入了各种安全保障功能,但是在实际执行的过程中会占用大量的系统开销,无疑使速度受到严重的影响。
反观UDP由于排除了信息可靠传递机制,将安全和排序等功能移交给上层应用来完成,极大降低了执行时间,使速度得到了保证。
2、2、NETUDP编程的基本方法
socket是套接字的英文名称,主要是用于网络编程。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
、net的System、Net、Sockets命名空间包含Windows套接字接口的托管实现。
而System、Net命名空间中的所有其他网络访问类都建立在该套接字实现之上,有就是说使用System、Net、Sockets和System、Net命名空间中类可以完成通过socket动态库中的几乎全部功能。
基于、net的UDP编程主要使用UdpClient类实现。
UdpClient类提供了一些简单的方法,用于在阻塞同步模式下发送和接收无连接UDP数据报。
因为UDP是无连接传输协议,所以不需要在发送和接收数据前建立远程主机连接。
但可以选择使用下面两种方法之一来建立默认远程主机:
●使用远程主机名和端口号作为参数创建UdpClient类的实例。
●创建UdpClient类的实例,然后调用Connect方法。
可以使用在UdpClient中提供的任何一种发送方法将数据发送到远程设备。
使用Receive方法可以从远程主机接收数据。
UdpClient方法还允许发送和接收多路广播数据报。
使用JoinMulticastGroup方法可以将UdpClient预订给多路广播组。
使用DropMulticastGroup方法可以从多路广播组中取消对UdpClient的预订。
UdpClient提供的公共方法有:
publicvoidClose();
publicvoidConnect(
System、Net、IPEndPointendPoint
);
publicvoidConnect(
System、Net、IPAddressaddr,
intport
);
publicvoidConnect(
System、Stringhostname,
intport
);
publicvoidDropMulticastGroup(
System、Net、IPAddressmulticastAddr
);
publicvoidJoinMulticastGroup(
System、Net、IPAddressmulticastAddr
);
publicvoidJoinMulticastGroup(
System、Net、IPAddressmulticastAddr,
inttimeToLive
);
publicubyte[]Receive(
System、Net、IPEndPoint&remoteEP
);
publicintSend(
ubyte[]dgram,
intbytes
);
publicintSend(
ubyte[]dgram,
intbytes,
System、Net、IPEndPointendPoint
);
publicintSend(
ubyte[]dgram,
intbytes,
System、Stringhostname,
intport
);
2、3基于Delphi、net的UDP发送程序的实现
下面给出了一个基于Delphi、net2006的UDP发送端的类的部分源代码。
读者只要编写一个UDP接收端的程序,就可以实现基于UDP协议的消息的发送和接收了。
unitPDP、ScoreUdpSock;
interface
uses
System、Threading,Classes,System、Net,System、Net、Sockets,System、Text,Borland、Vcl、Forms;
const
PORT=2007;
type
TPDPUdpSock=class(TThread)
protected
procedureExecute;override;
private
{Privatedeclarations}
udps:
arrayofUdpClient;
ips:
arrayofIPAddress;
ipends:
arrayofIPEndPoint;
byteSend:
arrayofbyte;
PDANums:
Integer;
SendMsg:
String;
public
constructorCreate(PDAIPs:
arrayofString;Msg:
String);
destructorDestroy;override;
end;
implementation
{TPDPUdpSock}
//UDP发送类的构造函数,继承于TThread类。
实现IPEndPoint和UdpClient的初始化等。
输入参数为
(1)UDP接收方:
可以多一个或者多个,是IP地址的动态数组
(2)发送的消息。
constructorTPDPUdpSock、Create(PDAIPs:
arrayofString;Msg:
String);
var
I:
Integer;
begin
PDANums:
=high(PDAIPs)-low(PDAIPs)+1;
SetLength(ips,PDANums);
SetLength(ipends,PDANums);
SetLength(udps,PDANums);
forI:
=low(PDAIPs)tohigh(PDAIPs)do
begin
ips[i]:
=IPAddress、Parse(PDAIPs[i]);
ipends[i]:
=IPEndPoint、Create(ips[i],port);
udps[i]:
=UdpClient、Create;
end;
SendMsg:
=Msg;
inheritedCreate(true);
end;
//UDP发送类的析构函数,实现socket的关闭和释放。
destructorTPDPUdpSock、Destroy;
varI:
Integer;
begin
forI:
=0toPDANums-1do
begin
udps[i]、Close;
ifudps[i]<>Nilthen
udps[i]、Free;
end;
inherited;
end;
//向多个UDP接收方发送消息。
procedureTPDPUdpSock、Execute;
var
I:
Integer;
begin
inherited;
while(notterminated)do
begin
Thread、Sleep(1000);
byteSend:
=Encoding、ASCII、GetBytes(SendMsg);
for