Java网络编程简单了解
程序员文章站
2022-07-10 19:42:34
这篇文章将简单入手Java的HttpURLConnection,InetAddress,Socket以及ServerSocketHttpURLConnectionHttpURLConnection 位于 java.net 包中,提供了用来连接请求URL的方法import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;....
这篇文章将简单了解Java的HttpURLConnection,InetAddress,Socket以及ServerSocket
HttpURLConnection
HttpURLConnection 位于
java.net
包中,提供了用来URL连接请求的方法
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author AhogeK ahogek@gmail.com
* @date 2021-02-23 16:40
*/
public class HttpUrlConnectionTest {
public static void main(String[] args) {
try {
// 设置一个URL
URL csdn = new URL("https://www.csdn.net/");
// 通过设置的URL创建一个HttpURLConnection连接,URL.openConnection()返回的是URLConnection, HttpURLConnection是其子类
HttpURLConnection httpUrlConnection = (HttpURLConnection) csdn.openConnection();
// 设置请求的方法,类似还有很多请求配置常用的连接超时等
httpUrlConnection.setRequestMethod("GET");
httpUrlConnection.setConnectTimeout(1000);
// 通过BufferedReader接收响应
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream()));
// 输出响应内容
bufferedReader.lines().forEach(System.out::println);
// 关闭连接与流
httpUrlConnection.disconnect();
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
请求成功就能拿到CSDN的首页页面的HTML
InetAddress
该类同样在
java.net
包中,用于表示IP地址,例如在socket编程中会用到该类
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
/**
* @author AhogeK ahogek@gmail.com
* @date 2021-02-23 19:51
*/
public class InetAddressTest {
public static void main(String[] args) throws UnknownHostException {
/*
* InetAddress没有公共构造方法,我们可以通过静态方法来构建
* getByName() 方法可以通过给定主机域名来获取 InetAddress实例
*/
InetAddress google = InetAddress.getByName("www.google.com");
// 通过 toString() 可以以 域名/IP 的格式输出
System.out.println(google.toString());
// getHostAddress() 用来获取InetAddress对象的IP地址
System.out.println(google.getHostAddress());
// getHostName() 即获取其域名
System.out.println(google.getHostName());
// 同理也可以反向生成实例对象
System.out.println(InetAddress.getByAddress("www.google.com",new byte[] {(byte) 172, (byte) 217, 31, (byte) 132}).toString());
// 输出 本地主机 地址 pc名/本地ip
System.out.println(InetAddress.getLocalHost());
// 因为一个域名不一定只映射一个ip,所以 getAllByName 可以获取域名相关连的多个IP
System.out.println(Arrays.toString(InetAddress.getAllByName("www.google.com")));
}
}
输出:
Socket与ServerSocket
Socket
同样位于
java.net
,称之为套接字,是作为两台计算机相连的端点
在接下来要写的小demo中,Socket的主要步骤:
- 建立与服务器的连接
- 使用输出流将数据发送到SockerServer
- 使用输入流读取SocketServer返回的数据
- 关闭连接
ServerSocket
ServerSocket 是服务端套接字,它会等待Socket的接入,然后执行一系列操作再返回
ServerSocket的主要步骤:
- 创建服务器的套接字并将其绑定到特定的接口
- 等待客户端Socket的接入
- 通过接入的Socket获取其输入流读取数据
- 通过接入的Socket获取输出流来写入数据
DEMO
Socket
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.Scanner;
/**
* @author AhogeK ahogek@gmail.com
* @date 2021-02-23 21:01
*/
public class SocketClient {
public static void main(String[] args) throws IOException {
System.out.println("Client start!");
// 创建本地的InetAddress实例 (即用来获取本地服务端IP)
InetAddress localHost = InetAddress.getLocalHost();
// 设置服务端端口
int port = 8080;
// 用于进行客户端输入的操作
Scanner clientScanner = new Scanner(System.in);
// 通过服务器的IP与端口实例化 Socket
Socket socket = new Socket(localHost.getHostAddress(), port);
// 实例化 Socket 的输出流 (第二参数指是否自动flush) 用于向服务端写数据
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
// 实例化 Socket 的输入流 用于读取服务端数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
LocalDateTime localDateTime = LocalDateTime.now();
// 除非输入 “exit” 不然不会关闭可以持续输出
String clientInput;
while (!"exit".equals(clientInput = clientScanner.nextLine())) {
// 客户端输入发送至服务器
writer.println(LocalDateTime.now().toString() + " " + clientInput);
// 输出服务端返回
System.out.println("Server: " + br.readLine());
}
// 关闭 Socket
socket.close();
}
}
ServerSocket
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author AhogeK ahogek@gmail.com
* @date 2021-02-23 21:15
*/
public class ServerSocketTest {
private static final int CORE_POOL_SIZE = 5;
private static final int MAX_POOL_SIZE = 10;
private static final int QUEUE_CAPACITY = 100;
private static final Long KEEP_ALIVE_TIME = 1L;
private final static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(QUEUE_CAPACITY),
new ThreadPoolExecutor.CallerRunsPolicy());
public static void main(String[] args) throws IOException {
System.out.println("Server start!");
// 创建ServerSocket实例
ServerSocket serverSocket = new ServerSocket(8080);
// 使用到了Java8的流操作因此这边需要用到原子类
AtomicBoolean close = new AtomicBoolean(false);
// 利用这条线程来随时关闭服务器
EXECUTOR.execute(() -> {
Scanner scanner = new Scanner(System.in);
while (!"exit".equals(scanner.nextLine())) {
close.set(true);
}
});
while (!close.get()) {
// 支持多线程接入Socket
EXECUTOR.execute(() -> {
try {
// 调用 accept() 进行阻塞等待 Socket 接入
Socket socket = serverSocket.accept();
// 接入后获取其输入输出流用于读取写入
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String clientInput;
while ((clientInput = reader.readLine()) != null) {
System.out.println("client: " + clientInput);
// 发回消息给客户端
writer.println("This is Server");
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
}
输出:
上述代码中,ServerSocket 用了阿里规范中推荐的线程池ThreadPoolExecutor
来创建Socket客户端接入的线程
本文地址:https://blog.csdn.net/AhogeK/article/details/113995035