【网络编程3】Java组播套接字
2016-06-14 23:21
741 查看
这篇博文是本文学习《Java网络程序设计》书中第5章中组播套接字的学习总结。所有源代码都在文章后面我的github链接代码中。
——惠州学院13网络工程 吴成兵 20160612
一 组播套接字概述
二 MulticastSocket
21 MulticastSocket构造方法
22MulticastSocket常用方法
三 组播套接字编程
31 使用组播套接字发送数据的过程
32 使用组播套接字接收数据的过程
四 组播套接字编程示例
41 组播套接字发送和接收程序
411 发送端
412 接收端
42 组播应用英汉词典
421 广播端
422 接收端
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/19/74d696fc033c633d1f2cd8ec6aa3837c)
DatagramSocket只允许数据报包发送给指定的目的地址,而MulticastSocket则可以将数据报包以广播方式发送到数量不等的多个接收端。若要使用多点广播,则需要让一个数据报包标有组目标主机地址,当数据报包发出后,整个组的所有主机都能收到该数据报包。IP多点广播(或多点发送)实现了将单一信息发送到多个接收端的广播,其思想是设置一个特殊网络地址作为多点广播地址,每一个要收到多点广播地址都被看做一个组,接收端需要接收广播信息时,加入到组即可,发送端则向每组发送数据报包。IP协议为多点广播提供了这批特殊的IP地址,这些IP地址的范围是224.0.0.0~239.255.255.255。
MulticastSocket是DatagramSocket的一个子类,扩展了DatagramSocket类的一些方法,就有权访问DatagramSocket的方法。
public MulticastSocket() throws IOException :使用本机默认地址、随机端口来创建一个MulticastSocket对象,用于发送端。(同上面构造方法port=0的情况)
public MulticastSocket(SocketAddress bindaddr) throws IOException :使用本机指定地址、指定端口来创建一个MulticastSocket对象。
public void leaveGroup(InetAddress mcastaddr) throws IOException :如果不想接收组播包了,就调用leaveGroup方法。程序就发信息到组播路由器,通知它停止向此用户发送数据。
public void send(DatagramPacket p) throws IOException :和DatagramSocket发送数据的方法相似。
public synchronized void receive(DatagramPacket p) throws IOException :和DatagramSocket接收数据的方法相似。
@Deprecated
public void send(DatagramPacket p, byte ttl) throws IOException:和DatagramSocket发送数据的方法相似,其中ttl是生存时间,大小在0~255之间。
public void setTimeToLive(int ttl) throws IOException :设置套接字发出的组播包中的默认ttl数值。
public int getTimeToLive() throws IOException :返回ttl数值。
MultiSocket比DatagramSocket多了setTimeToLive(int ttl)方法,该ttl参数设置数据报包最多可以跨过多少个网络:
当ttl为0时,指定数据报包应停留在本地主机;
当ttl为1时,指定数据报包应发送到本地局域网;(默认情况下)
当ttl为32时,意味着数据报包应发送到本站点的网络上;
当ttl为64时,意味着数据报包应保留在本地区;
当ttl为128时,意味着数据报包应保留在本大洲;
当ttl为255时,意味着数据报包可以发送到所有地方。
创建DatagramPacket数据报。
调用MulticastSocket类的send()方法发送组播包。
关闭组播套接字。
发送送组播包的代码如下:
调用MulticastSocket类的joinGroup()方法加入一个组播组。
创建DatagramPacket数据报。
调用MulticastSocket类的receive()方法接收组播包。
调用MulticastSocket类的leaveGroup()方法离开该组播组。
关闭组播套接字。
接收送组播包的代码如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/19/0a3502c6af19a872e2aefe17621743fe)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/19/c4e62afdc290ef5e627bfeedce471601)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/19/99f898951b57f81ca295a882e4a53fea)
文中所有源代码链接
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《Java组播套接字》:
http://blog.csdn.net/u014134180/article/details/51675461
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/09/41eb9709344917033e1b973b7bafe911)
如果你看完这篇博文,觉得对你有帮助,并且愿意付赞助费,那么我会更有动力写下去。
返回到目录 ↩
——惠州学院13网络工程 吴成兵 20160612
目录 1
目录 1一 组播套接字概述
二 MulticastSocket
21 MulticastSocket构造方法
22MulticastSocket常用方法
三 组播套接字编程
31 使用组播套接字发送数据的过程
32 使用组播套接字接收数据的过程
四 组播套接字编程示例
41 组播套接字发送和接收程序
411 发送端
412 接收端
42 组播应用英汉词典
421 广播端
422 接收端
一 组播套接字概述
前面两篇博客介绍了发送端程序线程发送单一的消息(通过流套接字和数据报套接字)给唯一的接收端程序,这种行为被称为单点传送(unicasting)。如果发送端程序要将同一信息发送给多个接收端,那么发送端程序和接收端程序可以利用多点传送(multicasting)方式进行通信。多点传送就是发送端程序对专用的多点传送组的IP地址和端口发送一系统自寻址数据包,通过加入操作IP地址被多点传送Socket注册,通过这个点,客户程序可以接收发送给组的自寻址包(同样接收端程序也可以给这个组发送自寻址包),一旦客户程序读完所有要读的自寻址数据包,那么可以通过离开组操作多点传送组。DatagramSocket只允许数据报包发送给指定的目的地址,而MulticastSocket则可以将数据报包以广播方式发送到数量不等的多个接收端。若要使用多点广播,则需要让一个数据报包标有组目标主机地址,当数据报包发出后,整个组的所有主机都能收到该数据报包。IP多点广播(或多点发送)实现了将单一信息发送到多个接收端的广播,其思想是设置一个特殊网络地址作为多点广播地址,每一个要收到多点广播地址都被看做一个组,接收端需要接收广播信息时,加入到组即可,发送端则向每组发送数据报包。IP协议为多点广播提供了这批特殊的IP地址,这些IP地址的范围是224.0.0.0~239.255.255.255。
二 MulticastSocket ##
public class MulticastSocket extends DatagramSocket
MulticastSocket是DatagramSocket的一个子类,扩展了DatagramSocket类的一些方法,就有权访问DatagramSocket的方法。
2.1 MulticastSocket构造方法
public MulticastSocket(int port) throws IOException :使用本机默认地址、指定端口来创建一个MulticastSocket对象,用于接收端或发送端。public MulticastSocket() throws IOException :使用本机默认地址、随机端口来创建一个MulticastSocket对象,用于发送端。(同上面构造方法port=0的情况)
public MulticastSocket(SocketAddress bindaddr) throws IOException :使用本机指定地址、指定端口来创建一个MulticastSocket对象。
2.2MulticastSocket常用方法
public void joinGroup(InetAddress mcastaddr) throws IOException :建立了MultiSocket对象后,要发送或接收组播包,必须用joinGroup方法加入一个组播组。public void leaveGroup(InetAddress mcastaddr) throws IOException :如果不想接收组播包了,就调用leaveGroup方法。程序就发信息到组播路由器,通知它停止向此用户发送数据。
public void send(DatagramPacket p) throws IOException :和DatagramSocket发送数据的方法相似。
public synchronized void receive(DatagramPacket p) throws IOException :和DatagramSocket接收数据的方法相似。
@Deprecated
public void send(DatagramPacket p, byte ttl) throws IOException:和DatagramSocket发送数据的方法相似,其中ttl是生存时间,大小在0~255之间。
public void setTimeToLive(int ttl) throws IOException :设置套接字发出的组播包中的默认ttl数值。
public int getTimeToLive() throws IOException :返回ttl数值。
MultiSocket比DatagramSocket多了setTimeToLive(int ttl)方法,该ttl参数设置数据报包最多可以跨过多少个网络:
当ttl为0时,指定数据报包应停留在本地主机;
当ttl为1时,指定数据报包应发送到本地局域网;(默认情况下)
当ttl为32时,意味着数据报包应发送到本站点的网络上;
当ttl为64时,意味着数据报包应保留在本地区;
当ttl为128时,意味着数据报包应保留在本大洲;
当ttl为255时,意味着数据报包可以发送到所有地方。
三 组播套接字编程
3.1 使用组播套接字发送数据的过程
调用MulticastSocket()创建一个组播套接字。创建DatagramPacket数据报。
调用MulticastSocket类的send()方法发送组播包。
关闭组播套接字。
发送送组播包的代码如下:
package _5_3组播套接字; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; public class MCServer { public static void main(String[] args) throws IOException { System.out.println("Server starting..."); MulticastSocket s = new MulticastSocket(); InetAddress group = InetAddress.getByName("231.0.0.1"); byte[] dummy = new byte[0]; DatagramPacket dgp = new DatagramPacket(dummy, 0, group, 10000); for (int i = 0; i < 30000; i++) { byte[] buffer = ("Video line " + i).getBytes(); dgp.setData(buffer); dgp.setLength(buffer.length); s.send(dgp); } } }
3.2 使用组播套接字接收数据的过程
调用MulticastSocket()创建一个组播套接字。调用MulticastSocket类的joinGroup()方法加入一个组播组。
创建DatagramPacket数据报。
调用MulticastSocket类的receive()方法接收组播包。
调用MulticastSocket类的leaveGroup()方法离开该组播组。
关闭组播套接字。
接收送组播包的代码如下:
package _5_3组播套接字; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; public class MCClient { public static void main(String[] args) throws IOException { MulticastSocket s = new MulticastSocket(10000); InetAddress group = InetAddress.getByName("231.0.0.1"); s.joinGroup(group); for (int i = 0; i < 10; i++) { byte[] buffer = new byte[256]; DatagramPacket dgp = new DatagramPacket(buffer, buffer.length); s.receive(dgp); byte[] buffer2 = new byte[dgp.getLength()]; System.arraycopy(dgp.getData(), 0, buffer2, 0, dgp.getLength()); System.out.println(new String(buffer2)); } s.leaveGroup(group); s.close(); } }
四 组播套接字编程示例
4.1 组播套接字发送和接收程序
发送端发送的中文数据要用UTF-8格式,否则接收端将会收到乱码。4.1.1 发送端
package _07实验七_组播编程.MulticastProject2.test; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.util.Date; /** * Copyright ? 2016 Authors. All rights reserved. * * FileName: .java * @author : Wu_Being <1040003585@qq.com> * Date/Time: 2016-6-14/下午08:46:39 * Description: 组播的服务端 */ public class MulticastSender_UTF8 { public static void server() throws Exception{ InetAddress group = InetAddress.getByName("239.1.2.3");//组播地址 int port = 22363; MulticastSocket mss = null; try { mss = new MulticastSocket(port); mss.joinGroup(group); System.out.println("发数据包启动!(启动时"+new Date()+")"); while(true){ String message = "Hello,你的电脑已中毒##"+new Date(); byte[] buffer = message.getBytes(); DatagramPacket dp = new DatagramPacket(buffer, buffer.length,group,port); mss.send(dp); System.out.println("发数据("+message+")包给 "+group+":"+port); Thread.sleep(1); } } catch (Exception e) { e.printStackTrace(); }finally{ try { if(mss!=null){ mss.leaveGroup(group); mss.close(); } } catch (Exception e2) { // TODO: handle exception } } } public static void main(String[] args) throws Exception { server(); } }
4.1.2 接收端
package _07实验七_组播编程.MulticastProject2.test; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.util.Date; /** * * Copyright ? 2016 Authors. All rights reserved. * * FileName: .java * @author : Wu_Being <1040003585@qq.com> * Date/Time: 2016-6-14/下午10:16:44 * Description: */ public class MulticastReceive_UTF8 { public static void main(String[] args) throws Exception { test(); } public static void test() throws Exception{ InetAddress group = InetAddress.getByName("239.1.2.3");//组播地址 int port = 22363; MulticastSocket msr = null;//创建组播套接字 try { msr = new MulticastSocket(port); msr.joinGroup(group);//加入连接 byte[] buffer = new byte[8192]; System.out.println("接收数据包启动!(启动时间: "+new Date()+")"); while(true){ //建立一个指定缓冲区大小的数据包 DatagramPacket dp = new DatagramPacket(buffer, buffer.length); msr.receive(dp); String s = new String(dp.getData(),0,dp.getLength()); //解码组播数据包 System.out.println("收到"+dp.getSocketAddress()+"数据("+s+")"); } } catch (Exception e) { e.printStackTrace(); }finally{ if(msr!=null){ try { msr.leaveGroup(group); msr.close(); } catch (Exception e2) { // TODO: handle exception } } } } }
4.2 组播应用:英汉词典
4.2.1 广播端
package _5_4组播套接字编程示例._5_4_2组播应用_英汉词典; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.FileDialog; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Panel; import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Timer; /** * * @author geek */ @SuppressWarnings("serial") public class BroadCastWord extends Frame implements ActionListener { int port; InetAddress group = null; MulticastSocket socket = null; Timer time = null; FileDialog open = null; Button select, startBroadCast, stopBroadCast; File file = null; String fileDir = null, fileName = null; FileReader in = null; BufferedReader br = null; int token = 0; TextArea showPlaying, showPlayed; public BroadCastWord() { super("单词广播系统"); select = new Button("Select to broadcast file"); startBroadCast = new Button("start broadcast"); stopBroadCast = new Button("stop broadcast"); startBroadCast.addActionListener(this); startBroadCast.setEnabled(false); select.addActionListener(this); stopBroadCast.addActionListener(this); stopBroadCast.setEnabled(false); time = new Timer(2000, this); open = new FileDialog(this, "选择要广播的文件", FileDialog.LOAD); showPlaying = new TextArea(10, 10); showPlaying.setForeground(Color.blue); showPlayed = new TextArea(10, 10); Panel north = new Panel(); north.add(select); north.add(startBroadCast); north.add(stopBroadCast); add(north, BorderLayout.NORTH); Panel center = new Panel(); center.setLayout(new GridLayout(1, 2)); center.add(showPlaying); center.add(showPlayed); add(center, BorderLayout.CENTER); validate(); port = 5000; try { group = InetAddress.getByName("239.255.0.0"); socket = new MulticastSocket(port); socket.setTimeToLive(1); socket.joinGroup(group); } catch (UnknownHostException ex) { Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); } setBounds(100, 50, 360, 380); setVisible(true); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } public static void main(String[] args) { new BroadCastWord(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == select) { showPlayed.setText(null); open.setVisible(true); fileName = open.getFile(); fileDir = open.getDirectory(); file = new File(fileDir, fileName); try { in = new FileReader(file); br = new BufferedReader(in); startBroadCast.setEnabled(true); } catch (FileNotFoundException ex) { Logger.getLogger(BroadCastWord.class.getName()).log(Level.SEVERE, null, ex); } } else if (e.getSource() == startBroadCast) { time.start(); startBroadCast.setEnabled(false); stopBroadCast.setEnabled(true); } else if (e.getSource() == time) { String s = null; try { if (token == -1) { file = new File(fileDir, fileName); in = new FileReader(file); br = new BufferedReader(in); } s = br.readLine(); if (s != null) { token = 0; showPlaying.setText("正在广播的内容:\n" + s); showPlayed.append(s + "\n"); byte buf[] = s.getBytes(); DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port); socket.send(packet); } else { token = -1; } } catch (Exception ex) { } } else if (e.getSource() == stopBroadCast) { time.stop(); stopBroadCast.setEnabled(false); startBroadCast.setEnabled(true); } } }
4.2.2 接收端
package _5_4组播套接字编程示例._5_4_2组播应用_英汉词典; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Frame; import java.awt.GridLayout; import java.awt.Panel; import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; /** * * Copyright ? 2016 Authors. All rights reserved. * * FileName: .java * @author : Wu_Being <1040003585@qq.com> * Date/Time: 2016-6-14/下午10:51:10 * Description: */ @SuppressWarnings("serial") public class Receive extends Frame implements Runnable, ActionListener { int port; InetAddress group = null; MulticastSocket socket = null; Button startRece, stopRece; Thread thread = null; TextArea showReceiving, showReceived; boolean stoped = false; public Receive() { super("定时接收信息"); thread = new Thread(this); startRece = new Button("start receive"); stopRece = new Button("stop receive"); startRece.addActionListener(this); stopRece.addActionListener(this); showReceiving = new TextArea(10, 10); showReceiving.setForeground(Color.blue); showReceived = new TextArea(10, 10); Panel north = new Panel(); north.add(startRece); north.add(stopRece); add(north, BorderLayout.NORTH); Panel center = new Panel(); center.setLayout(new GridLayout(1, 2)); center.add(showReceiving); center.add(showReceived); add(center, BorderLayout.CENTER); validate(); port = 5000; try { group = InetAddress.getByName("239.255.0.0"); socket = new MulticastSocket(port); socket.joinGroup(group); } catch (UnknownHostException ex) { Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); } setBounds(100, 50, 360, 380); setVisible(true); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); } public static void main(String[] args) { new Receive(); } public void run() { while (true) { byte[] data = new byte[8192]; DatagramPacket packet = null; packet = new DatagramPacket(data, data.length); try { socket.receive(packet); String message = new String(packet.getData(), 0, packet.getLength()); showReceiving.setText("正在接收的内容\n" + message); showReceived.append(message + "\n"); } catch (IOException ex) { Logger.getLogger(Receive.class.getName()).log(Level.SEVERE, null, ex); } if (stoped) { break; } } } public void actionPerformed(ActionEvent e) { if (e.getSource() == startRece) { startRece.setBackground(Color.blue); stopRece.setBackground(Color.gray); if (!(thread.isAlive())) { thread = new Thread(this); } thread.start(); stoped = false; } if (e.getSource() == stopRece) { startRece.setBackground(Color.gray); stopRece.setBackground(Color.blue); thread.interrupt(); stoped = true; } } }
文中所有源代码链接
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《Java组播套接字》:
http://blog.csdn.net/u014134180/article/details/51675461
如果你看完这篇博文,觉得对你有帮助,并且愿意付赞助费,那么我会更有动力写下去。
返回到目录 ↩
相关文章推荐
- Python网络数据采集
- 读《TCPL》- 介绍
- linux网络编程----->线程同步-->互斥量和读写锁
- 【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)
- python之basic加密http下载
- C# Http Get 提交请求
- VMWare虚拟机下RedHat 9.0linux的网络设置
- 理解OAuth 2.0
- Httpclient远程调用WebService示例
- thrift使用http并部署到iis
- http和https协议
- http和https协议
- C/C++网络编程总结
- 基于TCP/IP协议下的Socket通信
- 利用Wireshark 解密HTTPS流量
- Android网络编程(一)
- 【网络流24题----01】飞行员配对方案问题
- nginx做前端反代负载均衡,后端httpd+tomcat
- Spring3中js/css/jpg/gif等静态资源无法找到(No mapping found for HTTP request with URI)问题解决(转)
- 【51CTO学院三周年】藏头诗一首送祝福