Java回炉学习(九)
1. ip4地址分类
2. InetAddress 类
- 获取本机InetAddress对象getLocalHost
- 根据指定主机名/域名获取ip地址对象getByName
- 获取InetAddress对象的主机名getHostName
- 获取InetAddress对象的地址getHostAddress
3. Socket
-
套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
-
通信的两端都要有Socket,是两台机器间通信的端点
-
网络通信其实就是Socket间的通信。
-
示例:server端:
@SuppressWarnings({"all"}) public class Homework01Server { public static void main(String[] args) throws IOException { //思路 //1. 在本机 的9999端口监听, 等待连接 // 细节: 要求在本机没有其它服务在监听9999 // 细节:这个 ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发] ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端,在9999端口监听,等待连接.."); //2. 当没有客户端连接9999端口时,程序会 阻塞, 等待连接 // 如果有客户端连接,则会返回Socket对象,程序继续 Socket socket = serverSocket.accept(); // //3. 通过socket.getInputStream() 读取客户端写入到数据通道的数据, 显示 InputStream inputStream = socket.getInputStream(); //4. IO读取, 使用字符流, 老师使用 InputStreamReader 将 inputStream 转成字符流 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); String answer = ""; if ("name".equals(s)) { answer = "我是韩顺平"; } else if("hobby".equals(s)) { answer = "编写java程序"; } else { answer = "你说的啥子"; } //5. 获取socket相关联的输出流 OutputStream outputStream = socket.getOutputStream(); // 使用字符输出流的方式回复信息 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write(answer); bufferedWriter.newLine();// 插入一个换行符,表示回复内容的结束 bufferedWriter.flush();//注意需要手动的flush //6.关闭流和socket bufferedWriter.close(); bufferedReader.close(); socket.close(); serverSocket.close();//关闭 } }
-
client:
@SuppressWarnings({"all"}) public class Homework01Client { public static void main(String[] args) throws IOException { //思路 //1. 连接服务端 (ip , 端口) //解读: 连接本机的 9999端口, 如果连接成功,返回Socket对象 Socket socket = new Socket(InetAddress.getLocalHost(), 9999); //2. 连接上后,生成Socket, 通过socket.getOutputStream() // 得到 和 socket对象关联的输出流对象 OutputStream outputStream = socket.getOutputStream(); //3. 通过输出流,写入数据到 数据通道, 使用字符流 BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); //从键盘读取用户的问题 Scanner scanner = new Scanner(System.in); System.out.println("请输入你的问题"); String question = scanner.next(); bufferedWriter.write(question); bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束, 注意,要求对方使用readLine()!!!! bufferedWriter.flush();// 如果使用的字符流,需要手动刷新,否则数据不会写入数据通道 //4. 获取和socket关联的输入流. 读取数据(字符),并显示 InputStream inputStream = socket.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String s = bufferedReader.readLine(); System.out.println(s); //5. 关闭流对象和socket, 必须关闭 bufferedReader.close();//关闭外层流 bufferedWriter.close(); socket.close(); System.out.println("客户端退出....."); } }
4. netstat
netstat -an
可以查看当前主机网络情况,包括端口监听情况和网络连接情况,netstat -an | more
可以分页显示,要求在dos控制台下执行win+r
- 当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的, 是随机的.
5. UDP 网络通信编程
- **类DatagramSocket和DatagramPacket[数据包/数据报]**实现了基于UDP协议网络程序。
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。
- 1.核心的两个类/对象DatagramSocket与DatagramPacket 2.建立发送端,接收端(没有服务端和客户端概念) 3.发送数据前,建立数据包/报DatagramPacket对象 4.调用DatagramSocket的发送、 接收方法 5.关闭DatagramSocket
6. QQ 聊天项目后端框架
7. io与网络编程
- BIO(同步阻塞) 服务端需要对客户端的每个请求处理完成后 才会继续接受客户端的请求,客户端也会等待服务端处理完请求后才会发送请求,通常会使用多线程去处理 因为BIO每个连接一个单独的线程
- NIO(同步非阻塞) NIO使用单线程或者只使用少量的多线程,一个请求一个线程,多个连接共用一个线程。(即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。) (可以使用资源池或者队列等手段实现异步的处理)
- AIO(异步非阻塞) AIO的读写方法都是异步的 完成后会主动调用回调函数
- 快速理解:
- AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。
- NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。
- BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。
- 三者区别:
- BIO:BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
- NIO:NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
- AIO:AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
8. 重定向与转发的区别:
- 重定向访问服务器两次,转发只访问服务器一次。
- 重定向可以看见目标页面的URL,转发只能看见第一次访问的页面URL,以后的工作都是有服务器来做的。
- 重定向跳转后必须加上return,要不然页面虽然跳转了,但是还会执行跳转后面的语句,转发是执行了跳转页面,下面的代码就不会在执行了。
- 在request级别使用信息共享,使用重定向必然出错
- 还有一个大的区别就是,重定向可以访问自己web应用以外的资源