java网络通信不止UDP,TCP
预备知识
多线程
实现多线程
线程池
IO流
核心功能就是读和写
扩展功能对什么读写,怎么读写,如何优化读写
网络基础
IP
IP规定网络上所有的设备都必须有一个独一无二的IP地址,就好比是邮件上都必须注明收件人地址,邮递员才能将邮件送到。同理,每个IP信息包都必须包含有目的设备的IP地址,信息包才可以正确地送到目的地。同一设备不可以拥有多个IP地址,所有使用IP的网络设备至少有一个唯一的IP地址
OSI模型
TCP/IP模型
网络通信
基本思路:
- 存在着两台主机client,和server
- 两方通过ip和端口号确定对方位置
- 通过socket传递信息
TCP
TCP协议全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的RFC 793定义。TCP 是面向连接的、可靠的流协议。,
• 它充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在 UDP 中都没有。
• 此外,TCP 作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。
• 根据 TCP 的这些机制,在 IP 这种无连接的网络上也能够实现高可靠性的通信( 主要通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)客户端创建socket,服务端接受socket,然后再通过socket传递信息
• 用到的主要的类:
• Socket
• ServerSocket
• I/O相关
• 类之间的关系
• InetSocketAddress继承SocketAddress,作用是存储ip地址和端口号
• Inet4Address与Inet6Address继承InetAddress,作用存储p地址
创建
private static class InetSocketAddressHolder {
// The hostname of the Socket Address
private String hostname;
// The IP address of the Socket Address
private InetAddress addr;
// The port number of the Socket Address
private int port;
}
//要端口和ip地址,InetAddress提供ip地址,port提供端口
分析
Socket构造方法做了些什么:
- 创建一个SocksSocketImpl实例
- 调用bind()绑定本地端口和地址(如果不为空)实际上是调用的SocksSocketImpl的bind方法
- 调用connect()连接远程主机和端口
大多数会调用两个私有的构造函数,空实现以及传入Proxy构造对象时需要手动调用connect(),进行连接
package-private一般是为了功能的实现
ServerSocket构造方法做了些什么 - 创建一个SocksSocketImpl实例
- 调用bind()绑定本地监听端口(必须绑定)和地址以及确定backlog(无法绑定抛出异常)
- 参数port指定服务器要绑定的端口(即服务器要监听的端口,注意端口号为零时自动分配),参数backlog指定客户连接请求队列的长度,参数bindAddr指定服务器要绑定的IP地址。
- 默认构造方法:允许服务器在绑定到特定端口之前,先设置ServerSocket的一些选项。因为一旦服务器与特定端口绑定,有些选项就不能再改变了。
public ServerSocket(int port, int backlog, InetAddress bindAddr)
设置Socket选项
·TCP_NODELAY:表示立即发送数据。
·SO_RESUSEADDR:表示是否允许重用Socket所绑定的本地地址。
·SO_TIMEOUT:表示接收数据时的等待超时时间。
·SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket。
·SO_SNDBUF:表示发送数据的缓冲区的大小。
·SO_RCVBUF:表示接收数据的缓冲区的大小。
·SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。
·OOBINLINE:表示是否支持发送1字节的TCP紧急数据。
设置ServerSocket选项
·SO_TIMEOUT:表示等待客户连接的超时时间。
·SO_REUSEADDR:表示是否允许重用服务器所绑定的地址。
·SO_RCVBUF:表示接收数据的缓冲区的大小
服务
• 客户端:对象创建成功并且连接到远程主机后可以获取一些信息,已经通过getOutPutStream()与getInputStream()获取I/o流对象读入和写入信息
• 服务器:监听接口接受客户端的socket对象,再从中获取信息
关闭
可以以一个标志作为是否结束的判断(比如输入bye)
半关闭:
调用Socket的close()方法关闭Socket后,它的输出流和输入流也都被关闭。有的时候,可能仅仅希望关闭输出流或输入流之一
shutdownInput():关闭输入流。shutdownOutput():关闭输出流。
完全关闭:
为了确保关闭,要将socket.close放在finally中(实现了java.lang.Auto Closable接口。这意味着如果在try代码块中打开或创建了这些类的实例,那么即使程序没有显式地关闭它们,Java虚拟机也会在退出try代码块时自动关闭它们,释放相关的资源)
服务器同时与多个客户端连接
方式1:为每个客户分配一个工作线程。
方式2:创建一个线程池,由其中的工作线程来为客户服务.
方式3:利用JDK的Java类库中现成的线程池,由它的工作线程来为客户服务。
单独分配线程
- 主线程负责接收客户端的连接,创造工作线程负责通信
- 每个线程负责一个客户端
自定义线程池
使用jdk内置线程池
java.util.concurrent
线程池的缺点
1.死锁
2.系统资源不足
3.并发错误
4.线程泄漏
5.任务过载
UDP
• UDP 不提供复杂的控制机制,利用 IP 提供面向无连接的通信服务。
• 并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP 也无法进行流量控制等避免网络拥塞行为。
• 此外,传输途中出现丢包,UDP 也不负责重发。
• 甚至当包的到达顺序出现乱序时也没有纠正的功能。
• 如果需要以上的细节控制,不得不交由采用 UDP 的应用程序去处理。
• UDP 常用于一下几个方面:1.包总量较少的通信(DNS、SNMP等);2.视频、音频等多媒体通信(即时通信);3.限定于 LAN 等特定网络中的应用通信;4.广播通信(广播、多播)。
• 客户端通过DataPacket保存信息,DataSocket发送packet信息,服务端通过监听端口接受Packet
DataPacket
• 发送信息的packet必须要指定地址和端口,接受信息的packet则不必指定
• 数据报中只能存放字节形式的数据,在发送方,需要把其他格式的数据转换为字节序列,在接收方,需要把字节序列转换为原来格式的数据(可以利用ByteArrayOutputStream和DataOuputStream)
• 可以利用ByteArrayInputStream和DataInputStream来把字节序列转换为原来格式的数据
DataSocket
DatagramSocket类负责接收和发送数据报。在客户程序中,一般由操作系统为DatagramSocket类分配本地端口,这种端口也被称为匿名端口。在服务器程序中,一般由程序显式地为DatagramSocket类指定本地端口。
• 每个DatagramSocket对象都会与一个本地端口绑定(在构造方法中就自动绑定,不提供则随机分配),在此端口监听发送过来的数据报。在recieve()方法中还会进一步检查.
• connect()是可选的 ,但与TCP的连接不一样,前者不建立TCP意义上的连接,而是限制当前DatagramSocket或DatagramChannel只对参数指定的远程主机和UDP端口收发数据报。
组播
单播:提供点对点的通信。发送者每次发送的数据有着唯一的目的地址,只被一个接收者接收。前面介绍的TCP Socket和UDP Socket都只支持单播。
组播:发送者每次发送的数据可以被小组内的所有接收者接收。
广播:发送者每次发送的数据可以被传播范围内的所有接收者接收
原理
组播地址:
组播组内的所有主机共享同一个地址,这种地址被称为组播地址,组播地址是范围在224.0.0.0 ~239.255.255.255之间的IP地址。此范围内的所有地址的前4个二进制位都是“1110”。组播地址也被称为D类IP地址,
使用UDP:
大多数组播数据为音频或视频,这些数据一般都很大,即便部分数据在传输途中被丢失,接收方也仍然能识别信号。因此组播数据通过UDP发送,虽然不可靠,但比面向连接的TCP的传输速度快3倍以上。
TTL(Time to live)
这也是与单播UDP不同的地方
好处
如图:在从主机1到路由器2的途中数据只需要传输一次,(单播对数据进行了不必要的复制,浪费了许多网络带宽。如果采用组播,则可以大大提高传输效率,路由器会动态决定组播数据的路由,只在必要时才复制数据)。
实现
java.net.MulticastSocket具有组播的功能,它是DatagramSocket的子类
非阻塞通信
什么是阻塞
放弃CPU,暂停运行,只有等到导致阻塞的原因消除,才能恢复运行;或者被其他线程中断,该线程会退出阻塞状态,并且抛出InterruptedException(比如烧水,一直等水烧开后再做其他事)
阻塞的原因
线程阻塞
1.线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n ms,然后恢复运行。
2.线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,等到获得了同步锁,才能恢复运行。
3. 线程执行了一个对象的wait()方法,进入阻塞状态,只有等到其他线程执行了该对象的notify()或notifyAll() 方法,才可能将其唤醒。
4. 线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。例如当线程执行System.in.read() 方法时,如果用户没有向控制台输入数据,则该线程会一直等读到了用户的输入数据才从read()方法返回。
客户端阻塞
- 请求与服务器建立连接时,即当线程执行Socket的带参数的构造方法,或执行Socket的connect()方法时,会进 入阻塞状态,直到连接成功,此线程才从Socket的构造方法或connect()方法返回。
- 线程从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达 输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断.
- 输入流中有多少数据才算足够呢?这要看线程执行的read()方法的类。
(1)int read():只要输入流中有1字节,就算足够。
(2)int read(byte[] buff):只要输入流中的字节数目与参数buff数组的长度相同,就算足够。
(3)String readLine():只要输入流中有1行字符串,就算足够。 - 线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流 的write()方法返回或异常中断。
- 如果调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close()方法 时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。
服务端阻塞
- 线程执行ServerSocket的accept()方法,等待客户的连接,直到接收到了客户连接,才从accept()方法返回。
- 线程从Socket的输入流读入数据时,如果输入流没有足够的数据,就会进入阻塞状态。
- 线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流 的write()方法返回或异常中断。
实现
java.nio.channels包提供了支持非阻塞通信的类
·ServerSocketChannel:ServerSocket的替代类,支持阻塞通信与非阻塞通信。
·SocketChannel:Socket的替代类,支持阻塞通信与非阻塞通信。
·Selector:为ServerSocketChannel监控接收连接就绪事件,为 SocketChannel监控连接就绪、读就绪和写就绪事件。
·SelectionKey:代表ServerSocketChannel以及SocketChannel向Selector注册事件的句柄。当一个SelectionKey对象位于Selector对象的selected-keys集合中,就表示与这个SelectionKey对象相关的事件发生了。
java网络通信不止UDP,TCP的更多相关文章
- java 网络编程 UDP TCP
网络编程 网络编程主要用于解决计算机与计算机(手机.平板..)之间的数据传输问题. 网络编程: 不需要基于html页面就可以达到数据之间的传输. 比如: feiQ , QQ , 微信....网页编程: ...
- Java基础之UDP协议和TCP协议简介及简单案例的实现
写在前面的废话:马上要找工作了,做了一年的.net ,到要找工作了发现没几个大公司招聘.net工程师,真是坑爹呀.哎,java就java吧,咱从头开始学呗,啥也不说了,玩命撸吧,我真可怜啊. 摘要: ...
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- java基础55 UDP通讯协议和TCP通讯协议
本文知识点(目录): 1.概述 2.UDP通讯协议 3.TCPP通讯协议 1.概述 1.在java中网络通讯作为Socket(插座)通讯,要求两台都必须安装socket. 2.不同的 ...
- 4.Java网络编程之TCP/UDP
常见传输协议: UDP , TCP UDP协议: 特点: 1.将数据及源和目的封装成数据包中,不需要建立连接 2.每个数据包的大小限制在64K内 ...
- Java网络通信初步认知
本文转载自:http://wing011203.cnblogs.com/ 在这篇文章里,我们主要讨论如何使用Java实现网络通信,包括TCP通信.UDP通信.多播以及NIO. TCP连接 TCP的基础 ...
- Java程序员从笨鸟到菜鸟之(十三)java网络通信编程
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 首先声明一下,刚开始学习java网络通信编程就对他有一种畏惧感,因为自己对网络一窍不通,所 ...
- JAVA 通过 Socket 实现 TCP 编程
简介 TCP简介 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义.在简化的计算机 ...
- Java中的UDP协议编程
一. UDP协议定义 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包.在OSI模型中,在第四层——传输层,处于IP协议的上一层.UDP有不提供数据报分组.组装和不能对数据包 ...
随机推荐
- Explain 索引优化分析
Explain 语法 # 语法 explain + DQL语句 mysql> explain select * from city where countrycode ='CHN' or cou ...
- Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...
- spring-cloud-netflix-hystrix-turbine
Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数 ...
- CodeForces 1047C Enlarge GCD(数论)题解
题意:n个数的gcd是k,要你删掉最少的数使得删完后的数组的gcd > k 思路:先求出k,然后每个数除以k.然后找出出现次数最多的质因数即可. 代码: #include<cmath> ...
- set CSS style in js solutions All In One
set CSS style in js solutions All In One css in js set each style property separately See the Pen se ...
- 如何给 GitHub 添加 SSH key, 如何生成 SSH key 详细图文教程!
如何给 GitHub 添加 SSH key, 如何生成 SSH key 详细图文教程! 一. 生成 SSH key https://ide.c9.io/xgqfrms/ 创建一个空项目:(或使用 ...
- 微信小程序 HTTP API
微信小程序 HTTP API promise API https://www.npmtrends.com/node-fetch-vs-got-vs-axios-vs-superagent node-f ...
- style element & web components
style element & web components style.textContent style.setContent bug style.textContent const st ...
- svn conflict & svn cleanup
svn conflict & svn cleanup OK $ svn --help $ svn cleanup Tree Conflicts https://tortoisesvn.net/ ...
- website url spam
website url spam xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!