打算将 Socket 编程再复习下,为后续学习 netty 做准备。
知识准备
学习 Socket 编程,一些前置知识必不可少。
OSI 参考模型以及 TCP/IP 协议栈。
网络编程三要素:协议、IP 和端口号。
端口号是正在运行的程序的标识;有效的端口号范围:0 到 65535,其中 0 到 1024 为系统使用或保留。
TCP/IP 是对一组协议的统称,具体每一层都有很多协议。传输层的协议主要关注 TCP 和 UDP。
UDP 的特点是无连接、速度快、不可靠,需要将数据打包,有大小限制。
TCP 的特点是有连接(三次握手、四次挥手),速度相比 UDP 要慢,但要可靠,数据无限制。
Socket 编程,即为网络编程,也称为套接字编程。Socket 是网络上具有唯一标识的 IP 地址和端口号组合在一起构成。Socket 通信的两端都有 Socket,网络通信即为 Socket 间的通信,数据在两个 Socket 间在某种协议下通过 IO 流传输。
API 学习
关于 Java Socket 的源码都在 net 包下,其中有几个比较重要的类 InetAddress
和 URL
等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| package com.nekolr;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.URL;
public class APIDemo {
public static void main(String[] args) throws Exception {
InetAddress address = InetAddress.getLocalHost(); String hostName = address.getHostName(); String ip = address.getHostAddress();
byte []bytes = address.getAddress(); InetAddress address1 = InetAddress.getByName("avalon"); InetAddress address2 = InetAddress.getByName("192.168.229.1"); InetAddress address3 = InetAddress.getByAddress(bytes);
URL baidu = new URL("http://www.baidu.com");
URL url = new URL(baidu, "/index.html?username=nekolr#test"); url.getProtocol(); url.getHost(); url.getPort(); url.getPath(); url.getFile(); url.getRef(); url.getQuery();
InputStream is = baidu.openStream(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = br.readLine(); while (line!=null){ System.out.println(line); line = br.readLine(); } br.close(); isr.close(); is.close();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(baidu.openStream(), "utf-8"))) { String data; while((data = reader.readLine())!=null){ System.out.println(data); } } catch (IOException e) { e.printStackTrace(); } } }
|
简单 Socket 通信练习
Socket 通信基于 TCP 和 UDP 协议,针对这两个协议有不同的写法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.*;
public class TcpSocket {
static class TcpServer implements Runnable { private int port;
public TcpServer(int port) { this.port = port; }
@Override public void run() { ServerSocket serverSocket = null; BufferedReader reader = null; BufferedWriter writer = null; try { serverSocket = new ServerSocket(this.port); Socket socket = serverSocket.accept(); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("Client Message:" + reader.readLine());
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("Hello Client"); writer.newLine(); writer.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (serverSocket != null) serverSocket.close(); if (reader != null) reader.close(); if (writer != null) writer.close(); } catch (Exception e) { e.printStackTrace(); } } } }
static class TcpClient implements Runnable { private String host; private int port;
public TcpClient(String host, int port) { this.host = host; this.port = port; }
@Override public void run() { Socket socket = null; BufferedWriter writer = null; BufferedReader reader = null; try { socket = new Socket(this.host, this.port); writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("Hello Server"); writer.newLine(); writer.flush(); reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("Server Message:" + reader.readLine()); } catch (Exception e) { e.printStackTrace(); } finally { try { if (socket != null) socket.close(); if (reader != null) reader.close(); if (writer != null) writer.close(); } catch (Exception e) { e.printStackTrace(); } } } }
public static void main(String[] args) { TcpServer tcpServer = new TcpServer(8888); TcpClient tcpClient = new TcpClient("localhost", 8888);
ExecutorService executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), new ThreadPoolExecutor.AbortPolicy());
executor.execute(tcpServer); executor.execute(tcpClient); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.concurrent.*;
public class UdpSocket {
static class UdpServer implements Runnable {
private int clientPort = 10088;
private int serverPort = 10086;
private String host = "localhost";
@Override public void run() { try (DatagramSocket socket = new DatagramSocket(serverPort)) { byte[] bytes = "我是服务端,消息为:i'm server".getBytes(); DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(host), clientPort); socket.send(sendPacket);
bytes = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(bytes, bytes.length); socket.receive(receivePacket);
System.out.println("服务端接收的消息为:" + new String(bytes, "utf-8")); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
static class UdpClient implements Runnable {
private int clientPort = 10088;
private int serverPort = 10086;
private String host = "localhost";
@Override public void run() { try (DatagramSocket socket = new DatagramSocket(clientPort)) { byte[] bytes = "我是客户端,消息为:i'm client".getBytes(); DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(host), serverPort); socket.send(sendPacket);
bytes = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(bytes, bytes.length); socket.receive(receivePacket);
System.out.println("客户端接收的消息为:" + new String(bytes, "utf-8"));
} catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
public static void main(String[] args) { UdpServer udpServer = new UdpServer(); UdpClient udpClient = new UdpClient();
ExecutorService executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), new ThreadPoolExecutor.AbortPolicy());
executor.execute(udpServer); executor.execute(udpClient); } }
|