当前位置: 首页 > article >正文

安卓入门九 常用网络协议二

  1. Android Socket

socket 是端对端的通信,即网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket;

那两台计算机怎么通信呢 ? 它的通信必要条件为:IP地址,协议,端口号。

IP地址:两台主机他们需要有一个唯一的标识,用来表示他们所处的身份,所在的位置,这就是IP地址

协议:需要有共同的语言,否则就会出现言语不通,无法交流,这就是我们的协议,比如 TCP/IP协议簇

端口号:每台主机都需要有相应的端口号,一台主机上可以运行多个应用程序,那如何辨别不同应用程序的通信,我们需要使用端口号来进行区分。

而 socket 通信是基于TCP/IP 网络层上的一种传送方式,我们通常把TCP和UDP称为传输层(图片来源百度图片):osi参考模型与TCP/IP参考模型的对应关系

在建立 socket ,我们需要分别创建 server 和 client ,用一张图来解释可以如下:

从上图我们得出

服务端的步骤:

获取 ServerSocket 的实例

通过 server.accpet() 拿到客户端的 socket 实例

通过 socket.getInputStream() 或 socket.getOutputStream() 进行数据传输

客户端步骤:

获取 Socket 的实例

通过 connect 连接服务器

通过 socket.getInputStream() 或 socket.getOutputStream() 进行数据传输

2.1 TCP示例

理解了上面的连接过程,接着,我们来实现一个简单栗子;
客户端通过终端数据,并发送给服务端,服务端拿到数据后,回数据给客户端,

以‘bye’结束
首先先看客户端代码,首先通过 System.in 拿到终端的数据,然后通过 outputstream 发送给客户端,如下:

接着看服务端代码:

效果如下 (记得先启动服务端再启动客户端端):
服务端:

客户端:

2.2 UDP示例

UDP 是一个面向数据包的传输层协议,进程的每一个输出操作都正好产生一个UDP数据报,并组装成一份待发送的IP数据报。格式如下

IP数据报的最大长度为 65535 字节 ,除去首字IP 的20 字节和 UDP首部8个字节,实际上,UDP 能传输的最大字节数为 65507,个字节;当我们的数据超过这个长度时,则需要考虑分包的问题,这个问题,我们在后面分析。

UDP 的传输是不可靠的,它只负责把数据传输出去,并不会去考虑接收端是否能接受到。在大多不需要考虑应答的应用中,我们会优先考虑 UDP,比如多人聊天;当然,我们还可以 UDP 与 TCP 一起辅助,利用各自的优点来实现特殊的功能,比如文件快传。

DatagramSocket 和 DatagramPacket

socket的udp的api并没有包含在socket api中,而是通过DatagramSocket和DatagramPacket来实现的。

我们知道两台计算机的通信,无论是 TCP 还是 UDP ,都需要知道 IP 和 端口。同样,在 UDP 的单播实例中,实现步骤也是一样的,具体参考以下流程图:

2.3 单播、组播、多播

1.单播

单播即点对点的通信,这个也比较好理解,IP 和 端口都是确定的。
所以,UDP 的服务端代码如下:

客户端代码:

运行结果

IP地址分类和IP构成

对 ip 的分类划分:

可以看到,类别的不同,可以通过子网掩码来区分。我们常用的则为 C 端的ip地址。

然后来看看一些udp广播多播的知识:

255.255.255.255 为受限广播,即所有网段都能收到,但路由并不会去转发该广播,毕竟所有网段都会接受,所以只有本局域网能够接收到。

x.x.x.255 为 C 类广播,只有该网段下的才能收到 ,比如 192.168.33.255,那么 192.168.33.x 下的所有网段都能接收到。

多播广播,这个为多播预留的地址。

接着继续看 ip 地址 的构成,它是由 32 byte 组成:

上面看到了受限广播地址,即 255.255.255.255 ,当使用这个地址作为广播地址时,路由器的其他设备都能监听到,但如果 A 路由器和B路由器想要之间也能通信,则需要计算器出来的地址,比如:

A设备:ip为192.168.134.7 ,子网掩码为 255.255.255.192

B设备:ip为192.168.134.100 ,子网掩码也是 255.255.255.192

看到 A 与 B 的子网掩码是一样,但其实还是不能通信,因为 A与B 的通信地址不一样,因为A的地址为 192.168.134.63 而,B 则为 192.168.134.127 ,本来广播地址不同,也不能通信。

2.广播

理解了上面的知识点,接着我们来看看实现一下广播的代码,大致思路如下,pc 端的 client 发送一个 255.255.255.255 的受限广播,pc 端和 Android 接受之后,发送回应给客户端,客户端在接受之后,打印相关信息,并可以按任意键退出,并打印出已经搜索到的设备信息.

受限是客户端:

发送广播:

接着,监听服务端发送回来的信息:

接着写服务端的:

服务端也比较简单,监听即可。
接着看看Android端的,其实跟pc 的服务端一致,开发线程监听广播和发送即可,由于代码差不多,就不贴出来,具体看工程代码。
运行结果如下:
pc 服务端:

Android 服务端:

pc 客户端:

3.多播(组播)

从上面我们已经知道,在 ip 的分配中,有专门的一组留给组播的ip,从这里也可以看到,在效率上,组播比广播要优越得多。

组播组由D类IP地址和标准UDP端口号指定。 D类IP地址范围为224.0.0.0至239.255.255.255 (含)。 地址224.0.0.0是保留的,不应该使用。

而组播使用的socket api 为:MulticastSocket ,MulticastSocket 是 DatagramSocket 的子类,我们可以通过 joinGroup 来把某个地址加入到组播中;

