使用 Java 进行网络编程时,由虚拟机实现了底层复杂的网络协议,Java 程序只需要调用 Java 标准库提供的接口,就可以简单高效地编写网络程序。Java 提供的这些标准库存在于 java.net 包下。
TCP 编程
Socket 是一个抽象概念,一个应用程序通过一个 Socket 来建立一个远程连接,而 Socket 内部通过 TCP/IP 协议把数据传输到网络。Socket、TCP 和部分 IP 的功能都是由操作系统提供的,不同的编程语言只是提供了对操作系统调用的简单的封装。
服务端
public class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
OutputStream output = null;
try {
serverSocket = new ServerSocket(8888);
System.out.println("Server is running...");
// 没连接就会阻塞
socket = serverSocket.accept();
output = socket.getOutputStream();
output.write("您好,欢迎访问服务端!".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally { //由下向上,依次关闭
if(output != null ){
try {
output.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();
}
}
}
}
}
结果:Server is running…
客户端
public class Client {
public static void main(String[] args) {
Socket socket = null;
InputStream input = null;
try {
InetAddress addressIP = InetAddress.getByName("127.0.0.1");
int port = 8888;
socket = new Socket(addressIP, port); //尝试建立连接
input = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = input.read(bytes)) != -1) {
sb.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(input != null ){
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null ){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
结果:您好,欢迎访问服务端!
UDP 编程
UDP编程就简单得多,因为UDP没有创建连接,数据包也是一次收发一个,所以没有流的概念。
服务端
public class Server {
public static void main(String[] args) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket(6666); // 监听指定端口
for (;;) {
// 数据缓冲区:
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet); // 收取一个UDP数据包
String s = new String(packet.getData(), packet.getOffset(), packet.getLength(), StandardCharsets.UTF_8);
System.out.println(s);
// 发送数据:
byte[] data = "请求已收到!".getBytes(StandardCharsets.UTF_8);
packet.setData(data);
ds.send(packet);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
ds.close();
}
}
}
结果:你好,我发了个包!
客户端
public class Client {
public static void main(String[] args) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
ds.setSoTimeout(1000);
ds.connect(InetAddress.getByName("localhost"), 6666);
// 发送:
byte[] data = "你好,我发了个包!".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length);
ds.send(packet);
// 接收:
byte[] buffer = new byte[1024];
packet = new DatagramPacket(buffer, buffer.length);
ds.receive(packet);
String resp = new String(packet.getData(), packet.getOffset(), packet.getLength());
System.out.println(resp);
ds.disconnect();
} catch (Exception e) {
e.printStackTrace();
} finally {
ds.close();
}
}
}
结果:请求已收到!
HTTP 编程
HTTP 是 HyperText Transfer Protocol 的缩写,翻译为超文本传输协议,它是基于 TCP 协议之上的一种请求-响应协议。HTTP 请求的格式是固定的,它由 HTTP Header 和 HTTP Body 两部分构成。
服务端
服务器端的 HTTP 编程本质上就是编写 Web 服务器,这是一个非常复杂的体系,也是 JavaEE 开发的核心内容,本次就不实现了。
客户端
浏览器也是一种 HTTP 客户端,客户端的 HTTP 编程,它的行为本质上和浏览器是一样的,即发送一个 HTTP 请求,接收服务器响应后,获得响应内容。
public class Client {
public static void main(String[] args) throws IOException {
URL url = new URL("https://www.baidu.com/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setUseCaches(false);
conn.setConnectTimeout(5000); // 请求超时5秒
// 设置HTTP头:
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 11; Windows NT 5.1)");
// 连接并发送HTTP请求:
conn.connect();
// 判断HTTP响应是否200:
if (conn.getResponseCode() != 200) {
throw new RuntimeException("bad response");
}
// 获取所有响应Header:
Map<String, List<String>> map = conn.getHeaderFields();
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
// 获取响应内容:
InputStream input = conn.getInputStream();
}
}
从 Java 11 开始,引入了新的 HttpClient,它使用链式调用的 API,能大大简化 HTTP 的处理。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/java/280328.html