1. InetAddress类
-
InetAddress类表示Internet协议地址,其常用方法有:
// 获取:主机名/主机IP;主机名称可以是机器名称,也可以是IP地址 static InetAddress getByName(String host) // 获取:主机名 String getHostName() // 获取:主机IP String getHostAddress()
-
127.0.0.1是回送地址,即localhost,指本地机,一般用来测试使用。
-
InetAddress使用示例:
import java.net.InetAddress; import java.net.UnknownHostException; public class InetAddressTest { public static void main(String[] args) throws UnknownHostException { InetAddress localhost = InetAddress.getByName("127.0.0.1"); String hostName = localhost.getHostName(); String hostAddress = localhost.getHostAddress(); System.out.println(localhost); System.out.println(hostName); System.out.println(hostAddress); /** * 运行结果: * www.liu2m.com/127.0.0.1 * www.liu2m.com * 127.0.0.1 */ } }
2. UDP通信
-
Java为UDP客户端和服务端提供了DatagramSocket类
-
UDP发送数据的步骤:
- 创建客户端的DatagramSocket对象:new DatagramSocket()
- 将待发送数据打包:new DatagramPacket(byte[] buf, int length, InetAddress address, int port)
- 调用DatagramSocket对象的方法发送数据:send(DatagramPacket p)
- 关闭客户端的DatagramSocket对象:close()
-
UDP接收数据的步骤:
- 创建服务端的DatagramSocket对象:new DatagramSocket(int port)
- 创建一个数据包来存储接收到数据:new DatagramPacket(byte[] buf, int length)
- 调用DatagramSocket对象的方法接收数据:receive(DatagramPacket p)
- 调用DatagramPacket对象的方法解析收到的数据包:getData()、getLength()
- 关闭服务端的DatagramSocket对象:close()
-
UDP发送端程序示例:
import java.io.*; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /** * UDP发送端: */ public class UDPClient { public static void main(String[] args) throws IOException { // 1. 创建客户端的DatagramSocket对象 String host = "127.0.0.1"; int port = 22361; DatagramSocket ds = new DatagramSocket(); // 2. 装饰标准输入流 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; System.out.println("You can exit the program by typing exit"); while ((line = br.readLine()) != null) { // 3. 将待发送数据打包 DatagramPacket dp = new DatagramPacket(line.getBytes(), line.length(), InetAddress.getByName(host), port); // 4. 调用DatagramSocket对象的方法发送数据 ds.send(dp); if ("exit".equals(line)) { break; } } ds.disconnect(); // 5. 释放资源 br.close(); ds.close(); } }
-
UDP接收端程序示例:
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; /** * UDP接收端: */ public class UDPServer { public static void main(String[] args) throws IOException { // 1. 创建服务端的DatagramSocket对象 int port = 22361; DatagramSocket ds = new DatagramSocket(port); byte[] bytes = new byte[1024]; while (true) { // 2. 创建一个数据包来存储接收到数据 DatagramPacket dp = new DatagramPacket(bytes, bytes.length); // 3. 调用DatagramSocket对象的方法接收数据 ds.receive(dp); // 4. 调用DatagramPacket对象的方法解析收到的数据包 String data = new String(dp.getData(), 0, dp.getLength()); System.out.println(data); if ("exit".equals(data)) { break; } } // 5. 释放资源 ds.close(); } }
3. TCP通信
-
Java为TCP客户端提供了Socket类;为TCP服务端提供了ServerSocket类
-
TCP发送数据的步骤:
- 创建客户端的Socket对象并将其连接到服务端:new Socket(String host, int port)
- 获取Socket对象的输出流来写数据:getOutputStream()
- 关闭发送端的Socket对象:close()
-
TCP接收数据的步骤:
- 创建服务端的ServerSocket对象:new ServerSocket(int port)
- 调用ServerSocket对象的方法监听客户端连接并返回Socket:accept()
- 获取Socket对象的输入流来读数据:getInputStream()
- 关闭accept()返回的Socket对象:close()
- 关闭发送端的ServerSocket对象:close()
-
多线程上传文件示例:TCP发送端
import java.io.*; import java.net.Socket; /** * 文件上传:TCP客户端 * 1. 创建Socket对象并将其连接到服务端 * 2. 使用FileInputStream读取待上传文件 * 3. 获取Socket对象的输出流来给服务端写数据 * 4. 禁用Socket对象的输出流;任何先前写入的数据将被发送,随后是TCP的正常连接终止序列 * 由于read方法在检测到流的结尾或抛出异常之前会阻塞,因此客户端应给服务端一个结束标志 * 5. 获取Socket对象的输入流来读服务端返回的数据 * 6. 释放资源 */ public class TCPClient { public static void main(String[] args) throws IOException { // 1. 创建客户端的Socket对象并将其连接到服务端 String host = "127.0.0.1"; int port = 22361; Socket socket = new Socket(host, port); // 2. 使用FileInputStream读取待上传文件 String filePath = "D:\\upload.txt"; FileInputStream fis = new FileInputStream(filePath); // 3. 获取Socket对象的输出流来写数据 OutputStream socketOut = socket.getOutputStream(); byte[] bytes = new byte[1024]; int len = 0; while ((len = fis.read(bytes)) != -1) { // 给服务端写数据 socketOut.write(bytes, 0, len); } // 4. 禁用Socket对象的输出流;任何先前写入的数据将被发送,随后是TCP的正常连接终止序列 socket.shutdownOutput(); // 5. 获取Socket对象的输入流来读服务端返回的数据 InputStream socketIn = socket.getInputStream(); int receiveLen = socketIn.read(bytes); System.out.println(new String(bytes, 0, receiveLen)); // 6. 释放资源 fis.close(); socket.close(); } }
-
多线程上传文件示例:TCP接收端
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 文件上传:TCP服务端 * 1. 创建服务端的ServerSocket对象 * 2. 调用ServerSocket对象的方法监听客户端连接并返回Socket * 线程完成: * 3. 获取Socket对象的输入流来读服务端上传的数据 * 4. 使用FileOutputStream将读取到的文件写到磁盘 * 5. 获取Socket对象的输出流来给服务端写回复 * 6. 释放资源 */ public class TCPServer { public static void main(String[] args) throws IOException { // 1. 创建服务端的ServerSocket对象 int port = 22361; ServerSocket serverSocket = new ServerSocket(port); // 获取线程池 ExecutorService es = Executors.newFixedThreadPool(20); while (true) { // 2. 调用ServerSocket对象的方法监听客户端连接并返回Socket Socket socket = serverSocket.accept(); // 为每一个客户端提交一个线程 es.submit(new UploadThread(socket)); } // es.shutdown(); // serverSocket.close(); } }
-
多线程上传文件示例:上传线程
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /** * 文件上传:上传线程 */ public class UploadThread implements Runnable { private Socket socket = null; public UploadThread(Socket socket) { this.socket = socket; } @Override public void run() { try { // 3. 获取Socket对象的输入流来读服务端上传的数据 InputStream socketIn = socket.getInputStream(); // 4. 使用FileOutputStream将读取到的文件写到磁盘 String uploadPath = "D:\\upload\\upload_" + System.currentTimeMillis() + ".txt"; FileOutputStream fos = new FileOutputStream(uploadPath); byte[] bytes = new byte[1024]; int len = 0; while ((len = socketIn.read(bytes)) != -1) { // 给磁盘写数据 fos.write(bytes, 0, len); } // 5. 获取Socket对象的输出流来给服务端写回复 OutputStream socketOut = socket.getOutputStream(); socketOut.write("Uploaded successfully".getBytes()); // 6. 释放资源 fos.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
4. 模拟B/S服务器
-
服务端:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 模拟B/S服务器: * 1. 创建服务端的ServerSocket对象 * 2. 调用ServerSocket对象的方法监听客户端连接并返回Socket * 线程完成: * 3. 获取Socket对象的输入流 * 装饰Socket对象的输入流 * 读取请求的第一行 * 在请求的第一行中分离出uri * 4. 获取Socket对象的输出流 * 5. 使用FileInputStream来读取浏览器请求的文件 * 向浏览器回复HTTP协议 * 向浏览器回复数据 * 6. 释放资源 */ public class WebServer { public static void main(String[] args) throws IOException { // 1. 创建服务端的ServerSocket对象 int port = 22361; ServerSocket serverSocket = new ServerSocket(port); // 获取线程池 ExecutorService es = Executors.newFixedThreadPool(20); while (true) { // 2. 调用ServerSocket对象的方法监听客户端连接并返回Socket Socket socket = serverSocket.accept(); // 为每一个客户端提交一个线程 es.submit(new ResponseThread(socket)); } // es.shutdown(); // serverSocket.close(); } }
-
响应线程:
import java.io.*; import java.net.Socket; /** * 响应线程 */ public class ResponseThread implements Runnable { private Socket socket; public ResponseThread(Socket socket) { this.socket = socket; } @Override public void run() { try { // 3. 获取Socket对象的输入流 InputStream socketIn = socket.getInputStream(); // 装饰Socket对象的输入流 BufferedReader br = new BufferedReader(new InputStreamReader(socketIn)); // 读取请求的第一行 String s = br.readLine(); // 在请求的第一行中分离出uri String uri = s.split(" +")[1].substring(1); // 4. 获取Socket对象的输出流 OutputStream socketOut = socket.getOutputStream(); System.out.println(uri); // 5. 使用FileInputStream来读取浏览器请求的文件 FileInputStream fis = new FileInputStream(uri); // 向浏览器回复HTTP协议 socketOut.write("HTTP/1.1 200 OK\r\n".getBytes()); socketOut.write("Content-Type:text/html\r\n".getBytes()); socketOut.write("\r\n".getBytes()); byte[] bytes = new byte[1024]; int len = 0; while ((len = fis.read(bytes)) != -1) { // 向浏览器回复数据 socketOut.write(bytes, 0, len); } // 6. 释放资源 br.close(); fis.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
若有错误或补充,欢迎私信