Android

vscode 配置Android开发环境:https://www.jianshu.com/p/378930364493

Android手机端搭建ServerSocket:https://blog.csdn.net/DickyQie/article/details/80045639

========

java 包

如果其他的一个源文件包含了这个包提供的类、接口、枚举或者注释类型的时候,都必须将这个包的声明放在这个源文件的开头。

包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。

如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

===android 开发导入包=====

1、google 搜索相关包名,如nanohttpd gradle,点击进入org.nanohttpd » nanohttpd » 2.3.0 - Maven Repository mvnrepository.com 官方

2、android.studio 下build.gradle 添加包,包括页面显示的包groupId,artifactId,version

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
---官网提示----<br><!-- https://mvnrepository.com/artifact/org.nanohttpd/nanohttpd -->
<dependency>
<groupId>org.nanohttpd</groupId>
<artifactId>nanohttpd</artifactId>
<version>2.3.0</version>
<scope>runtime</scope>
</dependency>
 
----android build.gradle---
 
dependencies {
    implementation 'org.nanohttpd:nanohttpd:2.3.0'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.navigation:navigation-fragment:2.2.2'
    implementation 'androidx.navigation:navigation-ui:2.2.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

  3、点击sync.gradle即可下载对应的包到本地。

 

=============================

ADB Forward

1、参考:https://blog.csdn.net/mjm0771/article/details/6186410

在TCP网络编程中,Client的Socket(C)如果调用Connect()成功,就说明已经和Server端的Socket(S)连接上,可以通讯了。但是如果使用adb forward做端口映射,就不一样了。端口映射的实质是,让ADB-server作为一个switcher转发ADB-client的数据包,送给adbd,adbd再发给设备端的对应端口。因此一旦建立了映射,就相当于ADB-server开始监听这个目标端口。而此时如果有C去尝试Connect这个端口,是一定会成功的,因为与C连接的是ADB-server,而非真正的设备上的目标程序。这就出现了,即使Connect()成功,却完全无法知道究竟是否成功连接到S。

因此,判断真正连接成功的方法,只有轮询收发握手数据包。程序中约定好事先做个交互:C发送一个数据包,等待S回复;C如果收到了S的回复包,说明连通;如果接收超时,则认为没有连通。在没有连通的情况下,需要重新建立Socket,并Connect(),然后再尝试握手

2、参考:https://blog.csdn.net/u013553529/article/details/80036227

顾名思义,adb forward的功能是建立一个转发,adb forward tcp:11111 tcp:22222的意思是,将PC端的11111端口收到的数据,转发给到手机中22222端口。但是光执行这个命令还不能转发数据,还需要完成两个步骤才能传数据。这两个步骤是:

(a)在手机端,建立一个端口为22222的server,并打开server到监听状态。
(b)在PC端,建立一个socket client端,连接到端口为11111的server上。

PC端的应用与手机端应用通信建立的过程:
(1)执行adb forward tcp:11111 tcp:22222
(2)启动手机端应用,建立端口为22222的server,并处于监听状态(LISTENING)
(3)启动PC端应用,连接端口为11111的server(adb创建的)
之后,就可以传输数据了。

PC端的应用与手机端应用之间传输数据的过程:
(1)PC端应用将数据发送给端口为11111的server(adb创建的)
(2)adb将数据转发给手机端adbd进程(通过USB传输)
(3)adbd进程将数据发送给端口为22222的server(手机端应用创建的)
传递是双向的,第(1)和第(3)步是通过socket实现的,所以通过socket的读和写就完成了PC端应用和手机端应用的数据传递。
————————————————
原文链接:https://blog.csdn.net/u013553529/article/details/80036227

 

=============================================

1、Socket java初始: 转自 https://www.w3cschool.cn/essential_netty_in_action/essential_netty_in_action-lqfu2890.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ServerSocket serverSocket = new ServerSocket(portNumber);//1
Socket clientSocket = serverSocket.accept();             //2
BufferedReader in = new BufferedReader(                     //3
        new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out =
        new PrintWriter(clientSocket.getOutputStream(), true);
String request, response;
while ((request = in.readLine()) != null) {                 //4
    if ("Done".equals(request)) {                         //5
        break;
    }
}
response = processRequest(request);                        //6
out.println(response);                                    //7
}                                                        //8

  

1.ServerSocket 创建并监听端口的连接请求

2.accept() 调用阻塞,直到一个连接被建立了。返回一个新的 Socket 用来处理 客户端和服务端的交互

3.流被创建用于处理 socket 的输入和输出数据。BufferedReader 读取从字符输入流里面的本文。PrintWriter 打印格式化展示的对象读到本文输出流

4.处理循环开始 readLine() 阻塞,读取字符串直到最后是换行或者输入终止。

5.如果客户端发送的是“Done”处理循环退出

6.执行方法处理请求,返回服务器的响应

7.响应发回客户端

8.处理循环继续

显然,这段代码限制每次只能处理一个连接。为了实现多个并行的客户端我们需要分配一个新的 Thread 给每个新的客户端 Socket(当然需要更多的代码)。但考虑使用这种方法来支持大量的同步,长连接。在任何时间点多线程可能处于休眠状态,等待输入或输出数据。这很容易使得资源的大量浪费,对性能产生负面影响。当然,有一种替代方案。

除了示例中所示阻塞调用,原生 socket 库同时也包含了非阻塞 I/O 的功能。这使我们能够确定任何一个 socket 中是否有数据准备读或写。我们还可以设置标志,因为读/写调用如果没有数据立即返回;就是说,如果一个阻塞被调用后就会一直阻塞,直到处理完成。通过这种方法,会带来更大的代码的复杂性成本,其实我们可以获得更多的控制权来如何利用网络资源。

 

2、ServerSocket与Socket入门详解: 转自 https://blog.csdn.net/j080624/article/details/78468396

在Java中,服务器程序的基本生命周期如下:

1.使用一个ServerSocket()构造函数在一个特定端口创建一个新的ServerSocket。

2.ServerSocket使用其accept()方法监听这个端口的入站连接。accept()会一直阻塞,直到一个客户端尝试建立连接,此时accept()将返回一个连接客户端和服务器的socket对象。

也就是,客户端和服务器之间连接位于服务器端的socket。

3.根据服务器的类型,会调用socket的getInputStream()方法或getOutputStream()方法,或者这两个方法都调用,以获得与客户端通信的输入和输出流。

4.服务器和客户端根据已协商的协议交互,直到要关闭连接。

5.服务器或客户端(或二者)关闭连接。

6.服务器返回到步骤2,等待下一次连接。
=======================================

java 读取socket

日常写法:

mPrintWriter.print(sendData+ "\r\n");
mPrintWriter.flush();
String msg = mBufferedReader.readLine();
//处理数据


细心的你发现,发送数据时添加了结束符,如果不加结束符,导致readLine()阻塞,读不到任何数据,最终抛出SocketTimeoutException异常

总结

实际开发中,长连接比较复杂,还要考虑心跳,丢包,断开重连等问题。使用长连接时,要特别注意报文结束符问题,结束符只是用来告诉客户端或服务端数据已经发送完毕,客户端或服务端可以读取数据了,否则客户端或服务端会一直阻塞在read()或者readLine()方法

特别注意:
报文结束符:根据实际服务器规定的来添加,必要时问后端开发人员或者看接口文档是否有说明
不然在接口调试上会浪费很多宝贵的时间,影响后期功能开发。

posted @   小毛编  阅读(196)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示