网络通信
一、七层网络模型OSI
- OSI(Open System Interconnect),从上到下包括应用层-表示层-会话层-传输层-网络层-数据链路层-物理层
- TCP/IP 模型:应用层-传输层-网络层-数据链路层-物理层

二、基于TCP的编程模型
- 服务器
- 创建ServerSocket类型的对象并提供端口号
- 调用accept方法等待客户端连接请求
- 使用输入输出流进行通信,getInputStream()和getOutputStream()
- 关闭资源,释放Socket
- 客户端
- 创建Socket对象并提供连接的服务器地址和端口号
- 使用输入输出流进行通信
- 关闭资源释放Socket
- 常用类
- java.net.ServerSocket类主要用于描述服务器套接字信息(大插排)。
方法声明 功能介绍 ServerSocket(int port) 根据参数指定的端口号来构造对象 Socket accept() 侦听并接收到此套接字的连接请求 void close() 用于关闭套接字 - java.net.Socket类主要用于描述客户端套接字,是两台机器间通信的端点(小插排)。
方法声明 功能介绍 Socket(String host, int port) 根据指定主机名和端口来构造对象 InputStream getInputStream() 用于获取当前套接字的输入流 OutputStream getOutputStream() 用于获取当前套接字的输出流 void close() 用于关闭套接字
- java.net.ServerSocket类主要用于描述服务器套接字信息(大插排)。
package com.rf; import java.io.*; import java.net.Socket; import java.util.Scanner; public class ClientInput extends Thread { private Socket socket; private PrintStream ps = null; public ClientInput(Socket socket) { this.socket = socket; } @Override public void run() { Scanner sc = new Scanner(System.in); String s = null; while (true) { try { //(2)使用输入输出流进行通信; s = sc.nextLine(); ps = new PrintStream(socket.getOutputStream(), true); ps.println(s); if (s.contains("bye")) { break; } } catch (IOException e) { e.printStackTrace(); } } } } package com.rf; import java.io.*; import java.net.Socket; import java.util.Scanner; public class ClientOutput extends Thread { private Socket socket; private BufferedReader br = null; public ClientOutput(Socket socket) { this.socket = socket; } @Override public void run() { String s = null; try { while (true) { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); s = br.readLine(); if(s!=null) {System.out.println(s); if(s.contains("bye")){ System.out.println("用户已下线"); } } else break; } } catch (IOException e) { e.printStackTrace(); } } } package com.rf; import java.io.IOException; import java.net.Socket; public class ClientTest1 { public static void main(String[] args) { try { Socket socket=new Socket("127.0.0.1",9999); new ClientInput(socket).start(); new ClientOutput(socket).start(); } catch (IOException e) { e.printStackTrace(); } } } package com.rf; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.LinkedList; import java.util.List; public class Server { public static List<Socket> sockets = new LinkedList<>(); public static void main(String[] args) { ServerSocket ss = null; Socket socket = null; try { //(1)创建ServerSocket类型的对象并提供端口号; ss = new ServerSocket(9999); System.out.println("正在等待客户端的连接请求....."); while (true) { //(2)等待客户端的连接请求,调用accept()方法; socket = ss.accept(); System.out.println("客户端" + socket.getInetAddress() + "已上线..."); sockets.add(socket); new ServerTalk(sockets, socket).start(); } // (4)关闭Socket; } catch (IOException e) { e.printStackTrace(); } } } package com.rf; import java.io.*; import java.net.Socket; import java.util.List; public class ServerTalk extends Thread { private List<Socket> sockets; private Socket client; BufferedReader br = null; public ServerTalk(List<Socket> sockets, Socket client) { this.sockets = sockets; this.client = client; //(3)使用输入输出流进行通信; try { br = new BufferedReader(new InputStreamReader(client.getInputStream())); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { String str = null; try { while (true) { str = br.readLine(); System.out.println(client.getPort() + ":" + str); for (Socket s : sockets) { PrintStream ps = new PrintStream(s.getOutputStream(), true); if (s != client) { ps.println(s.getPort() + ":" + str); } else if(s==client) { if (str.contains("bye")) { ps.close();} } } } } catch (IOException e) { e.printStackTrace(); } } }
三、基于UDP的编程模型
- 接收方
- 创建DatagramSocket对象并提供端口号
- 创建DatagramPacket对象并提供缓冲区
- 通过Socket接收数据内容并存放到Packet中,调用receive()方法
- 关闭资源释放Socket
- 发送方
- 创建DatagramSocket对象
- 创建DatagramPacket对象并提供接收方的通信地址
- 通过Socket将Packet内容发送出去,调用send()方法
- 关闭资源释放Socket
- 常用类
- java.net.DatagramSocket类主要用于描述发送和接收数据报的套接字
方法声明 功能介绍 DatagramSocket() 使用无参的方式构造对象 DatagramSocket(int port) 根据参数指定的端口号来构造对象 void receive(DatagramPacket p) 用于接收数据报存放到参数指定的位置 void send(DatagramPacket p) 用于将参数指定的数据报发送出去 void close() 关闭Socket并释放相关资源 - java.net.DatagramPacket类主要用于描述数据报,数据报用来实现无连接包裹投递服务
方法声明 功能介绍 DatagramPacket(byte[] buf, int length) 根据参数指定的数组来构造对象,用于接
收长度为length的数据报DatagramPacket(byte[] buf, int length,
InetAddress address, int port)根据参数指定数组来构造对象,将数据报
发送到指定地址和端口InetAddress getAddress() 用于获取发送方或接收方的通信地址 int getPort() 用于获取发送方或接收方的端口号 int getLength() 用于获取发送数据或接收数据的长度 - java.net.InetAddress类主要用于描述互联网通信地址信息。
方法声明 功能介绍 static InetAddress getLocalHost() 用于获取当前主机的通信地址 static InetAddress getByName(String host) 根据参数指定的主机名获取通信地址
package com.udp; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.Arrays; public class Send { public static void main(String[] args) throws Exception { // 创建DatagramSocket对象 DatagramSocket datagramSocket=new DatagramSocket(6886); // 创建DatagramPacket对象并提供接收方的通信地址 byte[] bytes = new byte[1024]; for(int i=0;i<100;i++){ bytes[i]=(byte) i; } DatagramPacket datagramPacket=new DatagramPacket(bytes,10, InetAddress.getLocalHost(),6666); // 通过Socket将Packet内容发送出去,调用send()方法 datagramSocket.send(datagramPacket); datagramPacket=new DatagramPacket(bytes,10,10); datagramSocket.receive(datagramPacket); System.out.println(Arrays.toString(bytes)); // 关闭资源释放Socket datagramSocket.close(); } } package com.udp; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; import java.util.Arrays; public class Receive { public static void main(String[] args) { DatagramSocket datagramSocket = null; DatagramPacket datagramPacket=null; try { //创建 DatagramSocket对象并提供端口号 datagramSocket=new DatagramSocket(6666); //创建 datagramPacket提供缓冲区 byte[] b= new byte[1024]; datagramPacket=new DatagramPacket(b,100); //DatagramSocket对象接收数据内容 datagramSocket.receive(datagramPacket); System.out.println(Arrays.toString(b)); //回发数据 datagramPacket=new DatagramPacket(b,10, InetAddress.getLocalHost(),6886); datagramSocket.send(datagramPacket); } catch (Exception e) { e.printStackTrace(); }finally { datagramSocket.close(); } } }
- java.net.DatagramSocket类主要用于描述发送和接收数据报的套接字
四、URL类
- java.net.URL(Uniform Resource Identifier)类主要用于表示统一的资源定位器,也就是指向万维网上“资源”的指针。这个资源可以是简单的文件或目录,也可以是对复杂对象的引用,例如对数据库或搜索引擎的查询等
- 格式:<传输协议>://<主机名>:<端口号>/<资源地址>
| 方法声明 | 功能介绍 |
| URL(String spec) | 根据参数指定的字符串信息构造对象 |
| String getProtocol() | 获取协议名称 |
| String getHost() | 获取主机名称 |
| int getPort() | 获取端口号 |
| String getPath() | 获取路径信息 |
| String getFile() | 获取文件名 |
| URLConnection openConnection() | 获取URLConnection类的实例 |
五、URLConnection类
- java.net.URLConnection类是个抽象类,该类表示应用程序和URL之间的通信链接的所有类的超类,主要实现类有支持HTTP特有功能的HttpURLConnection类
| 方法声明 | 功能介绍 |
| InputStream getInputStream() | 获取输入流 |
| void disconnect() | 断开连接 |
package com.com; import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class URLTest { public static void main(String[] args) throws Exception { URL url = new URL("https://kaiwu.lagou.com"); System.out.println(url.getProtocol());//协议 System.out.println(url.getHost());//主机 System.out.println(url.getPath());//路径 System.out.println(url.getFile());//文件 System.out.println(url.getPort());//端口 System.out.println("-----------------"); URLConnection urlConnection =(HttpURLConnection) url.openConnection(); InputStream inputStream = urlConnection.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(inputStream)); String str=null; while ((str=br.readLine())!=null){ System.out.println(str); } } }
浙公网安备 33010602011771号