Skip to content

happyflyer/Java-Socket

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

1. 网络基础知识

Socket = IP 地址 + 端口号

Socket 是网络上运行的程序之间双向通信链路的终结点,是 TCP 和 UDP 的基础。

  • ftp:21
  • telent:23
  • http:80
  • ...

针对网络通信的不同层次, Java 提供的网络功能的四大类:

  • InetAddress:用于标识网络上的硬件资源
  • URL:统一资源定位符,通过 URL 可以直接读取或写入网络上的资源
  • Socket:使用 TCP 协议实现网络通信的 Socket 相关的类
  • Datagram:使用 UDP 协议,数据保存数据报中,通过网络进行通信

2. InetAddress 类

InetAddress address = InetAddress.getLocalHost();
System.out.println(address.getHostName());
System.out.println(address.getHostAddress());
System.out.println(Arrays.toString(address.getAddress()));
System.out.println(address);

3. URL

try {
    URL url = new URL("https://www.baidu.com");
    InputStream is = url.openStream();
    InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
    BufferedReader br = new BufferedReader(isr);
    String data = br.readLine();
    while (data != null) {
        System.out.println(data);
        data = br.readLine();
    }
    br.close();
    isr.close();
    is.close();
} catch (IOException e) {
    e.printStackTrace();
}

4. Socket

TCP 协议(传输控制协议)是面向连接、可靠的、有序的、以字节流发送数据。

Java 中基于 TCP 协议实现网络通信的类

  • 客户端的 Socket
  • 服务端的 ServerSocket

Socket通信模型

Socket 通信实现步骤

  1. 创建 ServerSocketSocket
  2. 打开连接到 Socket 的输入/输出流
  3. 按照协议对 Socket 进行读写操作
  4. 关闭输入/输出流,关闭 Socket

4.1. 基于 TCP 的 Socket 通信

4.1.1. 服务端

  1. 创建 ServerSocket 对象,绑定监听端口
  2. 通过 accept() 方法监听客户端请求
  3. 连接建立后,通过输入流读取客户端发送的请求信息
  4. 通过输出流向客户端发送响应信息
  5. 关闭相应资源
// 1. 创建 ServerSocket 对象,绑定监听端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("***服务器已经启动,开始侦听客户端的连接***");
// 2. 通过 accept() 方法监听客户端请求
Socket socket = serverSocket.accept();
// 3. 连接建立后,通过输入流读取客户端发送的请求信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = null;
while ((info = br.readLine()) != null) {
    System.out.println("我是服务器,客户端说:" + info);
}
socket.shutdownInput(); // 关闭输入流
// 4. 通过输出流向客户端发送响应信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("欢迎你");
pw.flush();
// 5. 关闭相应资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();

4.1.2. 客户端

  1. 创建 Socket 对象,指明需要连接的服务的地址和端口号
  2. 连接建立后,通过输出流向服务发送请求信息
  3. 通过输入流获取服务响应的信息
  4. 关闭相应资源
// 1. 创建 Socket 对象,指明需要连接的服务器的地址和端口号
Socket socket = new Socket("127.0.0.1", 8888);
// 2. 连接建立后,通过输出流向服务器发送请求信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("user:zhangsan;passwd:123456");
pw.flush();
socket.shutdownOutput(); // 关闭输出流
// 3. 通过输入流获取服务器响应的信息
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String resp = null;
while ((resp = br.readLine()) != null) {
    System.out.println("我是客户端,服务器说:" + resp);
}
socket.shutdownInput(); // 关闭输入流
// 4. 关闭相应资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();

4.2. 使用多线程实现服务端与多客户端通信

  1. 服务端创建 ServerSocket ,循环调用 accept() 等待客户端连接
  2. 客户端创建一个 Socket 并请求和服务端连接
  3. 服务端接受客户端请求,创建 Socket 与该客户端建立专线连接
  4. 建立连接的两个 Socket 在一个单独的 x 线程上对话
  5. 服务端继续等待新的连接
// 1. 创建 ServerSocket 对象,绑定监听端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("***服务器已经启动,开始侦听客户端的连接***");
int count = 0;
// 2. 通过 accept() 方法监听客户端请求
Socket socket;
while (true) {
    socket = serverSocket.accept();
    ServerThread thread = new ServerThread(socket);
    thread.setPriority(4);
    thread.start();
    count++;
    System.out.println("客户端的数量为:" + count);
    InetAddress address = socket.getInetAddress();
    System.out.println("当前客户端的地址为:" + address.getHostAddress());
}

5. UDP 编程

UDP 协议(用户数据报协议)是无连接、不可靠的、无序的。

UDP 协议传输速度快。

UDP 协议以数据报作为数据传输的载体。

使用 UDP 协议进行数据传输时,

  • 首先需要将要传输的数据定义成数据报(Datagram)

  • 在数据报中指明数据所要达到的 Socket(主机和端口号)

  • 然后再将数据报发送出去

  • DatagramPacket:数据报包

  • DatagramSocket:进行端到端通信的类

5.1. 基于 UDP 的 Socket 通信

5.1.1. 服务端

  1. 创建 DatagramSocket,指定端口号
  2. 创建 DatagramPacket
  3. 接受客户端发送的数据信息
  4. 读取数据
// 1. 创建 DatagramSocket,指定端口号
DatagramSocket socket = new DatagramSocket(8888);
// 2. 创建 DatagramPacket
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
System.out.println("***服务器已经启动,开始侦听客户端的连接***");
// 3. 接受客户端发送的数据信息
// 此方法在接收到数据之前按一直会保持阻塞
socket.receive(packet);
// 4. 读取数据
String info = new String(data, 0, packet.getLength());
System.out.println("我是服务器,客户端说:" + info);
// 服务器向客户端进行响应
InetAddress address = packet.getAddress();
int port = packet.getPort();
byte[] resp = "你好,这是服务器对客户端的响应".getBytes();
DatagramPacket respPacket = new DatagramPacket(resp, resp.length, address, port);
socket.send(respPacket);
socket.close();

5.1.2. 客户端

  1. 定义发送信息
  2. 创建 DatagramPacket,包含所要发送的信息
  3. 创建 DatagramSocket
  4. 发送数据
// 1. 定义发送信息
InetAddress address = InetAddress.getLocalHost();
int port = 8888;
byte[] data = "user:zhangsan;passwd:888888".getBytes();
// 2. 创建 DatagramPacket,包含所要发送的信息
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
// 3. 创建 DatagramSocket
DatagramSocket socket = new DatagramSocket();
// 4. 发送数据
socket.send(packet);
// 客户端接收服务器端的响应
byte[] resp = new byte[1024];
DatagramPacket respPacket = new DatagramPacket(resp, resp.length);
socket.receive(respPacket);
String info = new String(resp, 0, respPacket.getLength());
System.out.println("我是客户端,服务器响应的信息为:" + info);

6. 相关问题

  1. 线程优先级
  2. 对于同一个 Socket
    • 如果关闭了输出流,则与该输出流关联的 Socket 也会被关闭
    • 所以一般不需要关闭流,直接关闭 Socket 即可
  3. TCP 传输字符串、对象
  4. Socket 传递文件

Releases

No releases published

Packages

No packages published

Languages

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy