在实现这个问题:主机不断地重复播出节目预报,可以保证加入到同一组的主机随时可接收到广播信息。接收者将正在接收的信息放在一个文本域中,并将接收的全部信息放在另一个文本域中。
接收程序出错:Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at Receive.actionPerformed(Receive.java:68)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at Receive.actionPerformed(Receive.java:68)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
其中广播主机程序代码为:
import java.io.IOException; //导入java.io.IOException类
import java.net.*; //导入java.net包
public class Weather extends Thread{ //创建类。该类为多线程执行程序
String weather = "节目预报:八点有大型晚会,请收听";
int port = 9898; //定义端口
InetAddress iaddress = null; //创建InetAddress对象
MulticastSocket socket = null; //声明多点广播套接字
Weather(){ //构造方法
try {
iaddress = InetAddress.getByName("224.255.10.0"); //实例化InetAddress,指定地址
socket = new MulticastSocket(port); //实例化多点广播套接字
socket.setTimeToLive(1); //指定发送范围是本地网络
socket.joinGroup(iaddress); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
public void run(){ //run()方法
while(true){
DatagramPacket packet = null; //声明DatagramPacket对象
byte data[] = weather.getBytes(); //声明字节数组
packet = new DatagramPacket(data,data.length,iaddress,port); //将数据打包
System.out.println(new String(data)); //将广播信息输出
try {
socket.send(packet); //发送数据
sleep(3000); //线程休眠
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
}
public static void main(String[] args) { // 主方法
Weather w = new Weather(); //创建本类对象
w.start(); //启动线程
}
}
接收代码为:
import java.awt.event.*; //导入java.awt.event包
import javax.swing.*;
import java.awt.*;
import java.net.*;
public class Receive extends JFrame implements Runnable, ActionListener {
int port; //定义int型变量
InetAddress group = null; //声明InetAddress对象
MulticastSocket socket = null; //创建多点广播套接字对象
JButton ince = new JButton("开始接收"); //创建按钮对象
JButton stop = new JButton("停止接收");
JTextArea inceAr = new JTextArea(10, 10); //显示接收广播的文本域
JTextArea inced = new JTextArea(10, 10);
Thread thread; //创建Thread对象
boolean b = false; //创建boolean型变量
public Receive() { //构造方法
super("广播数据报"); //调用父类方法
thread = new Thread(this);
ince.addActionListener(this); //绑定按钮ince的单击事件
stop.addActionListener(this); //绑定按钮stop的单击事件
inceAr.setForeground(Color.blue); //指定文本域中文字颜色
JPanel north = new JPanel(); //创建Jpane对象
north.add(ince); //将按钮添加到面板north上
north.add(stop);
add(north, BorderLayout.NORTH); //将north放置在窗体的上部
JPanel center = new JPanel(); //创建面板对象center
center.setLayout(new GridLayout(1, 2)); //设置面板布局
center.add(inceAr); //将文本域添加到面板上
center.add(inced);
add(center, BorderLayout.CENTER); //设置面板布局
validate(); //刷新
port = 9898; //设置端口号
try {
group = InetAddress.getByName("224.255.10.0"); //指定接收地址
socket = new MulticastSocket(port); //绑定多点广播套接字
socket.joinGroup(group); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
setBounds(100, 50, 360, 380); //设置布局
setVisible(true); //将窗体设置为显示状态
}
public void run() { //run()方法
while (true) {
byte data[] = new byte[1024]; //创建byte数组
DatagramPacket packet = null; //创建DatagramPacket对象
packet = new DatagramPacket(data, data.length, group, port); //待接收的数据包
try {
socket.receive(packet); //接收数据包
String message = new String(packet.getData(), 0, packet
.getLength()); //获取数据包中内容
inceAr.setText("正在接收的内容:\n" + message); //将接收内容显示在文本域中
inced.append(message + "\n"); //每条信息为一行
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
if (b == true) { //当变量等于true时,退出循环
break;
}
}
}
public void actionPerformed(ActionEvent e) { //单击事件
if (e.getSource() == ince) { //单击按钮ince触发的事件
ince.setBackground(Color.red); //设置按钮颜色
stop.setBackground(Color.yellow);
if (!(thread.isAlive())) { //如线程不处于“新建状态”
thread = new Thread(this); //实例化Thread对象
}
thread.start(); //启动线程
b = false; //设置变量值
}
if (e.getSource() == stop) { //单击按钮stop触发的事件
ince.setBackground(Color.yellow); //设置按钮颜色
stop.setBackground(Color.red);
b = true; //设置变量值s
}
}
public static void main(String[] args) { //主方法
Receive rec = new Receive(); //创建本类对象
rec.setSize(460, 200); //设置窗体大下
}
}
接收程序出错:Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at Receive.actionPerformed(Receive.java:68)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at Receive.actionPerformed(Receive.java:68)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
其中广播主机程序代码为:
import java.io.IOException; //导入java.io.IOException类
import java.net.*; //导入java.net包
public class Weather extends Thread{ //创建类。该类为多线程执行程序
String weather = "节目预报:八点有大型晚会,请收听";
int port = 9898; //定义端口
InetAddress iaddress = null; //创建InetAddress对象
MulticastSocket socket = null; //声明多点广播套接字
Weather(){ //构造方法
try {
iaddress = InetAddress.getByName("224.255.10.0"); //实例化InetAddress,指定地址
socket = new MulticastSocket(port); //实例化多点广播套接字
socket.setTimeToLive(1); //指定发送范围是本地网络
socket.joinGroup(iaddress); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
public void run(){ //run()方法
while(true){
DatagramPacket packet = null; //声明DatagramPacket对象
byte data[] = weather.getBytes(); //声明字节数组
packet = new DatagramPacket(data,data.length,iaddress,port); //将数据打包
System.out.println(new String(data)); //将广播信息输出
try {
socket.send(packet); //发送数据
sleep(3000); //线程休眠
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
}
public static void main(String[] args) { // 主方法
Weather w = new Weather(); //创建本类对象
w.start(); //启动线程
}
}
接收代码为:
import java.awt.event.*; //导入java.awt.event包
import javax.swing.*;
import java.awt.*;
import java.net.*;
public class Receive extends JFrame implements Runnable, ActionListener {
int port; //定义int型变量
InetAddress group = null; //声明InetAddress对象
MulticastSocket socket = null; //创建多点广播套接字对象
JButton ince = new JButton("开始接收"); //创建按钮对象
JButton stop = new JButton("停止接收");
JTextArea inceAr = new JTextArea(10, 10); //显示接收广播的文本域
JTextArea inced = new JTextArea(10, 10);
Thread thread; //创建Thread对象
boolean b = false; //创建boolean型变量
public Receive() { //构造方法
super("广播数据报"); //调用父类方法
thread = new Thread(this);
ince.addActionListener(this); //绑定按钮ince的单击事件
stop.addActionListener(this); //绑定按钮stop的单击事件
inceAr.setForeground(Color.blue); //指定文本域中文字颜色
JPanel north = new JPanel(); //创建Jpane对象
north.add(ince); //将按钮添加到面板north上
north.add(stop);
add(north, BorderLayout.NORTH); //将north放置在窗体的上部
JPanel center = new JPanel(); //创建面板对象center
center.setLayout(new GridLayout(1, 2)); //设置面板布局
center.add(inceAr); //将文本域添加到面板上
center.add(inced);
add(center, BorderLayout.CENTER); //设置面板布局
validate(); //刷新
port = 9898; //设置端口号
try {
group = InetAddress.getByName("224.255.10.0"); //指定接收地址
socket = new MulticastSocket(port); //绑定多点广播套接字
socket.joinGroup(group); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
setBounds(100, 50, 360, 380); //设置布局
setVisible(true); //将窗体设置为显示状态
}
public void run() { //run()方法
while (true) {
byte data[] = new byte[1024]; //创建byte数组
DatagramPacket packet = null; //创建DatagramPacket对象
packet = new DatagramPacket(data, data.length, group, port); //待接收的数据包
try {
socket.receive(packet); //接收数据包
String message = new String(packet.getData(), 0, packet
.getLength()); //获取数据包中内容
inceAr.setText("正在接收的内容:\n" + message); //将接收内容显示在文本域中
inced.append(message + "\n"); //每条信息为一行
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
if (b == true) { //当变量等于true时,退出循环
break;
}
}
}
public void actionPerformed(ActionEvent e) { //单击事件
if (e.getSource() == ince) { //单击按钮ince触发的事件
ince.setBackground(Color.red); //设置按钮颜色
stop.setBackground(Color.yellow);
if (!(thread.isAlive())) { //如线程不处于“新建状态”
thread = new Thread(this); //实例化Thread对象
}
thread.start(); //启动线程
b = false; //设置变量值
}
if (e.getSource() == stop) { //单击按钮stop触发的事件
ince.setBackground(Color.yellow); //设置按钮颜色
stop.setBackground(Color.red);
b = true; //设置变量值s
}
}
public static void main(String[] args) { //主方法
Receive rec = new Receive(); //创建本类对象
rec.setSize(460, 200); //设置窗体大下
}
}
if (!(thread.isAlive())) { }中就行了耶.
问题应该就出在这里。
也就是说,当没有收到报文、或者报文没有接收完毕的时候,这个receive方法,是不会返回滴。
那么,楼主下面的代码就不会被执行,尤其是那个if(b == true){break;},
所以,这个线程在你按下“停止接收”按钮的时候,是无法终止滴。
然后,再按“开始接收”按钮,其thread.isAlive()当然要返回true了。
未终止的线程,其thread.isAlive()为true,并且thread.start();会抛上面楼主说的那个异常。
因为,人家线程已经是运行状态了,你还让人家开始运行,当然要抛异常了。
每个循环都检测一次是否有数据,然后sleep几毫秒。
不过,编程复杂度可能要加大一点。当然,也有比较恶心的做法。
就是,后台线程还是死命的接受,
前台只负责设置一个变量,控制程序是否显示(记录)这个接收的内容。
这样,那个线程只在创建对象的时候start一下,其他的时候,根本不用管它。
你发了一个报文,客户端会收一个报文,receive方法返回,做后续处理。
然后,在你发下一个包之前,客户端已经执行到了receive方法,并且,线程阻塞在这个方法上了。
如果服务端持续不发包,客户端的receive方法始终无法返回,那么,后续的代码根本运行不到。
这时,你点那个“停止接收”,也就是把b变量设置为true,它并不会影响到那个break语句,
以至于线程停止。因为,receive方法由于没有收到报文而在那阻塞着呢,所以,后面的代码执行不到。
(就是,你在点了“停止接收”后,必须再收一个报文,才能让线程结束,
如果你点了“停止接收”后,还没收到报文就又点了“开始接收”,那么就会抛异常)明白吧 ?
再不明白,你另请高明吧。我尽力了。
要不你在发送的socket.joinGroup(iaddress); //加入广播组
之前加上:socket.setBroadcast(true);试试。
真的很详细,我说说我对您那些话的理解!
如果我只按“开始接收”,不去按“停止接收”,程序应该是正常的,不会出错,原因是receive()接到数据包,返回,继续执行其它代码,因为b=false;所以一直在循环执行receive()(阻塞,发送,接收,阻塞,发送,接收……);
但现在是我只按“开始接收”,却不能正常显示接收。
您说的先按“开始接收”---“停止接收”---“开始接收”,程序真的是像你说的那样会抛出错误!
您的改进思路是明白的,但两个方法都不懂得实现!如果我一直在拼命地receive()接收不是一样会遇到阻塞出错的问题(像上面的那种错),还有就是如何显示接收到的信息也不懂得怎么实现!
preferme说得对
import java.net.*; //导入java.net包
public class Weather extends Thread{ //创建类。该类为多线程执行程序
String weather = "节目预报:八点有大型晚会,请收听";
int port = 9898; //定义端口
InetAddress iaddress = null; //创建InetAddress对象
MulticastSocket socket = null; //声明多点广播套接字
Weather(){ //构造方法
try {
iaddress = InetAddress.getByName("224.255.10.0"); //实例化InetAddress,指定地址
socket = new MulticastSocket(port); //实例化多点广播套接字
socket.setTimeToLive(1); //指定发送范围是本地网络
socket.setBroadcast(true);
socket.joinGroup(iaddress); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
public void run(){ //run()方法
while(true){
DatagramPacket packet = null; //声明DatagramPacket对象
byte data[] = weather.getBytes(); //声明字节数组
packet = new DatagramPacket(data,data.length,iaddress,port); //将数据打包
System.out.println(new String(data)); //将广播信息输出
try {
socket.send(packet); //发送数据
sleep(3000); //线程休眠
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
}
}
public static void main(String[] args) { // 主方法
Weather w = new Weather(); //创建本类对象
w.start(); //启动线程
}
}
import java.awt.event.*; //导入java.awt.event包
import javax.swing.*;
import java.awt.*;
import java.net.*;
public class Receive extends JFrame implements Runnable, ActionListener {
int port; //定义int型变量
InetAddress group = null; //声明InetAddress对象
MulticastSocket socket = null; //创建多点广播套接字对象
JButton ince = new JButton("开始接收"); //创建按钮对象
JButton stop = new JButton("停止接收");
JTextArea inceAr = new JTextArea(10, 10); //显示接收广播的文本域
JTextArea inced = new JTextArea(10, 10);
Thread thread; //创建Thread对象
boolean b = false; //创建boolean型变量
public Receive() { //构造方法
super("广播数据报"); //调用父类方法
thread = new Thread(this);
ince.addActionListener(this); //绑定按钮ince的单击事件
stop.addActionListener(this); //绑定按钮stop的单击事件
inceAr.setForeground(Color.blue); //指定文本域中文字颜色
JPanel north = new JPanel(); //创建Jpane对象
north.add(ince); //将按钮添加到面板north上
north.add(stop);
add(north, BorderLayout.NORTH); //将north放置在窗体的上部
JPanel center = new JPanel(); //创建面板对象center
center.setLayout(new GridLayout(1, 2)); //设置面板布局
center.add(inceAr); //将文本域添加到面板上
center.add(inced);
add(center, BorderLayout.CENTER); //设置面板布局
validate(); //刷新
port = 9898; //设置端口号
try {
group = InetAddress.getByName("224.255.10.0"); //指定接收地址
socket = new MulticastSocket(port); //绑定多点广播套接字
socket.joinGroup(group); //加入广播组
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
setBounds(100, 50, 360, 380); //设置布局
setVisible(true); //将窗体设置为显示状态
}
public void run() { //run()方法
while (true) {
byte data[] = new byte[1024]; //创建byte数组
DatagramPacket packet = null; //创建DatagramPacket对象
packet = new DatagramPacket(data, data.length, group, port); //待接收的数据包
try {
socket.receive(packet); //接收数据包
String message = new String(packet.getData(), 0, packet
.getLength()); //获取数据包中内容
inceAr.setText("正在接收的内容:\n" + message+"\n"); //将接收内容显示在文本域中
inced.append(message + "\n"); //每条信息为一行
} catch (Exception e) {
e.printStackTrace(); //输出异常信息
}
if (b == true) { //当变量等于true时,退出循环
break;
}
}
}
public void actionPerformed(ActionEvent e) { //单击事件
if (e.getSource() == ince) { //单击按钮ince触发的事件
ince.setBackground(Color.red); //设置按钮颜色
stop.setBackground(Color.yellow);
if (!(thread.isAlive())) { //如线程不处于“新建状态”
thread = new Thread(this);
thread.start(); //实例化Thread对象
}
//启动线程
b = false; //设置变量值
}
if (e.getSource() == stop) { //单击按钮stop触发的事件
ince.setBackground(Color.yellow); //设置按钮颜色
stop.setBackground(Color.red);
b = true; //设置变量值s
}
}
public static void main(String[] args) { //主方法
Receive rec = new Receive(); //创建本类对象
rec.setSize(460, 200); //设置窗体大下
}
}