Java核心类库篇8——网络编程
1、七层网络模型
-
OSI(Open System Interconnect),即开放式系统互联,是ISO(国际标准化组织)组织在1985 年研究的网络互连模型。
-
当发送数据时,需要对发送的内容按照上述七层模型进行层层加包后发送出去。
-
当接收数据时,需要对接收的内容按照上述七层模型相反的次序层层拆包并显示出来
2、协议
计算机在网络中实现通信就必须有一些约定或者规则,这种约定和规则就叫做通信协议,通信协议 可以对速率、传输代码、代码结构、传输控制步骤、出错控制等制定统一的标准。
2.1、TCP(传输控制协议Transmission Control Protocol)
- 面向连接的协议
- 建立连接 => 进行通信 => 断开连接
- 在传输前采用"三次握手"方式
- 在通信的整个过程中全程保持连接,形成数据传输通道
- 保证了数据传输的可靠性和有序性
- 是一种全双工的字节流通信方式,可以进行大数据量的传输
- 传输完毕后需要释放已建立的连接,发送数据的效率比较低
2.2、UDP(用户数据报协议User Datagram Protocol)
- 非面向连接的协议
- 在通信的整个过程中不需要保持连接,其实是不需要建立连接
- 不保证数据传输的可靠性和有序性
- 是一种全双工的数据报通信方式,每个数据报的大小限制在64K内
- 发送数据完毕后无需释放资源,开销小,发送数据的效率比较高,速度快
3、IP与端口
- IP地址是互联网中的唯一地址标识,本质上是由32位二进制组成的整数,叫做IPv4,当然也有128 位二进制组成的整数,叫做IPv6,目前主流的还是IPv4
- 端口号本质上是16位二进制组成的整数,表示范围是:0 ~ 65535,其中0 ~ 1024之间的端口号通 常被系统占用,建议编程从1025开始使用
- IP地址 - 可以定位到具体某一台设备
- 端口号 - 可以定位到该设备中具体某一个进程
- 网络编程需要提供:IP地址 + 端口号,组合在一起叫做网络套接字(InetSocketAddress):Socket
4、TCP网络编程
ServerSocket
方法声明 | 功能介绍 |
---|---|
public ServerSocket(int port) | 根据参数指定的端口号来构造对象 |
public Socket accept() | 侦听并接收到此套接字的连接请求 |
public void close() | 用于关闭套接字 |
Socket
方法声明 | 功能介绍 |
---|---|
public Socket(String host, int port) | 根据指定主机名和端口来构造对象 |
public InputStream getInputStream() | 用于获取当前套接字的输入流 |
public OutputStream getOutputStream() | 用于获取当前套接字的输出流 |
public void close() | 用于关闭套接字 |
4.1、客户端发给服务器端
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream=null;
try {
serverSocket = new ServerSocket(8099);
System.out.println("等待客户端连接");
socket = serverSocket.accept();
System.out.println("终于等到你");
//Thread.sleep(10000);
inputStream = socket.getInputStream();
int len=0;
byte[] buffer = new byte[1024];
while ((len=inputStream.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
} finally {
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream=null;
try {
socket = new Socket("127.0.0.1", 8099);
outputStream = socket.getOutputStream();
outputStream.write("hello, i am ruoye!".getBytes());
outputStream.flush();
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.2、服务器响应
字节输入输出流会出现问题read无法读到-1,此时应当
outputStream.flush();
socket.shutdownOutput();
但在多次通信时,关闭流显然不合适
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream=null;
OutputStream outputStream=null;
try {
serverSocket = new ServerSocket(8099);
System.out.println("等待客户端连接");
socket = serverSocket.accept();
System.out.println("终于等到你");
// Thread.sleep(10000);
inputStream = socket.getInputStream();
int len=0;
byte[] buffer = new byte[1024];
while ((len=inputStream.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
System.out.println("服务器收到消息");
outputStream = socket.getOutputStream();
outputStream.write("i know".getBytes());
outputStream.flush();
socket.shutdownOutput();
System.out.println("服务器发送消息");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream=null;
InputStream inputStream=null;
try {
socket = new Socket("127.0.0.1", 8099);
outputStream = socket.getOutputStream();
outputStream.write("hello, i am ruoye!".getBytes());
System.out.println("客户端发送消息成功");
outputStream.flush();
socket.shutdownOutput();
inputStream = socket.getInputStream();
int len=0;
byte[] buffer = new byte[1024];
while ((len=inputStream.read(buffer))!=-1){
System.out.println(new String(buffer,0,len));
}
System.out.println("客户端接收消息");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.3、DataInputStream流
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream=null;
OutputStream outputStream=null;
try {
serverSocket = new ServerSocket(8099);
System.out.println("等待客户端连接");
socket = serverSocket.accept();
System.out.println("终于等到你");
// Thread.sleep(10000);
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
System.out.println(dataInputStream.readUTF());
System.out.println("服务器收到消息");
outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("i know!");
System.out.println("服务器发送消息");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream=null;
InputStream inputStream=null;
try {
socket = new Socket("127.0.0.1", 8099);
outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("i am ruoye!");
System.out.println("客户端发送消息成功");
System.out.println("================="+outputStream);
outputStream.write("hello, i am ruoye!".getBytes());
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
System.out.println(dataInputStream.readUTF());
System.out.println("客户端接收消息");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.4、简易聊天室
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream=null;
OutputStream outputStream=null;
try {
serverSocket = new ServerSocket(8099);
System.out.println("等待客户端连接");
socket = serverSocket.accept();
System.out.println("终于等到你");
while (true) {
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
String s = dataInputStream.readUTF();
System.out.println(s);
if ("bye".equalsIgnoreCase(s)){
break;
}
outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("收到"+s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream=null;
InputStream inputStream=null;
Scanner scanner=new Scanner(System.in);
try {
socket = new Socket("127.0.0.1", 8099);
outputStream = socket.getOutputStream();
while (true) {
String next = scanner.next();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(next);
if ("bye".equalsIgnoreCase(next)){
break;
}
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
System.out.println(dataInputStream.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.5、多人聊天室
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8099);
while (true){
System.out.println("等待客户端连接");
Socket socket = serverSocket.accept();
System.out.println("终于等到你");
new Thread(new Conversation(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Conversation implements Runnable {
private Socket socket;
public Conversation(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream inputStream=null;
OutputStream outputStream=null;
try {
while (true) {
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
String s = dataInputStream.readUTF();
System.out.println("收到 "+socket.getInetAddress()+" "+socket.getPort()+"的消息:"+s);
if ("bye".equalsIgnoreCase(s)){
break;
}
outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("收到 "+socket.getInetAddress()+" "+socket.getPort()+":"+s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream=null;
InputStream inputStream=null;
Scanner scanner=new Scanner(System.in);
try {
socket = new Socket("127.0.0.1", 8099);
outputStream = socket.getOutputStream();
while (true) {
String next = scanner.next();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(next);
if ("bye".equalsIgnoreCase(next)){
break;
}
inputStream = socket.getInputStream();
DataInputStream dataInputStream=new DataInputStream(inputStream);
System.out.println(dataInputStream.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
5、UDP网络编程
DatagramSocket
用于描述发送和接收数据报的套接字(包裹投递服务的发送或接收点)
方法声明 | 功能介绍 |
---|---|
public DatagramSocket() | 使用无参的方式构造对象 |
public DatagramSocket(int port) | 根据参数指定的端口号来构造对象 |
public void receive(DatagramPacket p) | 用于接收数据报存放到参数指定的位置 |
public void send(DatagramPacket p) | 用于将参数指定的数据报发送出去 |
public void close() | 关闭Socket并释放相关资源 |
DatagramPacket
要用于描述数据报(用来实现无连接包裹投递服务)
方法声明 | 功能介绍 |
---|---|
public DatagramPacket(byte[] buf, int length) | 根据参数指定的数组来构造对象,用于接 收长度为length的数据报 |
public DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 根据参数指定数组来构造对象,将数据报 发送到指定地址和端口 |
public InetAddress getAddress() | 用于获取发送方或接收方的通信地址 |
public int getPort() | 用于获取发送方或接收方的端口号 |
public int getLength() | 用于获取发送数据或接收数据的长度 |
InetAddress
方法声明 | 功能介绍 |
---|---|
public static InetAddress getLocalHost() | 用于获取当前主机的通信地址 |
public static InetAddress getByName(String host) | 根据参数指定的主机名获取通信地址 |
5.1、简易广播
public class Receive {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(8099);
byte[] bytes=new byte[512];
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
System.out.println("等待发送消息");
datagramSocket.receive(datagramPacket);
System.out.println("等待到的内容"+new String(bytes));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket!=null){
datagramSocket.close();
}
}
}
}
public class Send {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(8100);
String str="hello udp!";
DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(), str.length(),new InetSocketAddress("127.0.0.1",8099));
datagramSocket.send(datagramPacket);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket!=null){
datagramSocket.close();
}
}
}
}
5.1、带回复的广播
public class Receive {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(8099);
byte[] bytes=new byte[512];
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
System.out.println("等待发送消息");
datagramSocket.receive(datagramPacket);
System.out.println("等待到的内容"+new String(bytes,0,datagramPacket.getLength()));
String str = "i know";
DatagramPacket datagramPacket1 = new DatagramPacket(str.getBytes(), str.length(),datagramPacket.getAddress(),datagramPacket.getPort());
datagramSocket.send(datagramPacket1);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket!=null){
datagramSocket.close();
}
}
}
}
public class Send {
public static void main(String[] args) {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(8100);
String str="hello udp!";
DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(), str.length(),new InetSocketAddress("127.0.0.1",8099));
datagramSocket.send(datagramPacket);
byte[] bytes=new byte[512];
DatagramPacket datagramPacket1 = new DatagramPacket(bytes,bytes.length);
System.out.println("等待回复消息");
datagramSocket.receive(datagramPacket1);
System.out.println("等待到的回复内容"+new String(bytes,0,datagramPacket1.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (datagramSocket!=null){
datagramSocket.close();
}
}
}
}
6、URL
统一资源定位器
<传输协议>://<主机名>:<端口号>/<资源地址>
方法声明 | 功能介绍 |
---|---|
URL(String spec) | 根据参数指定的字符串信息构造对象 |
String getProtocol() | 获取协议名称 |
String getHost() | 获取主机名称 |
int getPort() | 获取端口号 |
String getPath() | 获取路径信息 |
String getFile() | 获取文件名 |
URLConnection openConnection() | 获取URLConnection类的实例 |
URLConnection
方法声明 | 功能介绍 |
---|---|
InputStream getInputStream() | 获取输入流 |
void disconnect() | 断开连接 |
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("https://www.baidu.com/");
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}