当向多播组发送消息时,向该主机和端口发送的所有订阅的收件人都将收到消息(在数据包的生存时间内,请参见下文)。 套接字不需要是组播组的成员来向其发送消息。

当一个套接字订阅一个组播组/端口时,它接收其他主机发送到组/端口的数据报,组和端口的所有其他成员也同样。 套接字通过leaveGroup(InetAddress addr)方法放弃组中的成员资格。 多个MulticastSocket可以同时订阅组播组和端口,并且它们都将接收组数据报。

了解上面的知识后,我们做个试验,服务端接受其他组播成员加入,并打印出来,客户端则发送数据并接受服务端数据:

服务器:

客户端:

运行结果

2.4 TCP详细配置和传递基础数据

tcp 设置

首先,先看看客户端,在一般的设置中,我们可以使用 Socket socket = new Socket() 去创建客户端,而实际中个,创建 socket 可以还有配置代理,固定端口等,如下:

这里讲一下 bind 的属性,比如,我们在第一章中,socket 客户端的端口是一直变动的,这是因为我们并没有制定,而端口由系统去指定;当我们使用了 bind 之后,则客户端的端口就指定好了,不会再变动了;接着继续配置 socket 的其他属性:

需要注意的是 socket.setPerformancePreferences(1, 1, 0); 是权重的意思,就算设置成100💯100 也是1:1:1 的关系,这个可以根据业务需求去改,如果想要延迟低,则提高这个权重即可,其他的属性都说明得很清楚了。

需要注意的是,这些配置都需要在 connect 连接服务器之前,不然设置了无效;

接着看发送基础数据,这里采用 ByteBuffer 来实现,如下:

接着看服务器端的配置:
首先是创建 serverSocket:

接着配置 serversocket,这里跟客户端差不多:

上面看到 backlog 的意思,其实就是接入丢列大小,所以一般我们可以这样配置,当然也可以直接配置:

接着就是读取基础数据了:

结果如下:

2.5 UDP与TCP结合传输数据

通过 UDP 获取不同设备的ip和端口

通过 TCP 进行相互通信

设想一个案例,即我想与B设备相互通信;
但是并不知道B设备的ip和端口,但我们可以通过 udp 发送广播,找到设备 ip 和端口,再进行 tcp 通信;大概流程如下

客户端端通过 udp 广播 搜索设备,如果A或者B设备对广播的协议有响应,则发送自己的ip和端口给客户端,客户端拿到之后,再与之进行双向通信。

进行UDP通过获取IP

代码改动不大,发送广播那里,我们进行一个数据包装,采用 ByteBuffer,毕竟我们不想让每个人都与之通信。

客户端中发送广播:

通过广播,发送 cmd 和 要回送的 port ;接着,在服务端中,解析相应数据:

当 cmd 是 CMD_BROAD 才回送数据,然后把 tcp 的端口也回送回去;然后回到 client 中的 listener 去监听:

打印如下:

进行 TCP 双向通信

拿到 TCP 的设备之后,就可以进行通信了。
首先,我们先改动 客户端,让发送和接收分开:

发送

接收

这样,我们就能监听服务端的信息了,接着,我们需要改变一下服务端的;当终端也输入时,发送给其他客户端。
这里,我们也把发送和接收分开:
为了能并发,我们这里都是采用线程去处理:
发送

接收:

这样就完成了双向通信了。

实现一个多人聊天室

如果自己做服务端有做客户端,逻辑判断方面可以把自己搞死

判断是否是自身,如果不是,则通过服务端发送给其他客户端,这样就实现了我们刚才的思路; 客户端 - 服务端 - 客户端。

Android Socket(网络) 系列更新计划_android socket 版本升级-CSDN博客


http://www.kler.cn/a/459727.html

相关文章:

  • 分布式微服务项目___某污水处理项目
  • 【数据结构】双向循环链表的使用
  • Spark Runtime Filter
  • 深入浅出:Spring Boot 自定义消息转换器的实现与应用
  • Qt监控系统放大招/历经十几年迭代完善/多屏幕辅屏预览/多层级设备树/网络登录和回放
  • 铁路轨道缺陷数据集,4278张原始图片,支持YOLO,PASICAL VOC XML,COCO JSON格式的标注,可识别是否有裂缝,和间隙缺陷
  • Casino Royale靶场wp
  • C语言初阶习题【19】三子棋游戏
  • Maven:Java项目构建与管理的利器
  • 云端-IPv4 VRRP 单备份组配置实验
  • TinaCMS: 革命性的开源内容管理框架
  • 2024 开放原子开发者大会活动回顾|瀚高 IvorySQL 开源数据库在国产软件的开源实践
  • Github 2024-12-27 Java开源项目日报Top10
  • 微信小程序 单选多选radio/checkbox 纯代码分享
  • 【前端,TypeScript】TypeScript速成(五):对象类型
  • MATLAB中使用rationalfit函数进行有理函数拟合的步骤
  • 网络入侵检测系统(IDS)的安装部署
  • 使用uWSGI将Flask应用部署到生产环境
  • 指针与数组:深入C语言的内存操作艺术
  • UniApp 页面布局基础
  • Java 8 及经典面试题全解析
  • 深入探索:使用Java爬虫获取亚马逊商品图片
  • 数据库高安全—openGauss安全整体架构安全认证
  • 自动化文档处理:Azure AI Document Intelligence
  • 保姆级教程Docker部署ClickHouse镜像
  • 阿里云大模型ACP高级工程师认证模拟试题