您的位置:

java广播,java广播实现

本文目录一览:

java socket,我有客户端和服务器的代码,帮我添加广播和能多人会话,加分!!代码如下

根据你的改了个!不好意思,其中读写的思路稍微有点不同!不过可以做参考!

Server端代码:

import java.net.*;

import java.io.*;

import java.util.*;

public class TestServer {

ServerSocket s = null;

boolean started = false;//用来监听服务器是否启动!

ListServerReaderWriter clients = new ArrayListServerReaderWriter();//用来存放启动的客服端

public static void main(String[] args) {

new TestServer().start();

}

public void start() {

try {

s = new ServerSocket(5050);

started = true;

} catch(SocketException e) {

System.out.println("5050端口正在使用中!!!请关掉相关程序并重新运行服务器!");

System.exit(0);

} catch (IOException e) {

e.printStackTrace();

}

int i = 1;

try {

while(started) {

Socket ss = s.accept();

ServerReaderWriter c = new ServerReaderWriter(ss);//建立客服端

System.out.println("第" + i + "个客服端启动!");

++i;

new Thread(c).start();//启动线程

clients.add(c);

}

} catch (EOFException e) {

System.out.println("客服端被关闭!");

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ServerReaderWriter implements Runnable { //建议使用Runnable避免你重写run方法麻烦!

private Socket s;

private DataInputStream dis = null;//注意赋值,养成好习惯!

private DataOutputStream dos = null;

private boolean bConnected = false;//用于调用连接成功后的run方法

public ServerReaderWriter(Socket s) {

this.s = s;

try {

dis = new DataInputStream(s.getInputStream());

dos = new DataOutputStream(s.getOutputStream());

bConnected = true;

} catch (IOException e) {

e.printStackTrace();

}

}

public void send(String str) {

try {

dos.writeUTF(str);

} catch (IOException e) {

clients.remove(this);

System.out.println("有客户退出!");

}

}

public void run() {

try {

while (bConnected) {

String input = dis.readUTF();

System.out.println(input);

for(int i=0; iclients.size(); ++i) {

ServerReaderWriter c = clients.get(i);

c.send(input);

}

}

} catch(SocketException e) {

System.out.println("一个客服端已关闭,请勿再像他发送信息!");

} catch (EOFException e) {

System.out.println("谢谢使用!");

}catch (IOException e) {

e.printStackTrace();

} finally {

try {

if (dis != null) {

dis.close();

}

if (dos != null) {

dos.close();

}

if (s != null) {

s.close();

s = null;

}

//clients.clear();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

Client端代码:

import java.io.*;

import java.net.*;

import java.awt.*;

import java.awt.event.*;

public class TestClient extends Frame { //用到Frame生产界面比较直观

Socket s = null;

DataOutputStream dos = null;

DataInputStream dis = null;

private boolean bConnected = false;

TextField tfText = new TextField();

TextArea taContent = new TextArea();

Thread tRecv = new Thread(new ClientReaderWriter());

public static void main(String[] args){

new TestClient().launchFrame();

}

public void launchFrame() {

this.setSize(300, 300); //设置客服端窗口格式

this.setLocation(400, 300);

add(tfText, BorderLayout.SOUTH);

add(taContent, BorderLayout.NORTH);

this.pack();

this.addWindowListener(new WindowAdapter() { //监听窗口关闭事件

public void windowClosing(WindowEvent arg0) {

disconnect();

System.exit(0);

}

});

tfText.addActionListener(new TFListener());

setVisible(true);

connect();

tRecv.start();

}

public void connect() {

try {

s = new Socket("127.0.0.1", 5050); //依据自己的服务器,我这里用的localhost

dos = new DataOutputStream(s.getOutputStream());

dis = new DataInputStream(s.getInputStream());

System.out.println("连接服务器!");

bConnected = true;

} catch(ConnectException e) {

System.out.println("请检查服务器是否启动!");

try {

Thread.sleep(1000);

} catch (InterruptedException e1) {

e1.printStackTrace();

}

System.exit(0);

}

catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public void disconnect() {

try {

dos.close();

dis.close();

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

private class TFListener implements ActionListener {

public void actionPerformed(ActionEvent e) {

String str = tfText.getText().trim();

tfText.setText("");

try {

dos.writeUTF(str);

if(str.equals("bye")){

System.exit(0);

}

dos.flush();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

class ClientReaderWriter implements Runnable {

public void run() {

try {

while(bConnected) {

String input = dis.readUTF();

taContent.setText(taContent.getText() + input +'\n');

}

} catch (SocketException e) {

System.out.println("轻轻的我走了!Bye-bye!");

} catch (EOFException e) {

System.out.println("我断网了,再见!");

}

catch (IOException e) {

e.printStackTrace();

}

}

}

}

谈谈你对广播的理解?

广播就是用来发送/接收一系列通知的组件,它是四大组件之一,常用于进程间的通信。

低耦合高内聚:如果两个组件之间需要通信的话,可以通过获取组件之间的实例,但是这种方法无疑增加了耦合,不是很好,而使用广播,可以不需要获取对方的实例就能拿到想到的数据,当然还有更方便的事件总线机制,这里只是举个例子。它不仅可以使用在组件之间的通信,还有使用在进程间通信,程序保活等。

a.有序广播

b.无序广播

c.普通广播

d.粘性广播

e.本地广播

f.系统广播

首先需要一个广播接收器

然后注册广播, 注册可分为静态和动态注册:

1.动态注册:

这里要注意的是在程序销毁之前要解绑该广播,防止造成内存泄漏。

2.静态注册:

静态注册是通过在xml中完成的

最后就是发送广播:

这里需要特别说明一下本地广播,其他的广播可以存在被人拦截或者被人攻击的情况,所以安全性不是很高,所以就出了本地广播,这套机制只能接收应用程序内部的广播,所以就不存被人拦截或者攻击的情况。

广播的发送不变。

a.广播不会发送消息给已经停止的应用

b.Android 7.0屏蔽了某些广播事件,如: 后台程序无法监听网络状态,不允许静态注册,防止应用无节操地恶意唤醒

c.某些三方ROM(如:MUI/EMUI)也限制了某些广播事件,如:华为 EMUI 需要设置允许当前程序开机启动才允许监听 BOOT_COMPLETED

d.onReceiver()方法不要执行特别耗时的操作,耗时操作可以放到Service组件中

e.LocalBroadcastManager 不会有应用劫持广播信息的情况 ,只有 BroadcastManager 才会出现 ,所以 如果不是跨进程的话可以用 LocalBroadcastManager 完全替代 Broadcastreceive

是通过binder实现的,这个暂时不了解,后续会继续研究。

1.静态广播和动态广播哪一个先接收到?

答:动态优先静态,具体原因可以翻看ActivityManagerService(.../sdk/sources/android-xx/com/android/server/am/ActivityManagerService.java)的源码,可以根据sendBroadcast去一步一步的往下跟,最后你会发现,先遍历动态广播再静态广播,所以动态广播优先于静态。

java里怎么发广播呀

java里怎么发广播

public void onReceive(Context context,Intent intent){

Intent intent = new Intent(context,XxxService.class);

context.startService(intent);

}

Intent intent = new Intent();

intent.setAction("...");

Context.sendBroadcast(intent);

Android系统广播(Broadcast)注册,发送,接收流程解析

以下广播简称Broadcast

   是Android四大组件之一,在四大组件的另外两个组件 和 拥有发送和接收广播的能力。Android 是在 进程间通信机制的基础上实现的,内部基于消息发布和订阅的事件驱动模型,广播发送者负责发送消息,广播接收者需要先订阅消息,然后才能收到消息。 进程间通信与 的区别在于:

   有三种类型

   存在一个注册中心,也可以说是一个调度中心,即 。广播接收者将自己注册到 中,并指定要接收的广播类型;广播发送者发送广播时,发送的广播首先会发送到 , 根据广播的类型找到对应的 ,找到后边将广播发送给其处理。

   这里以普通广播为例子, 接收者有两种注册方式,一种是 ,一种是 :

(广播的发送分为 两种,这里针对有序的广播) 中的android:priority=""和 中的IntentFilter.setPriority(int)可以用来设置广播接收者的优先级,默认都是0 , 范围是[-1000, 1000],值越大优先级越高,优先级越高越早收到。

   在相同优先级接收同个类型广播时, 的广播接收器比 的广播接收者更快的接收到对应的广播,这个之后会进行分析。

   注:以下源码基于rk3399_industry Android7.1.2

   的流程可分为 , 和 三个部分,这里依次分析下

   在Android系统的 机制中,前面提到, 作为一个注册和调度中心负责注册和转发 。所以 的注册过程就是把它注册到 的过程。

   这里我们分析 广播的过程, 和 有一个共同的父类 ,所以它们对应的注册过程其实是调用 ,接下来我们按照流程逐步分析调用流程的源码。

frameworks/base/core/java/android/content/ContextWrapper.java

   在之前的 Android应用程序启动入口ActivityThread.main流程分析 分析过,在我们启动 Activity 时会创建一个 对象,然后通过 传给我们启动的 ,其内部就会将该对象赋值给 ; 的 方法也是类似的赋值流程,这里放个简易的源码应该更好理解

   可以看到最后都会将生成的 对象赋值给对应的

对象。接下来继续分析 , 即 函数。

/frameworks/base/core/java/android/app/ContextImpl.java

   这里我们首先看下如何将广播接收者 封装成一个 接口的 本地对象

/frameworks/base/core/java/android/app/LoadedApk.java

   每一个注册过广播接收者的 或 组件在font color='Crimson' LoadedApk /font类中都有个对应的 对象,该对象负责将 与 组件关联起来。这些对象,以关联的 作为关键字保存在一个 中。之后对应的 又以 的 作为关键字保存在 的成员变量 对象中。最后通过 对应的 方法获得其 接口的 本地对象。之后再回到 注册方法内,将 对象发给 进行注册。

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   在的 或 注册一个 时,并不是将其注册到font color='OrangeRed'AMS/font中,而是将与它关联的font color='OrangeRed'InnerReceiver/font对象注册到font color='OrangeRed'AMS/font中,当font color='OrangeRed'AMS/font接收到广播时,会根据 在内部找到对应的font color='OrangeRed'InnerReceiver/font对象,然后在通过这个对象将这个广播发送给对应的 处理。

   注册过程这边画了一个简单的流程图:

   font color='OrangeRed'Broadcast/font的发送过程可简单描述为以下几个过程:

frameworks/base/core/java/android/content/ContextWrapper.java

/frameworks/base/core/java/android/app/ContextImpl.java

/frameworks/base/core/java/android/app/ActivityManagerNative.java

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java