1. 获取网络地址ip/domin
InetAddress获取
public class TestInetAddress { public static void main(String[] args) throws UnknownHostException { InetAddress inetAddress = InetAddress.getByName("127.0.0.1"); InetAddress localhost = InetAddress.getByName("localhost"); InetAddress localHost = InetAddress.getLocalHost(); InetAddress localhost1 = InetAddress.getByName("DESKTOP-146VINF"); // 本机用户名 InetAddress localhost2 = InetAddress.getByName("www.baidu.com"); byte[] address = new byte[]{(byte) 192, (byte) 168,5,2}; InetAddress byAddress = InetAddress.getByAddress(address); System.out.println(inetAddress); System.out.println(localhost); System.out.println(localHost); System.out.println(localhost1); System.out.println(localhost2); System.out.println(byAddress); System.out.println(localhost.getAddress()); System.out.println(localhost.getCanonicalHostName()); // 获取规范名 System.out.println(localhost.getHostAddress()); // ip System.out.println(localhost.getHostName()); // 域名 主机名 } }
Port 端口
计算机端口号用于区分不同的进程
计算机端口按端口号可分为3大类:
(1)公认端口:从0到1023,它们紧密绑定于一些服务。通常这些端口的通讯明确表明了某种服务的协议。常用的有:http: 80 https: 443 ftp: 21 ssh: 22 telnet: 23
(2)注册端口:从1024到49151。它们松散地绑定于一些服务。也就是说有许多服务绑定于这些端口,这些 端口同样用于许多其它目的。常用的有:TomCat: 8080 MySql: 3306 Oracle:1506
(3)动态和/或私有端口:从49152到65535。理论上,不应为服务分配这些端口。实际上,机器通常从 1024起分配动态端口。
对于不同的传输层传输协议,在进行数据封装时包头信息不一样,即使UDP包和TCP包使用同一个端口,也不会导致端口冲突。
查看端口命令
netstat -a # netstat -ano|findstr "7024" #查看指定端口 tasklist|findstr "7024" # 查看指定端口进程
InetSocketAddress
public class TestInetSocketAddress { public static void main(String[] args) { InetSocketAddress localhost = new InetSocketAddress("192.168.5.3", 8080); // ip/主机+创建端口对象 System.out.println(localhost.getAddress()); System.out.println(localhost.getHostName()); System.out.println(localhost.getPort()); // 获得端口号 System.out.println(localhost.getHostString()); } }
通信协议
传输层通信协议
- TCP:面向连接
- UDP:非面向连接
TCP编程实现
Java语言的基于套接字编程分为服务端编程和客户端编程,其通信模型如图所示
TCP编程简单C/S通信示例
1、客户端Socket的工作过程包含以下四个基本的步骤:
创建 Socket:根据指定服务端的 IP 地址或端口号构造 Socket 类对象。若服务器端响应,则建立客户端到服务端的通信路线。若连接失败,则会出现异常。
打开连接到 Socket 的输入/出流: 使用 getInputStream()方法获得输入流,使用 getOutputStream()方法获得输出流,进行数据传输
按照一定的协议对 Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入路线的信息),通过输出流将信息写入线程
import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.nio.charset.StandardCharsets; public class TestTcpClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost",8888); OutputStream outputStream = socket.getOutputStream(); outputStream.write("小逼崽子,是不是没见过黑社会,敢不敢跟我比划比划".getBytes(StandardCharsets.UTF_8)); if (outputStream!=null){ outputStream.close(); } if (socket!=null){ socket.close(); } } }
2、服务器(服务端)程序的工作过程包含以下四个基本的步骤:
调用 ServerSocket(int port) :创建一个服务器端套接字,并绑定到指定端口 上。用于监听客户端的请求。
调用 accept():监听连接请求,如果客户端请求连接,则接受连接,返回通信 套接字对象。
调用 该Socket类对象的 getOutputStream() 和 getInputStream ():获取输出 流和输入流,开始网络数据的发送和接收。
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class TestTcpServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("连接建立中"); Socket clientSocket = serverSocket.accept(); System.out.println("与"+clientSocket.getInetAddress()+"成功建立连接"); InputStream inputStream = clientSocket.getInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len=0; while ((len=inputStream.read(buffer))!=-1){ out.write(buffer,0,len); System.out.println(out.toString());![](https://img2020.cnblogs.com/blog/2300439/202104/2300439-20210419235830981-132043291.png) File received = new File("test.png"); FileOutputStream output = new FileOutputStream(received); while ((len=inputStream.read(bufferFile))!=-1){ output.write(bufferFile,0,len); } // 接受完毕,告知客户断开连接 OutputStream outputStream = socket.getOutputStream(); outputStream.write("接收成功".getBytes(StandardCharsets.UTF_8)); output.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
TCP编程实现C/S文件传输
Server:
import java.io.*; import java.net.Socket; public class TestTcpFileTransportClient { public static void main(String[] args) throws IOException { // 创建socket Socket socket = new Socket("localhost",4396); // 创建流 OutputStream outputStream = socket.getOutputStream(); // 读取文件 File file = new File("./StaticSrc/images/img.png"); byte[] buffer = new byte[1024]; // 文件输入流 FileInputStream fileInputStream = new FileInputStream(file); // 写入流 int len; while ((len=fileInputStream.read(buffer))!=-1){ outputStream.write(buffer); } // 文件传输结束,关闭输出 socket.shutdownOutput(); InputStream inputStream = socket.getInputStream(); byte buffer2[] = new byte[20]; ByteArrayOutputStream msg = new ByteArrayOutputStream(); while ((len=inputStream.read(buffer2))!=-1){ msg.write(buffer2,0,len); } System.out.println(msg); msg.close(); inputStream.close(); fileInputStream.close(); outputStream.close(); socket.close(); } }
Client:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class TestTcpFileTransportServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(4396); Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); byte[] bufferFile = new byte[1024]; int len; File received = new File("test.png"); FileOutputStream output = new FileOutputStream(received); while ((len=inputStream.read(bufferFile))!=-1){ output.write(bufferFile,0,len); } // 接受完毕,告知客户断开连接 OutputStream outputStream = socket.getOutputStream(); outputStream.write("接收成功".getBytes(StandardCharsets.UTF_8)); output.close(); inputStream.close(); socket.close(); serverSocket.close(); } }
UDP 编程
1、类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序。
2、UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证 UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
3、DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号。
4、UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接。如同发快递包裹一样。
UDP网络通信流程
1、DatagramSocket与DatagramPacket
2、建立发送端,接收端
3、建立数据包
4、调用Socket的发送、接收方法
5、关闭Socket
接收方:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class TestUdpGet { public static void main(String[] args) throws IOException { // 开放端口 DatagramSocket socket = new DatagramSocket(2200); while (true) { // 接收数据 byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length); socket.receive(packet);// 阻塞接收 System.out.println(packet.getAddress().getHostAddress()); String msg = new String(packet.getData(), 0, packet.getLength()); if (msg.equals("shutdown")){ System.out.println("Connection has been closed"); socket.close(); return; } System.out.println(msg); } } }
发送方
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.*; import java.nio.charset.StandardCharsets; public class TestUdpSend { public static void main(String[] args) throws IOException, InterruptedException { // 建立一个socket DatagramSocket socket = new DatagramSocket(1111);//Ctrl+Alt+V BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while (true) { String data = reader.readLine(); byte[] msgBytes = data.getBytes(StandardCharsets.UTF_8); InetAddress localhost = InetAddress.getByName("localhost"); DatagramPacket datagramPacket = new DatagramPacket(msgBytes, 0, msgBytes.length, localhost, 2200); socket.send(datagramPacket); if (data.equals("shutdown")){ System.out.println("Connection is closed "); reader.close(); socket.close(); return; } } } }
多线程实现聊天功能
/* 发送消息线程 */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.charset.StandardCharsets; public class MsgSender implements Runnable{ private int destinationPort; private String destinationAddress; DatagramSocket socket = null; BufferedReader reader = null; public MsgSender(int sourcePort, int destinationPort, String destinationAddress) throws SocketException { this.destinationPort = destinationPort; this.destinationAddress = destinationAddress; socket = new DatagramSocket(sourcePort); reader = new BufferedReader(new InputStreamReader(System.in)); } @Override public void run() { while (true){ try { String data = reader.readLine(); byte[] dataByte = data.getBytes(StandardCharsets.UTF_8); DatagramPacket packet = new DatagramPacket(dataByte,0,dataByte.length, new InetSocketAddress(this.destinationAddress,this.destinationPort)); socket.send(packet); if(data.equals("shutdown")){ reader.close(); socket.close(); return; } } catch (IOException e) { e.printStackTrace(); } } } }
/* 消息接收线程 */ import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException; public class MsgReceiver implements Runnable{ private int port; private String msgSeeder; DatagramSocket socket = null; public MsgReceiver(int port, String msgSeeder) throws SocketException { this.port = port; this.msgSeeder = msgSeeder; socket = new DatagramSocket(port); } @Override public void run() { while (true){ try { byte[] msgBuffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(msgBuffer,0,msgBuffer.length); socket.receive(packet); byte[] data = packet.getData(); String msg = new String(data,0, packet.getLength()); if (msg.equals("shutdown")) { socket.close(); return; } System.out.println(msgSeeder+": "+msg); } catch (IOException e) { e.printStackTrace(); } } } }
/*用户1主线程*/ public class TestCli02 { public static void main(String[] args) throws SocketException { new Thread(new MsgSender(1233, 8888,"localhost")).start(); new Thread(new MsgReceiver(9999,"T")).start(); } }
/*用户2 主线程*/ public class TestCli02 { public static void main(String[] args) throws SocketException { new Thread(new MsgSender(1233, 8888,"localhost")).start(); new Thread(new MsgReceiver(9999,"T")).start(); } }
URL 编程
url:统一资源定位符
格式:<协议>://<主机><端口>/<路径>
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class TestUrl { public static void main(String[] args) throws IOException { // 1.资源地址 URL url = new URL("https://m701.music.126.net/20210419223947/bf29e2e59430cbc33e13485d38ac54e0/jdymusic/obj/wo3DlMOGwrbDjj7DisKw/7748121407/a09e/914d/bae7/0d34f4fab6d02c177c9fd38402f127b0.mp3"); // 2.url解析 System.out.println(url.getProtocol()); // 协议 System.out.println(url.getHost()); // 主机 System.out.println(url.getPort()); // 端口 System.out.println(url.getPath()); // System.out.println(url.getFile()); // System.out.println(url.getQuery()); // 参数 System.out.println(url.getAuthority()); // The Authority part of the URL is the host name and the port of the URI System.out.println(url.getContent()); // 内容 // 3.连接资源url HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream stream = urlConnection.getInputStream(); // 4. 文件输出流到 test.mp3 FileOutputStream outputStream = new FileOutputStream("test.mp3"); byte[] bytes = new byte[1024]; int len; while ((len=stream.read(bytes))!=-1){ outputStream.write(bytes,0,len); } // 下载完毕关闭流和url连接 stream.close(); outputStream.close(); urlConnection.disconnect(); } }