`
yu06206
  • 浏览: 111514 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

通信总结——浅谈P2P通信

阅读更多

                               浅谈P2P通信

什么是p2p?

定义一:p2p是一种通信模式,其中参与者都有相同的能力。在Internet上,p2p是一种网络类型,它允许相同网络程序的计算机相互连接,直接访问对方的硬盘文件。

定义二:p2p(peer-to-peer)是一种对等网络计算机技术,利用客户端的处理能力,实现客户端的点对点通信。

注:说白了,就是点对点通信。

一个概念—NAT

    NAT是Net Address Translation(网络地址转换)的简称,就是说,局域网通常靠一个具有公网IP的代理网关服务器Internet共享上网。局域网内的机器并不具备公网IP地址,它只有内网地址,假设它要和Internet上的HTTP服务器通信,代理网关便会新建一个端口来和这个网内机器关联,并通过这个端口来和HTTP服务器交换数据。最终,网内机器-> 代理网关-> HTTP服务器,在一个会话期间,各自的端口保持了映射关系,特别是代理网关和网内机器的端口映射,使得代理网关不会把接收到的数据向网内转发时,发错了机器。 

    局域网内的机器在网关处,就是靠NAT来映射端口并实现Internet连接,因此,NAT也直接被称为“端口映射”。端口映射之后,在一个会话期间保持,对于TCP连接是直到连接断开才销毁,而对于UDP,却存在一个不定的生存期,例如2秒。     我们再来分析一下上课老师提出的一个问题,就是服务器受到客户端发送过来的一条消息,然后要回复消息,服务器怎么知道局域网内某台客户机的IP地址呢?这主要是在局域网的网关处存在一个叫NAT的东西,NAT能够映射处客户机的IP然后准确的发送给服务器

实现P2P

如果两个局域网内的服务器要进行p2p通信,有四种方法:

第一:实现局域网内的数据链路层协议,就是写一个类似于TCP/IP的协议,由它来代替Windows系统里的TCP/IP协议,由它直接基于网卡硬件获取数据。这是十分复杂的。 

第二:用Internet上的公网服务器中转数据,但对于大数据量的中转,显然受到服务器和网络的负载极限的限制。 

第三:依靠Internet上的公网服务器做“媒人”,将这两台分别处于不同局域网的机器相互介绍给对方,在它们建立连接之后,服务器即脱离关系。这种方式下,服务器把A的NAT端口映射关系告诉B,又把B的NAT端口映射关系告诉A,这样AB相互知道对方的端口映射关系之后,就能建立连接。因为A和B各自的端口映射关系是靠各自的代理网关动态建立的,动态建立的映射端口不得不告知对方。 

第四:上面的第三种办法,也可以采用静态端口映射方式,这样就不需要中介服务器对A和B做介绍。在各方的代理网关上,可以在代理工具里将某个端口(如1350)和局域网内的某台机器(如内网IP为200.200.200.100,端口1360)做好静态映射,这样,代理网关会自动地将出入于1350端口的数据发往200.200.200.100的1360端口。当然,通信之前,必须对对方的端口映射关系做配置。有多少台网内机器要通信,就得映射多少个不同的端口,同时在另一个局域网内的机器就要做多少个配置。在局域网内搭建HTTP、FTP等服务器就是通过静态映射端口来实现的,这个端口一般不是HTTP、FTP的默认80和23,所以对这类站点的访问往往会在URL里加上端口号。 

    前面两种方法当然是不可行的,我们了解的一般是第三,第四种方法,第三种动态映射端口,需要增加中间服务器,第四种静态映射端口,在需要通信的各方机器很多的情况下,做手工端口映射和配置都是很繁琐的,并且一方添加一台机器,就需要在其余对方增加配置。 向我们平常用的很多软件已经实现了P2P通信,比如著名的有MSN、QQ和BitTorrent下载软件,

    P2P要解决的唯一技术难题是如何发现、定位和寻址对方,就是如何穿透NAT、HTTP、Sock等代理和如何穿透方并建立起防火墙找到对通信的问题。由于绝大多数局域网是NAT代理结构,所以前面对NAT论述比较详细,也是网上讨论最多的话题,相比之下,穿透Http、Sock代理就简单一些。此外,穿透NAT发现对等点的办法还有一些,例如多播,但由于现有Internet对多播并不友好,同时多播是无连接和不可靠的,其实现有难度。

下面附一段我P2P代码测试:

 

package P2PTest;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * UDP P2P测试客户机:发送消息,接收服务器发来的消息
 * 
 * @author yujing
 * 
 */
public class DatagramINetClient extends Thread {
	// 公网服务器地址
	private SocketAddress destAdd = new InetSocketAddress(" 192.168.1.121",
			10000);
	private DatagramSocket sendSocket;// 发送Socket对象
	// 显示接收到消息的组件
	private JTextArea jta_recive = new JTextArea(10, 25);
	private JComboBox jcb_addList = new JComboBox();// 其他客户机的地址显示

	public DatagramINetClient() {
		try {
			sendSocket = new DatagramSocket();
		} catch (Exception e) {
		}
	}

	public void run() {
		try {
			while (true) {
				byte[] recvData = new byte[1024];
				// 创建接收数据包对象
				DatagramPacket recvPacket = new DatagramPacket(recvData,
						recvData.length);
				System.out.println("等待接收数据到来。。。");
				sendSocket.receive(recvPacket);
				byte[] data = recvPacket.getData();
				System.out.println("收到数据:" + new String(data).trim());
				// 读到信息
				ByteArrayInputStream bins = new ByteArrayInputStream(data);
				ObjectInputStream oins = new ObjectInputStream(bins);
				Object dataO = oins.readObject();
				if (dataO instanceof Set) {// 服务器端的地址列表
					Set<InetSocketAddress> othersAdds = (Set<InetSocketAddress>) dataO;
					jcb_addList.removeAllItems();
					// 将收到的地址列表加入到界面下拉框中
					for (InetSocketAddress it : othersAdds) {
						jcb_addList.addItem(it);

					}

				} else if (dataO instanceof String) {
					String s = (String) dataO;
					// 显示你到界面
					jta_recive.append(s + "\r\n");
				} else {
					String s = "unknown msg:" + dataO;
					jta_recive.append(s + "\r\n");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sendP2PMsg(String msg, InetSocketAddress dest) {
		try {
			ByteArrayOutputStream bous = new ByteArrayOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(bous);
			oos.writeObject(msg);
			oos.flush();
			byte[] data = bous.toByteArray();
			DatagramPacket dp = new DatagramPacket(data, data.length, dest);
			sendSocket.send(dp);
			System.out.println("已发送一条点对点消息to:" + dest);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void sendRequestMsg(String msg) {
		try {
			byte[] buffer = msg.getBytes();
			DatagramPacket dp = new DatagramPacket(buffer, buffer.length,
					destAdd);
			sendSocket.send(dp);
			System.out.println("已发送给服务器:" + msg);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 显示主界面
	public void setUpUI() {
		JFrame frame = new JFrame();
		frame.setTitle("P2P测试——客户端");
		frame.setLayout(new FlowLayout());
		frame.setSize(300, 300);
		JButton button = new JButton("获取其他客户及地址");
		frame.add(button);
		frame.add(jcb_addList);
		// 发送请求给服务器端的其他客户及列表信息
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				sendRequestMsg("取得地址");

			}
		});
		// 用户名密码标签
		JLabel la_name = new JLabel("接收到的消息");
		JLabel la_users = new JLabel("发送给:");
		final JTextField jtf_send = new JTextField(20);// 发送输入框
		JButton bu_send = new JButton("Send");
		frame.add(la_name);
		frame.add(jta_recive);
		frame.add(la_users);
		frame.add(jtf_send);
		frame.add(bu_send);
		// 发送事件监听
		ActionListener al = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String msg = jtf_send.getText();
				// 得到选中的目标地址
				InetSocketAddress dest = (InetSocketAddress) jcb_addList
						.getSelectedItem();
				sendP2PMsg(msg, dest);
				jtf_send.setText("");

			}
		};
		bu_send.addActionListener(al);
		jtf_send.addActionListener(al);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(3);

	}

	// 主函数
	public static void main(String[] args) {
		DatagramINetClient sender = new DatagramINetClient();
		sender.start();
		sender.setUpUI();
	}

}
package P2PTest;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;

/**
 * UDP P2P测试通信转发服务器:接收,转发消息
 * @author yujing
 *
 */
public class DatagramRouteServer {
	//存放所有客户机地址的队列
	private Set<InetSocketAddress> clientAddSet = new HashSet<InetSocketAddress>();
	//启动接收的UDP端口服务器
	public void startServer() throws Exception{
		DatagramSocket socket=new DatagramSocket(10000);
		System.out.println("UDP服务器等待接收数据:"+socket.getLocalSocketAddress());
		while(true){
			//指定接收缓冲区大小
			byte[] buffer=new byte[256];
			//创建接收数据包对象
			DatagramPacket packet=new DatagramPacket(buffer, buffer.length);
			//阻塞等待数据到来,如果数据,存入packet中的缓冲区
			socket.receive(packet);
			//得到发送方得IP地址和端口号
			InetAddress clientAdd=packet.getAddress();
			int cientPort=packet.getPort();
			InetSocketAddress address=new InetSocketAddress(clientAdd, cientPort);
			//将这个地址加入到队列中
			clientAddSet.add(address);
			byte[] recvData=packet.getData();//取得数据
			//去掉空格
			String s=new String(recvData).trim();
			//接收到后,打印出收到的数据长度
			System.out.println("服务器收到数据:"+s+"form:"+address);
			for(InetSocketAddress dclient:clientAddSet){
				String temf=address+",到服务器取数据!";
				//转发服务器的地址和端口列表数据
				ByteArrayOutputStream bous=new ByteArrayOutputStream();
				ObjectOutputStream oos=new ObjectOutputStream(bous);
				oos.writeObject(temf);
				oos.flush();
				byte[] data=bous.toByteArray();
				DatagramPacket mp=new DatagramPacket(data, data.length);
				mp.setSocketAddress(dclient);//发送给客户端地址
				socket.send(mp);
			}
			//转发服务器断的地址列表数据
			ByteArrayOutputStream bous=new ByteArrayOutputStream();
			ObjectOutputStream oos=new ObjectOutputStream(bous);
			oos.writeObject(clientAddSet);
			oos.flush();
			byte[] data=bous.toByteArray();
			//发送服务器段保存的各个客户机的地址信息
			DatagramPacket sendp=new DatagramPacket(data, data.length);
			sendp.setSocketAddress(address);
			socket.send(sendp);
		}
	}
	/**
	 * 启动主函数
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		DatagramRouteServer reciver=new DatagramRouteServer();
		reciver.startServer();
	}
	 

}

 

分享到:
评论

相关推荐

    UDP_P2P通信对话框程序——VS2010版

    UDP_P2P通信对话框程序是基于Visual Studio 2010和Winsock库开发的,主要用于实现点对点(Peer-to-Peer)通信。在本文中,我们将深入探讨UDP_P2P通信的关键知识点,以及如何利用Winsock库在C++环境中构建这样的应用...

    p2p通信软件

    P2P(Peer-to-Peer)通信软件是一种网络通信模型,它允许网络中的各个节点(称为对等点或peer)直接交互,而不需要通过中央服务器进行数据交换。这种技术最初在文件分享领域得到广泛应用,如Napster、Gnutella和...

    浅谈互联网金融风险——某P2P公司风险管理现状分析研究.pdf

    互联网金融风险是当前金融行业高度关注的议题,尤其是P2P(Peer-to-Peer)借贷模式,它是在互联网金融背景下快速发展起来的一种新型金融业态。P2P借贷模式允许借贷双方直接通过互联网平台进行借贷,大大降低了传统...

    实现P2P网络通信.rar

    《实现P2P网络通信——基于Java的深度解析》 P2P(Peer-to-Peer)网络通信是一种去中心化的网络架构,其中每个节点既是服务的提供者也是服务的消费者。这种模式在分布式系统、文件共享、流媒体传输等领域有着广泛...

    JXTA——Java P2P网络编程技术.zip

    **JXTA(Java eXtensible ...总结起来,JXTA是Java开发者构建P2P网络应用的强大工具,通过学习和实践,开发者不仅可以掌握P2P网络的基本概念和技术,还能利用JXTA提供的API高效地开发出复杂且具有弹性的分布式系统。

    浅谈p2p网络平台风险控制-信用风险-经济.pdf

    浅谈P2P网络平台风险控制-信用风险-经济 P2P网络平台风险控制是互联网金融行业的一个重要话题。随着P2P网络平台的发展,风险控制变得越来越重要。本文将从信用风险、信息不对称风险、市场流动性风险、技术风险和...

    JXTA——Java P2P网络编程技术

    **JXTA——Java P2P网络编程技术** JXTA(Java XML-based Peer-to-Peer Technology)是由Sun Microsystems开发的一种开放源代码平台,旨在提供一种基于XML的、跨平台的P2P(Peer-to-Peer)网络协议。P2P网络是一种...

    stm32控制nfc(PN532)模块进行P2P(点对点)通信程序

    STM32控制NFC(PN532)模块进行P2P通信是嵌入式系统中一项关键的技术,尤其在物联网(IoT)应用中,它允许设备间直接交换数据,无需中间媒介。PN532是NXP公司生产的一款高性能、低功耗的NFC/RFID控制器,广泛用于各种...

    ASP网站实例开发源码——云网支持P2P生成HTML电影系统第2版(源码+数据库).rar

    在视频流媒体领域,P2P能够分担服务器的带宽压力,通过用户之间的直接共享来传输数据,从而提高整体的传输效率和观看体验。在这个电影系统中,P2P技术可能被用于影片的分发,使得用户在观看影片时也能上传内容给其他...

    浅谈P2P网络借贷大数据风险控制体系的构建.zip

    本文将围绕“浅谈P2P网络借贷大数据风险控制体系的构建”这一主题,深入探讨如何利用大数据技术来建立有效的风险防控机制。 首先,大数据在风险识别中的作用至关重要。P2P网络借贷涉及海量的交易数据,包括借款人的...

    java实现p2p通信

    ### Java实现P2P通信的关键知识点 #### 一、P2P通信模型及关键技术分析 ##### (一)信息的传递 **1. P2P通信模型** P2P(Peer-to-Peer)通信模型是一种分布式网络架构,其中的每一个节点既是服务的提供者也是...

    论文研究-基于对等组的P2P安全通信机制.pdf

    提出了一种基于对等组实现的P2P安全通信机制——P2PSCM。P2PSCM首先为通信节点构建安全对等组。组内节点相互通信时,先通过交换公私密钥和对称密钥建立节点间安全通信渠道;然后采用对称密钥加密传输数据;最后对...

    p2p通信过程自编程序

    总结起来,这个项目通过VC++实现了P2P通信的客户端和服务器模拟,涉及了网络协议设计、异常处理和NAT穿透等关键技术,对于理解P2P网络的运作机制非常有帮助。通过分析和运行这个程序,开发者可以深入了解P2P网络的...

    p2p通信语音设计

    P2P(Peer-to-Peer)通信是一种网络通信模型,其中每个参与者既是客户端也是服务器,直接与其他参与者交换数据,无需中心服务器。在这个场景下,我们讨论的是使用Microsoft Foundation Class(MFC)库来实现的P2P...

    C#实现P2P视频通信

    在IT领域,P2P(Peer-to-Peer)视频通信是一种流行的技术,它允许用户之间直接交换音视频数据,而无需通过中央服务器。本实例主要关注如何使用C#编程语言来实现这一功能,这对于初学者来说是一次很好的学习机会。...

    p2p通信 利用IP识别进行通信

    标题中的“p2p通信 利用IP识别进行通信”是指使用点对点(Peer-to-Peer,简称P2P)技术,通过网络中各节点的IP地址进行直接通信的技术。这种通信方式允许两个或多个计算机节点之间直接交换数据,而无需通过中心...

Global site tag (gtag.js) - Google Analytics