|
摘要:P2P协议是由IETF定义的点对点的通信协议,用来取代串行链路互连网络协议SLIP(SerialLineInternetProtocol),它为在点对点链路上直接相连的两个设备之间提供一种传送数据包的方法。文章阐述了P2P的基本原理,并在Delphi7平台下实现了局域网的语音通信过程。
一、引言
P2P是一种网络模型,在这种模型中所有的节点是对等的(称为对等点),各节点具有相同的责任与能力并协同完成任务。对等点之间通过直接互连共享信息资源、处理器资源、存储资源甚至高速缓存资源等,无需依赖集中式服务器或资源就可完成。这种模式与当今广泛使用的客户端/服务器(C/S)的网络模式形成鲜明对比,C/S模式中服务器是网络的控制核心,而P2P模式的节点则具有很高的自治性和随意性。随着像Napster、Gnutella这种信息共享应用程序变得越来越流行,P2P技术受到人们的广泛关注。实际上,P2P它可分为纯粹的P2P和混合P2P两类。纯粹的P2P模式是指所有参与的计算机都是对等点,各对等点之间直接通讯,自始至终完全没有中心服务器对对等点间的信息交换进行控制、协调或处理。而混合P2P模式则依赖于中心服务器去执行一些功能。
P2P模式相对于C/S模式有一些主要优点。P2P模式最主要的优点就是资源的高度利用率。在P2P网络上,闲散资源有机会得到利用,所有节点的资源总和构成了整个网络的资源,整个网络可以被用作具有海量存储能力和巨大计算处理能力的超级计算机。C/S模式下,即使客户端有大量的闲置资源,也无法被利用。P2P模式相对于C/S模式的主要优点有:
(一)、可靠性高
随着节点的增加,C/S模式下,服务器的负载就越来越重,形成了系统的瓶颈,一旦服务器崩溃,整个网络也随之瘫痪。而在P2P网络中,每个对等体都是一个活动的参与者,每个对等点都向网络贡献一些资源,如存储空间、CPU周期等。所以,对等点越多,网络的性能越好,网络随着规模的增大而越发稳固。
(二)、基于内容的寻址方式处于一个更高的语义层次
因为用户在搜索时只需指定具有实际意义的信息标识而不是物理地址,每个标识对应包含这类信息的节点的集合。这将创造一个更加精炼的信息仓库和一个更加统一的资源标识方法。
(三)、信息在网络设备间直接流动,高速及时,降低中转服务成本
(四)、信息发布灵活
但是,P2P也有不足之处。首先,P2P不易于管理,而对C/S网络,只需在中心点进行管理。随之而来的是P2P网络中数据的安全性难于保证。因此,在安全策略、备份策略等方面,P2P的实现要复杂一些。另外,由于对等点可以随意地加入或退出网络,会造成网络带宽和信息存在的不稳定。
二、P2P通信技术分析与设计方案
图1系统功能模型
系统的基本模型是当通信的双方在通信之前必须进行连接建立过程,即拨号。当连接建立完成时即可进行数据(本文为语音)包的传输,之后双方之一可以申请断开连接,完成一次通信过程。其基本模型如图1所示。
三、点对点语音通信的实现
(一)、实现思路
IP层协议向上层(主要指传输层)提供统一的IP数据包,使得各种物理层的差异对上层协议不再存在。对下层提供标准的网络接口。同时,IP另外的功能还包含寻径、数据块的分组和片的重组、寻找新的路由、差错与控制、路径报错等。IP层作为通讯子网的最高层,提供无连接的数据传输机制。它的协议很简单,不能保证传输的可靠性。IP协议是点到点的协议。IP层对等的实体之间的通信不用中间的机器。在本程序中只做了IP的打包及解包。
该层为传输控制层提供可靠的面向连接的传输。面向连接是在通信之前建立链路,以确保通信的可靠性。建立连接是通过发送和接收双方的三次握手协议来实现的:(假设A机向B机发出请求连接)第一次握手中,A机向B机发送连接请求;第二次,B机收到请求后,发送连接确认信号,其中包B的初始报文序号以及B对A的确认;第三次,A机向B机发送数据,包含对B的初始序号的确认。
另外,作为应用层与网际层的接口,它还提供报文的转发等。将从应用层接收来的数据按协议的标准进行打包,再转发给IP层;对于从IP层来的数据,解包后送到应用层。
根据对TCP、PPP协议的剖析,该程序是在Winsocket的基础上实现TCP/IP三层协议的模拟,包含应用层到TCP层,再到IP层以及网络接口层的模拟,其实也就是按这三层协议进行报文的打包和解包。程序的编制是利用Delphi7提供的ClientSocket和ServerSocket将字符串类型的数据在同一局域网内发送。Socket通信在Windows中是排队的形式,由操作系统处理,而且接收方和发送方相互协同工作,否则就会造成数据丢失。另外,和所有的通信编程一样,SocketSocket编程也遵循数据分包传送这一基本规则。也就是说,在Socket编程中,每次发送和接收一个包,以保证数据传输的安全性和稳定性,同时也不至于过多地占用系统资源。对于ClientSocket组件。它用于请求方。也就是说,它的动作是主动地建立连接。ServerSocket组件用于响应方,它的动作是侦听以及被动接受连接。组件ClientSocket的属性是相对静态的,它和ServerSocket之间只是连接和断开的关系。并且仅当ServerSocket对其接受才表示建立连接。组件ServerSocket的属性是动态的。伴随着一个新的ClientSocket与之建立连接的同时,就会产生一个新的Socket与该ClientSocket对应,保持单独的连接,进行单独的通信。因此,在同一个ServerSocket中,可以与多个ClientSocket保持同时连接和各自独立的通信。ServerSocket的属性Socket。ActiveConnections用于表示客户端连接的数量;属性Socket。Connections[Index]用于访问单个与ClienSocket连接的Socket。在独立的ClientSocket中,属性Socket。Data是一个指针,缺省值是nil;在ServerSocket的每个独立的Socket。Connections[Index]中,属性Data也是一个指针,缺省值是nil。因此,可以通过该指针建立并保存各自独立的相关信息,用于实现各自独立的通信。而在ClientSocket的事件OnRead中,调用方法传递的Socket值就是响应该事件的对象属性ClientSocket.Socket。同样,在ServerSocket的事件OnClientRead中,调用方法传递的参数Socket就是对应于当前发送数据客户端的唯一的Socket连接。
(二)、各功能的实现
1.开机核心代码:
procedureTFormMain.FormCreate(Sender:TObject);//窗口创建
begin
…
UpdateButtons;//更新按钮状态
FormCall:=TFormCall.Create(nil);
FormSelIP:=TFormSelIP.Create(nil);
LoadConfigInfo;
ifFileExists(SocksProxyFile)thenEdSocksIP.Items.LoadFromFile(SocksProxyFile);
ifFileExists(HttpProxyFile)thenEdHttpIP.Items.LoadFromFile(HttpProxyFile);
end;
procedureTFormMain.BtOpenClick(Sender:TObject);//开机按钮
varip,port:string;
begin
…
Listen:=TAudioListenThread.Create(Handle,EdListenPort.Text);//监听线程的创建
withListen.Socketdo
begin
SocksIP:='';//Socks的IP初始值为空
SocksPort:='';//Socks的端口号初始值为空
SocksUsername:='';//Socks的用户名初始值为空
SocksPassword:='';//Socks的密码初始值为空
SocksTimeout:=60000;//Socks的延迟初始值为一分钟
SocksType:=ST_Socks4;//Socks的类型为Socks
HTTPTunnelIP:='';//Socks的IP初始值为空
HTTPTunnelPort:='';//Socks的端口号初始值为空
HTTPTunnelUser:='';//Socks的用户名初始值为空
HTTPTunnelPass:='';//Socks的密码初始值为空
HTTPTunnelTimeout:=60000;//Socks的延迟初始值为一分钟
ifCkSocks.Checkedthen//如果选择Socks代理服务器
begin
ParseIpPort(EdSocksIP.Text,ip,port);//分析Socks的IP和端口号
SocksIP:=ip;//把本机的IP赋值给Socks的IP
SocksPort:=port;//把本机的端口号赋值给Socks的端口号
SocksUsername:=EdSocksUser.Text;//把本机的用户名赋值给Socks的用户名
SocksPassword:=EdSocksPass.Text;//把本机的密码赋值给Socks的密码
ifRbSocks5.CheckedthenSocksType:=ST_Socks5;//如果选择Socks服务类型
end;
ifCkHttp.Checkedthen//如果选择HTTP代理服务器
begin
ParseIpPort(EdHttpIP.Text,ip,port);//分析HTTP的IP和端口号
HTTPTunnelIP:=ip;//把本机的IP赋值给HTTP的IP
HTTPTunnelPort:=port;//把本机的端口号赋值给HTTP的端口号
HTTPTunnelUser:=EdHttpUser.Text;//把本机的用户名赋值给HTTP的用户名
HTTPTunnelPass:=EdHttpPass.Text;//把本机的密码赋值给HTTP的密码
end;
end;
Listen.Resume;
end;
procedureTFormMain.DoListenFinal;//监听终端
begin
Listen:=nil;
IsOpen:=False;//更新按钮设置
UpdateButtons;
StatusBar.Panels[0].Text:='就绪';
LbMyIP.Caption:='本机IP:无';
end;
procedureParseIpPort(constaddr:string;varip,port:string);//分析IP和端口号
vari:Integer;
begin
port:=addr;
i:=Pos(':',port);
ip:=Copy(port,1,i-1);
Delete(port,1,i);
end;
procedureTerminateThread(thread:TThread);//终端线程
begin
ifAssigned(thread)then
begin
thread.Terminate;
tryPostThreadMessage(thread.ThreadID,WM_TERMINATE,0,0);//主要发送消息
exceptend;
end;
end;
procedureTFormSelIP.LsAllIPClick(Sender:TObject);//选择地址窗口
begin
ifLsAllIP.ItemIndex>=0then
LbMySelIP.Caption:='我的选择是:'+LsAllIP.Items[LsAllIP.ItemIndex]
elseLbMySelIP.Caption:='我的选择是:';
end;
procedureTFormMain.BtCloseClick(Sender:TObject);//关机
begin
ifAssigned(Listen)then//如果正在监听
begin
BtClose.Enabled:=False;//关机按钮设置为非
Listen.Terminate;//结束监听
end;
end;
代码所实现的NetPhone开机界面如图2,3所示。
图2开机界面1
图3开机界面2
2..NetPhone通话界面的代码实现:
procedureTFormMain.OnConnected(varms:TMessage);//连接
begin
ATimer.Enabled:=True;
StatusBar.Panels[1].Text:='通话中...';
LbCaller.Caption:='对方IP:'+Sock.GetRemoteSinIP+':'+IntToStr(Sock.GetRemoteSinPort);
Send:=TAudioSendThread.Create(Handle,Sock,tfDoNothing);//发送线程
Send.PhoneOpen:=CkPhone.Checked;
Send.Resume;//发送
OpenAudioIn(Send.ThreadID);
ifAudioInOpenedthenStartAudioInelseShowMessage('打开语音输入设备失败!');
OpenAudioOut(Recv.ThreadID);
ifAudioOutOpenedthenStartAudioOutelseShowMessage('打开语音输出设备失败!');
end;
procedureTFormMain.OnClientConnect(varms:TMessage);//
vars:TDblProxyTcpSocket;
t:TAudioRecvThread;
begin
s:=TDblProxyTcpSocket.Create;
s.Socket:=ms.WParam;
s.GetSins;
ifIsBusythen
begin
t:=TAudioRecvThread.Create(Handle,s,tfDoBusy);//接收线程
t.Resume;
end
elsebegin
IsBusy:=True;
UpdateButtons;//更新按钮设置
ifMessageDlg('是否接听来电?'+s.GetRemoteSinIP+':'+IntToStr(s.GetRemoteSinPort),
mtConfirmation,[mbYes,mbNo],0)=mrYesthen
begin
Sock:=s;
Recv:=TAudioRecvThread.Create(Handle,s,tfDoAgree);//接收线程
Recv.SpeakerOpen:=CkSpeaker.Checked;//接收声音
Recv.Resume;//接收
end
elsebegin
t:=TAudioRecvThread.Create(Handle,s,tfDoRefuse);//接收线程
t.Resume;
IsBusy:=False;//设置为不忙
UpdateButtons;//更新按钮设置
end;
end;
end;
代码所实现的NetPhone的通话界面如图4-5所示。
3.NetPhone挂机的代码实现:
procedureTFormMain.FormClose(Sender:TObject;varAction:TCloseAction);//关闭主窗口
begin
…
end;
procedureTFormMain.BtStopClick(Sender:TObject);//挂机
begin
BtStop.Enabled:=False;//挂机属性设置为非
CloseAudioIn;
CloseAudioOut;
ifAssigned(Recv)thenTerminateThread(Recv);//结束接收线程
ifAssigned(Send)thenTerminateThread(Send);//结束发送线程
ifAssigned(Sock)thenSock.CloseSocket;//结束通信Socks
end;
四、结束语
随着多媒体应用领域的不断扩展,特别是分布式多媒体应用的逐渐成熟,多媒体通信对多媒体通信网络提出了很高的要求。大容量的媒体数据在网上的实时传输对窄带网络和包交换协议提出了挑战。人们一直关注着那些能够满足交互式和实时多媒体通信要求的网络技术的发展。多媒体网络技术的进展将直接影响“信息高速公路”的建设速度,并将对人类的生活和生产方式产生深远的影响。总的来说,P2P行业“创富通宝”算是个中翘楚,它在理财方面,门槛低,收益高,理财100元起,年收益12%-14%,按日付息,随存随取;如果选择开设创业理财账户,最低0费用,开发新客户=10%业务提成+8%-14%奖金+1%业务补贴,工资妙结;另外,还办理贷款项目,信用贷款、担保贷款、抵押贷款、P2P定向贷款,日息0.1%,用几天借几天,灵活快捷,是上班族理财的不二之选。
https://aisshopp.com/create-fortune-attracting-ornaments-to-bring-prosperity-and-wealth-and-let-the-wealth-roll-in/ |
|