在开发网络应用程序时,我们会遇到Socket这个概念。Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。
Socket、TCP和部分IP的功能都是由操作系统提供的,不同的编程语言只是提供了对操作系统调用的简单封装。
为什么要用Socket进行网络通信?因为仅仅通过IP地址进行通信是不够的,同一台计算机同一时间会运行多个应用程序,例如QQ、微信客户端等。当操作系统接收到一个数据包时,如果只有IP地址,就没法判断应该发送给那个应用程序,所以,操作系统抽象出Socket接口,每个应用程序需要各自对应到不同的Socket,数据包才能根据不同的Socket正确的发送到对应的应用程序。
一个Socket就是由IP地址和端口号(0~65535)组成,端口号由操作系统分配,其中,小于1024的端口数语特权端口,需要管理员权限,大于1024的端口可以由任意用户的应用程序打开。
使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器段,它会主动监听某个指定的端口。另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定的端口,如果连接成功,客户端和服务端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
对于服务端来说:它的Socket是指定的IP地址和指定的端口号
对于客户端来说:它的Socket是它所在计算机的IP和一个由操作系统分配的随机端口号。
try (Socket socket = new Socket("127.0.0.1", 8080)) {
try (OutputStream outputStream = socket.getOutputStream();
) {
outputStream.write("Hello, world!\n".getBytes()); // 发送数据
outputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
// 创建一个 ServerSocket
try (ServerSocket serverSocket = new ServerSocket(8080)) {
// 调用 accept(),接收客户端的 Socket
System.out.println("服务器启动成功");
Socket socket = serverSocket.accept();
try (InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))
) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException e) {
e.printStackTrace();
}