【计算机网络】关于三种网络通信模式以及java中三种通信方式的实现介绍

当前的网络中有三种通讯模式:单播、广播、组播(多播),其中的组播出现时间最晚但同时具备单播和广播的优点,最具有发展前景。

一、单播:

主机之间“一对一”的通讯模式,网络中的交换机和路由器对数据只进行转发不进行复制。如果10个客户机需要相同的数据,则服务器需要逐一传送,重复10次相同的工作。但由于其能够针对每个客户的及时响应,所以现在的网页浏览全部都是采用IP单播协议。网络中的路由器和交换机根据其目标地址选择传输路径,将IP单播数据传送到其指定的目的地。

单播的优点:

1.  服务器及时响应客户机的请求

2.  服务器针对每个客户不通的请求发送不通的数据,容易实现个性化服务。

单播的缺点:

1. 服务器针对每个客户机发送数据流,服务器流量=客户机数量×客户机流量;在客户数量大、每个客户机流量大的流媒体应用中服务器不堪重负。

2. 现有的网络带宽是金字塔结构,城际省际主干带宽仅仅相当于其所有用户带宽之和的5%。如果全部使用单播协议,将造成网络主干不堪重负。现在的P2P应用就已经使主干经常阻塞,只要有5%的客户在全速使用网络,其他人就不要玩了。而将主干扩展20倍几乎是不可能。

二、 广播:

主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无条件复制并转发,所有主机都可以接收到所有信息(不管你是否需要),由于其不用路径选择,所以其网络成本可以很低廉。有线电视网就是典型的广播型网络,我们的电视机实际上是接受到所有频道的信号,但只将一个频道的信号还原成画面。在数据网络中也允许广播的存在,但其被限制在二层交换机的局域网范围内,禁止广播数据穿过路由器,防止广播数据影响大面积的主机。

广播的优点:

1. 网络设备简单,维护简单,布网成本低廉

2. 由于服务器不用向每个客户机单独发送数据,所以服务器流量负载极低。

广播的缺点:

1.无法针对每个客户的要求和时间及时提供个性化服务。

2. 网络允许服务器提供数据的带宽有限,客户端的最大带宽=服务总带宽。例如有线电视的客户端的线路支持100个频道(如果采用数字压缩技术,理论上可以提供500个频道),即使服务商有更大的财力配置更多的发送设备、改成光纤主干,也无法超过此极限。也就是说无法向众多客户提供更多样化、更加个性化的服务。

3. 广播禁止在Internet宽带网上传输。

三、组播:

主机之间“一对一组”的通讯模式,也就是加入了同一个组的主机可以接受到此组内的所有数据,网络中的交换机和路由器只向有需求者复制并转发其所需数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择的复制并传输数据,即只将组内数据传输给那些加入组的主机。这样既能一次将数据传输给多个有需要(加入组)的主机,又能保证不影响其他不需要(未加入组)的主机的其他通讯。

组播的优点:

1. 需要相同数据流的客户端加入相同的组共享一条数据流,节省了服务器的负载。具备广播所具备的优点。

2. 由于组播协议是根据接受者的需要对数据流进行复制转发,所以服务端的服务总带宽不受客户接入端带宽的限制。IP协议允许有2亿6千多万个(268435456)组播,所以其提供的服务可以非常丰富。

3. 此协议和单播协议一样允许在Internet宽带网上传输。

组播的缺点:

1.与单播协议相比没有纠错机制,发生丢包错包后难以弥补,但可以通过一定的容错机制和QOS加以弥补。

2.现行网络虽然都支持组播的传输,但在客户认证、QOS等方面还需要完善,这些缺点在理论上都有成熟的解决方案,只是需要逐步推广应用到现存网络当中。

实现:

1、单播(ServerSocket)

(1)服务端

public class TcpServer {

	ServerSocket serverSocket;
	Socket socket;

	InetAddress address;

