Java Socket网络编程
一.Socket概述
Java网络编程主要涉及的内容是Socket编程。
Socket(套接字),是网络上两个程序之间实现数据交换的一端,它既可以发送请求,也可以接受请求,一个Socket由一个IP地址和一个端口号唯一确定,利用Socket能比较方便的实现两端(服务端和客户端)的网络通信。
在Java中,有专门的Socket类来处理用户请求和响应,学习使用Socket类方法,就可以实现两台机器之间通信。
Socket通信是有两种方式的:TCP和UDP。
TCP通信:客户端提供了java.net.Socket
类,服务器端提供了java.net.ServerSocket
类。
UDP通信:UDP通信不建立逻辑连接,使用DatagramPacket
类打包数据包,使用DatagramSocket
类发送数据包。
Socket通信模型如下图:
二. TCP通信客户端Socket
Java中专门用来实现Socket客户端的类就叫Socket
,这个类实现了客户端套接字,用于向服务器发出连接请求等。
-
构造方法:
Socket(String host, int port)
:创建一个流套接字并将其连接到指定IP地址的指定端口号。如果host为null,则相当于指定地址为回送地址。
回送地址(来自百度百科):
127.x.x.x是本机的会送地址,即主机IP堆栈内部的IP地址,主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,协议软件立即返回之,不进行任何网络传输。
-
主要方法:
-
InputStream getInputStream()
:返回此套接字的输入流。关闭生成的InputStream也将关闭相关的Socket。
-
OutputStream getOutputStream()
:返回此套接字的输出流。关闭生成的OutputStream也将关闭相关的Socket。
-
void close()
:关闭此套接字
-
三. TCP通信服务器端ServerSocket
Java中专门用来建立Socket服务器的类叫ServerSocket
,这个类实现了服务器套接字,该对象等待通过网络的请求。
-
构造方法:
ServerSocket(int port)
:创建绑定到特定端口的服务器套接字。 -
主要方法:
-
Socket accept()
:监听并接受连接,返回一个新的Socket对象,用于和客户端通信,该方法会一直阻塞直到建立连接。 -
void close()
:关闭此套接字。
-
四.基于TCP的Socket通信
-
步骤分析:
- 服务端先启动,创建ServerSocket对象,等待连接。
- 客户端启动,创建Socket对象,请求连接。
- 服务器端接收请求,调用accept方法,并返回一个Socket对象。
- 客户端的Socket对象获取OutputStream,向服务器端发送数据。
- 服务器端Socket对象获取InputStream,读取客户端的数据。
- 服务器端Socket对象获取OutputStream,向客户端发送数据。
- 客户端的Socket对象获取InputStream,读取服务器的数据。
- 客户端释放资源,断开连接。
-
主要代码
-
服务器端
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class TCPServer { public static void main(String[] args) throws IOException { System.out.println("Server start..."); ServerSocket server = new ServerSocket(1234); while (true) { Socket client = server.accept(); // 字节流转为字符流 InputStreamReader isr = new InputStreamReader(client.getInputStream()); // 字符流转换为缓冲流 BufferedReader br = new BufferedReader(isr); // 读取 String line = null; while ((line = br.readLine()) != null) { System.out.println("接收到客户端信息:" + line); } // 发送信息到客户端 字节流转字符流 OutputStreamWriter out = new OutputStreamWriter(client.getOutputStream()); // 字符流转换为缓冲流 BufferedWriter bw = new BufferedWriter(out); String str = "你好,服务器收到了"; bw.write(str); bw.flush(); // 关闭资源 client.close(); } } }
-
客户端
import java.io.*; import java.net.Socket; public class TCPClient { public static void main(String[] args) throws IOException { System.out.println("Client start..."); Socket client = new Socket("localhost", 1234); OutputStreamWriter osw = new OutputStreamWriter(client.getOutputStream()); BufferedWriter bw = new BufferedWriter(osw); String str = "你好,我是客户端"; bw.write(str); bw.flush(); // 发送一个终结符,告诉服务器,已经发送完毕 client.shutdownOutput(); InputStreamReader isr = new InputStreamReader(client.getInputStream()); BufferedReader br = new BufferedReader(isr); String line = null; while((line = br.readLine()) != null) { System.out.println("接收到服务器消息:" + line); } // 释放资源 client.close(); } }
注意:
在交互时,服务器accept是阻塞的,read也是阻塞的,所以在发送完数据后,需要调用shutdownOutput来告知发送结束,否则会一直阻塞。
-
五.UDP相关类DatagramPacket类和DatagramSocket类
- 数据包类DatagramPacket
- 作用:用来封装发送端或接收端要发送或接收的数据。
- 构造方法
DatagramPacket(byte[] buf, int length)
:构造DatagramPacket,用来接收长度为length的数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port)
:构造数据报包,用来将长度为length的包发送到指定主机上的指定端口号。
- 常用方法
public int getLength()
:获得发送端实际发送的字节数或接收端世界接收的字节数public int getPort()
:获得发送端或接收端端口号
- 发送数据包类DatagramSocket
- 作用:用来发送和接收数据包对象
- 构造方法
DatagramSocket()
:构造数据报套接字并将其绑定到本地主机上任何可用的端口。DatagramSocket(int port)
:创建数据包套接字并将其绑定到本地主机上指定端口。
- 常用方法
public void send(DatagramPacket p)
:从此套接字发送数据报包public void receive(DatagramPacket p)
:从此套接字接收数据报包public void close()
:关闭此数据报套接字
- InetAddress类(无构造方法)
- 作用:代表一个IP地址
- 静态方法
public static InetAddress getLocalHost()
:返回本地主机public static InetAddress getByName()
:在给定主机名的情况下确定主机的 IP 地址。
- 普通方法
public String getHostName()
: 获取此 IP 地址的主机名。public String getHostAddress()
:返回 IP 地址字符串(以文本表现形式)
六.基于UDP的Socket通信
-
步骤分析
- 服务器端先启动,创建DatagramSocket对象,监听端口,用于接收
- 服务器端创建DatagramPacket对象,打包用于接收的数据包
- 服务器阻塞等待接收
- 客户端启动,创建DatagramSocket对象,监听端口,用于接收
- 客户端创建DatagramPacket对象,打包用于发送的数据包
- 客户端发送数据,服务端接收
- 服务端接收数据后,创建DatagramPacket对象,打包用于发送的数据包,发送数据
- 客户端创建DatagramPacket对象,打包用于接收的数据包,阻塞等待接收
- 客户端接收服务端数据,断开连接,释放资源
-
主要代码
-
服务器
import java.io.IOException; import java.net.*; public class UDPServer { public static void main(String[] args) throws IOException { System.out.println("Server Start..."); // 保存接收的数据 byte[] rData = new byte[1024]; // 接收时监听端口8888 DatagramSocket ds = new DatagramSocket(8888); DatagramPacket rdp = new DatagramPacket(rData, rData.length); while (true) { ds.receive(rdp); System.out.println("Receive:" + new String(rData)); // 发送数据 byte[] sData = "你好,我是服务器".getBytes(); DatagramPacket sdp = new DatagramPacket(sData, sData.length, rdp.getAddress(), rdp.getPort()); ds.send(sdp); } } }
-
客户端
import java.io.IOException; import java.net.*; public class UDPClient { public static void main(String[] args) throws IOException { System.out.println("Client login..."); // 构建数据包 byte[] sendData = "Hello,I am Client".getBytes(); InetAddress sendAddress = InetAddress.getLocalHost(); DatagramPacket dp = new DatagramPacket(sendData, sendData.length, sendAddress, 8888); DatagramSocket ds = new DatagramSocket(1234); ds.send(dp); // 创建数据包,接收数据 byte[] receiveData = new byte[1024]; DatagramPacket rdp = new DatagramPacket(receiveData, receiveData.length); ds.receive(rdp); System.out.println("Receive:" + new String(receiveData)); ds.close(); } }
注意:
UDP通信双方,对应端口号一致才可以,比如发送方使用1234端口,接收方需要监听1234端口才可以。
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理