java之WIFI模块实现文件传输(开源)

server/2024/10/18 21:24:29/

AndroidManifest这里要获取到权限,所以要导入:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

主界面:

public class MainActivity extends AppCompatActivity {private Button startBtton, stopButton;@Overrideprotected void onCreate(Bundle savedInstanceState) {//super的意思是继承父类super.onCreate(savedInstanceState);//初始化xml组件setContentView(R.layout.activity_main);//初始化按钮组件startBtton=findViewById(R.id.bth_start);stopButton=findViewById(R.id.bth_stop);//当按钮按下去时候的监听器然后进行跳转到别的界面startBtton.setOnClickListener(v->startActivity(new Intent(MainActivity.this ,ServerActivity.class)));stopButton.setOnClickListener(view ->startActivity(new Intent(MainActivity.this,ClientActivity.class)) );}
}

服务器端:

public class ServerActivity extends AppCompatActivity {private static final String TAG="ServerActivity";//mRegistrationListener: 监听NSD服务注册状态的回调接口。private NsdManager mNsdManager=null;private  NsdManager.RegistrationListener mRegistrationListener;//CHAT_PORT: 定义了用于通信的端口号。private  final int CHAT_PORT=6613;//udpListenerThread: 用于UDP监听的线程。private Thread udpListenerThread;//running: 用于控制UDP监听线程是否运行的标志。private boolean running = false;//packet: 用于接收UDP数据包的对象。private DatagramPacket packet;//BUFFER_SIZE: 定义了缓冲区的大小。private final int BUFFER_SIZE = 1024*6;private byte[] buffer = new byte[BUFFER_SIZE];//serverTV 和 msgTV: 分别是用于显示服务器状态和接收到的消息的TextView控件。private TextView serverTV, msgTV;//构造方法: 一个空的构造方法。public ServerActivity() {}@SuppressLint("MissingInflatedId")@Override//onCreate: 活动创建时调用的方法,用于初始化界面和设置NSD服务。protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_server);serverTV = findViewById(R.id.tv_server_state);msgTV = findViewById(R.id.tv_msg_receive);//设置mRegistrationListener的回调方法。mRegistrationListener=new NsdManager.RegistrationListener() {@SuppressLint("SetTextI18n")@Override//获取NSD服务管理器,创建NsdServiceInfo对象并注册服务。//当服务注册失败时调用。参数serviceInfo包含有关尝试注册的服务的信息,// errorCode提供了失败的原因。这里通过调用Log.i记录信息,并使用runOnUiThread更新UI,显示"nsd服务:注册失败"。public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {Log.i(TAG,"onRegistrationFailed ");runOnUiThread(() -> serverTV.setText("nsd服务:注册失败"));}@SuppressLint("SetTextI18n")@Override// 当服务注销失败时调用。参数含义与上一个方法相同。这里更新UI显示"nsd服务:取消注册失败"。public void onUnregistrationFailed (NsdServiceInfo nsdServiceInfo,int i){Log.i(TAG, "onUnregistrationFailed ");runOnUiThread(() -> serverTV.setText("nsd服务:取消注册失败"));}@SuppressLint("SetTextI18n")@Override// 当服务成功注册时调用。参数serviceInfo包含已注册服务的详细信息。这里更新UI显示"nsd服务:注册成功"。public void onServiceRegistered (NsdServiceInfo nsdServiceInfo){Log.i(TAG, "onServiceRegistered ");runOnUiThread(() -> serverTV.setText("nsd服务:注册成功"));}@SuppressLint("SetTextI18n")@Override//当服务成功注销时调用。参数含义与注册成功时相同。这里更新UI显示"nsd服务:取消注册成功"。public void onServiceUnregistered (NsdServiceInfo nsdServiceInfo){Log.i(TAG, "onServiceUnregistered ");runOnUiThread(() -> serverTV.setText("nsd服务:取消注册成功"));}};//这行代码通过调用getSystemService方法获取系统服务NSD_SERVICE,即Network ServicemNsdManager = (NsdManager) getSystemService(NSD_SERVICE);//创建了一个NsdServiceInfo对象,这个对象用于存储关于要注册的服务的信息NsdServiceInfo serviceInfo = new NsdServiceInfo();//设置服务的名称为"test"。这个名称将用于客户端搜索服务时的标识。serviceInfo.setServiceName("test");//设置服务监听的端口号。CHAT_PORT应该是一个定义好的端口常量,用于聊天服务。serviceInfo.setPort(CHAT_PORT);//客户端发现服务器是需要对应的这个Type字符串 ;_http._tcp.serviceInfo.setServiceType("_saixiang._tcp.");//客户端发现服务器是需要对应的这个Type字符串 ;_http._tcp.//使用NsdManager的registerService方法注册服务。第一个参数是之前创建的serviceInfo对象,// 第二个参数指定使用的协议为DNS-SD,第三个参数是一个监听器mRegistrationListener,用于接收服务注册过程中的状态更新。mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);//这行代码被注释掉了,如果取消注释,它将启动一个UDP监听器。UDP是一种无连接的网络协议,常用于需要快速传输但可以容忍一些数据丢失的场景。//startUdpListener();//这行代码调用了一个名为startListen的方法,这个方法的具体实现没有给出,但它的目的可能是启动一个监听器来处理网络请求。startListen();}private boolean ifListen=true;private ServerSocket serverSocket = null;private Socket socket = null;boolean ifSocketThreadStart = false;/*开始监听* *///线程定义: socketThread是一个内部线程类,用于处理TCP连接和数据接收。private final Thread socketThread = new Thread() {//这是线程的run方法,当线程启动时候会执行这个方法public void run() {//无限循环,表示线程会一直运行直到程序终止while (true) {try {//这个条件判断如果serverSocket是null并且ifListen为true,则执行大括号里的代码if (serverSocket == null && ifListen) {//定义了一个端口为6613的变量int socket_port = 6613;//创建一个新的serverSocket对象,监听6613端口serverSocket = new ServerSocket(socket_port);//如果serverSocket不是null,则执行大括号里的代码} else if (serverSocket != null) {//调用Accept方法等待客户端连接,并将连接的Socket对象赋值给变量socketsocket = serverSocket.accept();if (socket != null) {//创建一个包装了socket输入流的BufferedInputStream,再包装成DataInputStream,用于高效读取数据。DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));try {//定义了一个大小为1024的字节数组,用作数据缓冲区byte[] buffer = new byte[1024];int len = 0;//这是一个循环,当从DataInputStream读取到数据(len不为-1)时候,执行大括号里的代码while ((len = in.read(buffer)) != -1) {//使用读取到的数据和"GB2312"编码创建一个字符串。String text = new String(buffer, 0, len, "GB2312");//打印日志,记录接收到的数据。Log.d("test", "收到的数据为:" + text);}// 捕获并处理DataInputStream读取过程中可能发生的异常。} catch (Exception e) {Log.d("test", "DataService read: " + e);//调用一个自定义的方法来销毁socket,可能是关闭连接。destroySocket();}}}//捕获并处理ServerSocket创建或accept方法调用过程中可能发生的异常。} catch (IOException e1) {Log.d("test", "DataService accept: " + e1);destroySocket(); }}}};//startListen 用于启动public void startListen() {ifListen = true;if (!ifSocketThreadStart) {ifSocketThreadStart = true;socketThread.start();}}//停止TCP监听stopListen:public void stopListen() {ifListen = false;destroySocket();}//用于关闭和重置ServerSocket和Socket。private void destroySocket() {//开始一个 try 块,用于捕获并处理可能发生的异常。try {//检查 serverSocket 是否不为 null 且没有被关闭。if (serverSocket != null && !serverSocket.isClosed()) {//如果条件满足,调用 close 方法关闭 serverSocket。serverSocket.close();}//如果关闭 serverSocket 时发生 IOException,将进入这个 catch 块。} catch (IOException e) {
//            AppLog.Log(e.toString());}//无论是否发生异常,都会执行 finally 块中的代码。finally {//将 serverSocket 设置为 null,以确保它不再被使用。serverSocket = null;}//开始另一个 try 块,用于关闭另一个套接字 socket。try {//检查 socket 是否不为 null 且没有被关闭。if (socket != null && !socket.isClosed()) {//如果条件满足,调用 close 方法关闭 socket。socket.close();}}//如果关闭 socket 时发生 IOException,将进入这个 catch 块。catch (IOException e) {
//            AppLog.Log(e.toString());}//无论是否发生异常,都会执行 finally 块中的代码。finally {//将 socket 设置为 null,以确保它不再被使用。socket = null;}}@Override//onDestroy: 活动销毁时调用的方法,用于注销NSD服务和停止监听。protected void onDestroy() {//这是调用父类(即Activity类)的onDestroy()方法,以确保父类中的资源得到正确释放。super.onDestroy();//: 这个方法用于停止NSD服务。NSD服务允许应用程序在本地网络中注册和发现服务。stopNSDServer();
//       stopUdpListener();destroySocket();stopListen();}//NSD服务注册与注销: 通过mNsdManager注册和注销服务,以便其他设备可以通过NSD发现此服务public void stopNSDServer() {// mRegistrationListener作为参数传递,这样当服务取消注册时,监听器会收到相应的回调。mNsdManager.unregisterService(mRegistrationListener);}
}

截取了soket应该怎么接收和建立传输数据.

客户端:

//ClientActivity 继承自 AppCompatActivity表明它是一个可以处理配置更改(如屏幕旋转)的活动。
public class ClientActivity extends AppCompatActivity {private static final String TAG = "ClientActivity";private RecyclerView recyclerView;private NsdManager mNsdManager = null;//mNsdManager: 用于网络服务发现的 NsdManager 实例。private NsdManager.DiscoveryListener mNSDDiscoveryListener = null;    //    搜寻监听器private NsdManager.ResolveListener mNSDResolveListener = null;//    解析监听器private NSDDeviceAdapter adapter;private TextView serverTV;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//设置了活动的布局setContentView(R.layout.activity_client);serverTV=findViewById(R.id.tv_server_state_s);//获取了布局中RecyclerView组件recyclerView = findViewById(R.id.recyclerView);//为RecyclerView设置了线性布局管理器recyclerView.setLayoutManager(new LinearLayoutManager(this));//创建了一个适配器,用于管理RecyclerView中显示的数据adapter = new NSDDeviceAdapter();//将适配器设置到recyclerView上recyclerView.setAdapter(adapter);//服务发现监听器 (mNSDDiscoveryListener):定义了多个回调方法,用于处理服务发现过程中的不同事件。mNSDDiscoveryListener = new NsdManager.DiscoveryListener() {@Override//在开始服务时调用。public void onStartDiscoveryFailed(String serviceType, int errorCode) {Log.i(TAG,"onStartDiscoveryFailed ");}// 停止服务发现失败时调用@Overridepublic void onStopDiscoveryFailed(String serviceType, int errorCode) {//使用 Log.i(TAG, message) 记录信息,其中 message 是要记录的消息Log.i(TAG,"onStopDiscoveryFailed ");}//分别在服务发现开始时调用。@Overridepublic void onDiscoveryStarted(String serviceType) {Log.i(TAG,"onDiscoveryStarted ");}//分别在服务发现停止时调用。@Overridepublic void onDiscoveryStopped(String serviceType) {Log.i(TAG,"onDiscoveryStopped ");}//当发现新服务时调用,并使用 mNSDResolveListener 解析服务信息。@Overridepublic void onServiceFound(NsdServiceInfo serviceInfo) {Log.i(TAG,"onServiceFound "+serviceInfo.toString());mNsdManager.resolveService(serviceInfo, mNSDResolveListener);}//当服务不再可用时调用,并从适配器中移除该服务。@Overridepublic void onServiceLost(final NsdServiceInfo serviceInfo) {Log.i(TAG,"onServiceLost ");//使用 runOnUiThread(Runnable) 确保在主线程上更新UI,这是Android中更新UI的标准做法runOnUiThread(new Runnable() {@Overridepublic void run() {adapter.removeDevice(serviceInfo);}});}};//用于监听服务解析的结果。mNSDResolveListener = new NsdManager.ResolveListener() {@Override//onResolveFailed: 在服务解析失败时调用。public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {Log.i(TAG,"onResolveFailed ");}@Override//onServiceResolved: 在服务解析成功时调用,并更新适配器以添加服务信息public void onServiceResolved(final NsdServiceInfo serviceInfo) {Log.i(TAG,"onServiceResolved ");runOnUiThread(new Runnable() {@Overridepublic void run() {adapter.addDevice(serviceInfo);}});}};//使用 mNsdManager方法开始服务发现,指定服务类型 _saixiang._tcp.mNsdManager = (NsdManager) getSystemService(NSD_SERVICE);//使用discoverServices 方法开始服务发现,使用的协议 NsdManager.PROTOCOL_DNS_SD。mNsdManager.discoverServices("_saixiang._tcp.", NsdManager.PROTOCOL_DNS_SD, mNSDDiscoveryListener);// 客户端在服务解析成功后,尝试与服务器建立连接mNSDResolveListener = new NsdManager.ResolveListener() {@Overridepublic void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {// 处理解析失败的情况Log.i(TAG,"onResolveFailed ");}@Overridepublic void onServiceResolved(NsdServiceInfo serviceInfo) {// 服务解析成功,尝试建立连接new Thread(new Runnable() {@Overridepublic void run() {try {// 创建Socket连接Socket socket = new Socket(serviceInfo.getHost(), serviceInfo.getPort());// 发送数据OutputStream out = socket.getOutputStream();out.write("Hello Server!".getBytes());out.flush();// 接收数据InputStream in = socket.getInputStream();byte[] buffer = new byte[1024];int len = in.read(buffer);String received = new String(buffer, 0, len);Log.i(TAG, "Received: " + received);// 关闭连接socket.close();} catch (IOException e) {e.printStackTrace();}}}).start();}};}@Override//在活动销毁时停止服务发现,避免资源泄露。protected void onDestroy() {super.onDestroy();mNsdManager.stopServiceDiscovery(mNSDDiscoveryListener);}}

也是建立了socket来建立数据传输.


http://www.ppmy.cn/server/96579.html

相关文章

2024.8.2(MySQL)

一、mysql 1、下载mysql软件包 [rootmysql ~]# yum -y install wget [rootmysql ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 2、解压 [rootmysql ~]# tar -xf mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 3、安装…

如何通过OpenCV判断图片是否包含在视频内?

要判断图片是否包含在视频内&#xff0c;可以使用计算机视觉技术和图像处理方法。这通常涉及特征匹配或模板匹配。以下是一个基于OpenCV的解决方案&#xff0c;通过特征匹配的方法来实现这一目标。 步骤概述 读取视频和图片&#xff1a; 使用OpenCV读取视频文件和图片文件。 …

LoRA 的基本原理和操作步骤

Low-Rank Adaptation (LoRA) 是一种技术&#xff0c;用于在有限的计算资源和训练数据下&#xff0c;针对特定任务微调大型预训练模型。LoRA 的核心思想是将原始模型的参数矩阵分解为两个低秩矩阵&#xff0c;从而减少需要微调的参数量。下面详细讲解 LoRA 的原理和具体过程。 …

Linux下部署python记录

目录 前言 部署过程 安装python 收集依赖 安装依赖 上传代码到服务器 部署 打包部署 直接运行代码 nohub使用 总结 最终结果 更好的方法 遇到的问题 前言 在本地实现了一个python写的webapi&#xff0c;现在要部署到一个外网服务器测试&#xff0c;奈何服务器资…

3.Java面试题之AQS

1. 写在前面 AQS&#xff08;AbstractQueuedSynchronizer&#xff09;是Java并发包&#xff08;java.util.concurrent&#xff09;中的一个抽象类&#xff0c;用于实现同步器&#xff08;如锁、信号量、栅栏等&#xff09;。AQS提供了一种基于FIFO队列的机制来管理线程的竞争和…

gym/Gymnasium强化学习玩推箱子游戏

gym/Gymnasium强化学习玩推箱子游戏 gym 框架 源码 https://github.com/openai/gym 文档 https://www.gymlibrary.dev/ 自 2021 年以来一直维护 Gym 的团队已将所有未来的开发转移到 Gymnasium&#xff0c;这是 Gym 的替代品&#xff08;将 gymnasium 导入为 gym&#xff09;…

使用 Vue 3、TypeScript 和 Three.js 封装3D动画框架

在现代Web开发中&#xff0c;结合Vue.js的响应式特性与Three.js的强大3D渲染能力&#xff0c;可以创造出令人印象深刻的3D动画效果。本篇博客将介绍如何使用Vue 3、TypeScript和Three.js来封装一个可重用的3D动画框架。 1. 介绍 Vue 3 Vue 3 是Vue框架的最新版本&#xff0c…

Rider中修改默认文件关联,自定义打开方式

问题描述 想用Qt designer打开.ui文件&#xff0c;但是在Rider中&#xff0c;IDE会默认通过text进行打开 解决方法 1&#xff0c;允许用户将特定的文件类型与一个应用程序关联起来 File -> Settings -> Editor -> File Types -> Recognized File Types下&…