	public void init() {
		try {
			address=InetAddress.getByName("128.0.0.0");
			serverSocket = new ServerSocket(5656,10,address);

			while (true) {
				System.out.println("waiting...");
				socket = serverSocket.accept();
				new MyThread(socket).start();
				System.out.println("one start");
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	class MyThread extends Thread {
		Socket socket;

		public MyThread(Socket socket) {
			// TODO Auto-generated constructor stub
			this.socket = socket;
		}

		public void run() {
			// TODO Auto-generated method stub
			while (true) {
				try {
					OutputStream outputStream = socket.getOutputStream();
					outputStream.write(("rou wo wo  " + Thread.currentThread()
							.getName()).getBytes());

					try {
						sleep(2000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new TcpServer().init();
	}

}

(2)客户端

public class TcpClient {
	Socket socket;

	public void init() {
		try {
			socket = new Socket("192.0.0.1", 5656);

			while (true) {
				InputStream inputStream = socket.getInputStream();
				int i = 0;
				byte bs[] = new byte[1024];
				while ((i = inputStream.read(bs)) > 0) {
					System.out.println(new String(bs));
				}
			}

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new TcpClient().init();
	}

}

2、单播(DatagramSocket)

(1)端1

public class UdpServer {
	DatagramSocket datagramSocket;
	int port = 7070;
	DatagramPacket outPacket;
	byte[] bs = new byte[1024];
	String ip = "172.22.67.6";
	int i = 0;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new UdpServer().init();
	}

	public void init() {
		try {

			datagramSocket = new DatagramSocket(8002);

			try {
				outPacket = new DatagramPacket(bs, bs.length,
						InetAddress.getByName("127.0.0.1"), 8003);

				while (true) {
					outPacket
							.setData(("jia you nuan wo zi" + (++i)).getBytes());
					datagramSocket.send(outPacket);
					System.out.println("send ~" + i);
					Thread.sleep(2000);

				}

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

(2)端2:

public class UdpClient {
	DatagramSocket datagramSocket;
	int port = 7070;
	DatagramPacket inPacket;
	byte[] bs = new byte[1024];
	String ip = "172.22.67.6";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new UdpClient().init();
	}

	public void init() {

		try {
			datagramSocket =new DatagramSocket(8003,
                    InetAddress.getByName("127.0.0.1"));  

		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		try {
			inPacket = new DatagramPacket(bs, bs.length);
			while (true) {
				datagramSocket.receive(inPacket);
				System.out.println("udp receive " + new String(bs));

			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

3、广播(没有客户端和服务端之分)

(1)端1:

public class MulUdpClient {
	String ip = "230.0.0.0";
	MulticastSocket datagramSocket;
	int port = 5050;
	DatagramPacket inPacket;
	byte[] receive = new byte[1025];
	InetAddress address;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new MulUdpClient().init();
	}

	public void init() {

		try {
			datagramSocket = new MulticastSocket(port);
			address = InetAddress.getByName(ip);
			datagramSocket.joinGroup(address);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		inPacket = new DatagramPacket(receive, receive.length);
		while (true) {
			try {
				System.out.println("wait for server");
				datagramSocket.receive(inPacket);
				System.out.println("receive " + new String(receive));

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}

(2)端2:

public class MulUdpServer {
	MulticastSocket multicastSocket;
	String ip = "230.0.0.0";
	int port = 5050;
	InetAddress socketAddress;
	DatagramPacket datagramPacket;
	int i = 0;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new MulUdpServer().initServer();
	}

	public void initServer() {
		try {
			multicastSocket = new MulticastSocket(port);
			socketAddress = InetAddress.getByName(ip);
			multicastSocket.joinGroup(socketAddress);

			multicastSocket.setLoopbackMode(false);

			datagramPacket = new DatagramPacket(new byte[0], 0, socketAddress,
					port);

			new Thread() {
				public void run() {
					// TODO Auto-generated method stub
					while (true) {

						try {
							try {
								datagramPacket
										.setData(("wo ai ni dudu " + (++i))
												.getBytes());
								multicastSocket.send(datagramPacket);
								System.out.println("send success!" + i);
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							Thread.sleep(2000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}.start();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
时间: 2024-11-10 08:57:02

【计算机网络】关于三种网络通信模式以及java中三种通信方式的实现介绍的相关文章

Java中13种设计模式汇总

设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等(转)

Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互斥锁 / 读写锁 乐观锁 / 悲观锁 分段锁 偏向锁 / 轻量级锁 / 重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释. 公平锁 / 非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公

Java 中几种常用的线程池

Java 中几种常用的线程池 转载 : https://www.cnblogs.com/sachen/p/7401959.html 原创 2016年04月14日 23:29:01 标签: java / 线程池 / Executor 878 概述: 在java内置API中操作线程所用到的类为Thread.创建线程一般有两种方式, 继承Thread方式 实现Runnable方式,并以runnable作为target创建Thread 在Android中的耗时任务一般都需要另开线程来执行,常常需要用线程

java中四种引用类型

java中四种引用类型  今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在网上查资料,感觉收获颇多,现记录如下. 对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地

JAVA 中两种判断输入的是否是数字的方法__正则化_

JAVA 中两种判断输入的是否是数字的方法 package t0806; import java.io.*; import java.util.regex.*; public class zhengzehua_test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try { System.out.println("请输入第一个数字:"

java中两种添加监听器的策略

/*第一种:将事件的处理委托给其他对象,下面的例子是委托给了MyListener(implements ActionListener)*/ 1 import java.applet.Applet; 2 import java.awt.event.*; 3 import java.awt.*; 4 public class ChangeColor extends Applet{//Applet的默认布局为FlowLayout方式 5 Color myColor; 6 String str; 7 B

java中4种修饰符访问权限的区别及详解全过程

java中4种修饰符访问权限的区别及详解全过程 http://jingyan.baidu.com/article/fedf0737700b3335ac8977ca.html java中4中修饰符分别为public.protect.default.private,他们这就说明了面向对象的封装性,所以我们要适用他们尽可能的让权限降到最低,从而安全性提高. 下面详细讲述下它们的访问权限问题.(同一个类中除内部类外所有修饰符都是可以访问的,所以下面排除这种情况.) 首先在这里把它们的访问权限表示出来:

Java中两种动态代理的实现

本文介绍了java中两种动态代理的实现方法,Spring的动态代理也是基于这两种方法的.直接附上源码: 1.JDK实现 使用JDK实现动态代理必须使用接口 接口Work.java public interface Work { public void work(); } 实现类WorkImpl.java public class WorkImpl implements Work { @Override public void work() { System.out.println("我在工作&q

转载:Java中的字符串常量池详细介绍

引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池,需要的朋友可以参考下 Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new Stri