JAVA SE自学 基础篇 IO基础
目标
- 网络相关概念
- 使用Socket类和ServerSocket类进行TCP通信
- 使用DatagramSocket类和DatagramPacket类进行UDP通信
- 理解网络通信基本编程模型
概念
两台计算机要进行通信, 必须要有IP地址(ip address)
和端口(port)
有时候, IP地址也可以用主机名(hostname)替代:
- localhost 表示 本机 , 其地址相当于127.0.0.1 ( 本机回环地址 )
端口范围从065535, 其中01023是系统保留端口, 编程中尽量不要使用.
主动发起通信请求的一端称为客户端 (client) , 这要求客户端必须知道服务端的IP地 址和端口.
提供服务的一端称为服务端(server), 服务端必须随时在某个特定端口上待命, 这称为 监听(listening).
C / S , Client / Server, "客户端 / 服务器" 模型, 例如: QQ, MSN, LOL, 360安全卫士...
B / S , Browser / Server , "浏览器 / 服务器" 模型, 例如: taotao, jd, zhihu...
事实上, B就是一种通用的C, 浏览器具有解释执行网页代码的能力, 在BS模型中, 服务 器返回给浏览器的就是网页代码, 这意味着我们可以把所有的程序资源都部署在服务器上, 用户只需要一个浏览器就可以请求服务器的服务.
CS模型不便于升级维护, 但它不依赖于浏览器, 它能实现更炫丽的用户界面
BS模型反之
通信双方必须遵循某一约定, 这些约定称为通信协议 ( protocol )
OSI参考模型规定了通信协议的7个层次:
常见的通信协议有:
- tcp
- udp
- ftp
- http
- pop3
- smtp
- soap
- …
TCP, UDP属于传输层协议
ftp, http等协议属于应用层协议, 它的层次比传输层高, 但它们通常是基于tcp来实现 的.
TCP ( Transfer Control Protocol ) , 传输控制协议 , 它面向连接 , 可靠性 高 , 在传输数据之前需要建立连接(三次握手), 它像打电话, 通信结束后需要断开连接 (四次挥手).
UDP( User Datagram Protocol ) , 用户数据报协议, 它不面向连接, 可靠性低, 但效率高, 它像写信
在JAVA网络编程中, 通常把IP地址和端口号封装起来, 称为Socket套接字
JAVA中, 网络编程主要使用的包是==java.net ==
TCP编程
主要的类:
-
ServerSocket 服务端套接字, 用于监听端口, 接受客户端连接(Socket)
- ServerSocket(int port) // port为绑定和监听的端口
号 - accept(): Socket // 接受一个客户端的TCP连接, 接受 成功即握手成功. 要注意这是一个阻塞方法 ( block ).
- ServerSocket(int port) // port为绑定和监听的端口
-
Socket 客户端套接字, 一个Socket对象, 对应一个客户端
- Socket(String ip, int port) // 发起TCP连接, 一旦 服务端accept()就意味着握手成功. ip为服务端地址, port为 服务端监听的端口
- getOutputStream()
- getInputStream()
-
InetAddress 类表示的就是IP地址
- getLocalHost() // 返回本机地址
- getByName(String) // 把字符串类型的IP地址封装成 InetAddress类型
开发步骤:
- 服务端实例化ServerSocket, 并调用accept()接受客户端套接字
ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();
- 客户端实例化Socket
Socket socket = new Socket("127.0.0.1",8080);
- 利用Socket和流进行双工通信
网络编程的基本线程模型
客户端:
服务端:
UDP编程
主要的类:
- DatagramPacket 表示数据包
- DatagramSocket 负责接收和发送数据包
- send() 发送数据包
- receive() 接收数据包
第一个要注意的是构造器的使用:
- 如果是发送方
构造DatagramPacket时要传入:- 数据内容byte[] 及长度/偏移量
- 目标地址
- 目标端口
构造DatagramSocket时不需要任何参数!
- 如果是接收方
构造DatagramSocket时需要传入:
- 端口
构造一个空的DatagramPacket时需要传入: - 没有任何数据的byte[], 其长度为双方约定的大信息长度
第二个要注意的是接收方在拆包里的操作:
由于空包的byte[]是双方约定的大长度, 但实际上收到的数据包的数据长度可能达不 到. 所以DatagramPacket提供了getLength()方法, 这表示实际接收到的数据的长 度!, 拆包里注意使用这个长度, 抛弃掉无效字节.
发送方示例:
接收方示例:
基于HTTP的高级(应用层)通信编程
- URL
- openConnection()
- URLConnection
- getInputStream()
- getOutputStream()