一、Socket概述
Socket(套接字)是计算机网络编程中用于实现网络通信的一种机制。它提供了一种编程接口,允许应用程序通过网络进行数据传输,实现不同主机之间的通信。
Socket可以看作是一种抽象的概念,用于描述网络通信的端点。它包含了通信所需的各种参数和状态信息,以便应用程序能够通过它进行数据的发送和接收。
Socket的主要特点包括以下几个方面:
- 通信协议:Socket可以基于不同的通信协议进行数据传输,例如TCP/IP、UDP等。
- 通信模型:Socket可以支持不同的通信模型,如面向连接的流式Socket(如TCP)和无连接的数据报式Socket(如UDP)。
- 客户端-服务器模型:Socket通常用于实现客户端-服务器模型,其中客户端应用程序通过Socket与服务器进行通信。
- 端口号:Socket通过端口号来标识应用程序的通信端口,以便不同的应用程序能够同时在同一台主机上进行网络通信。
- API接口:Socket提供了一组API接口,供应用程序进行Socket编程,包括建立连接、发送数据、接收数据、关闭连接等操作。
Socket编程可以在不同的编程语言中进行,如C、C++、Java、Python等,通过调用相应的Socket API来实现网络通信功能。在Socket编程中,通常涉及以下几个步骤:
- 创建Socket:使用Socket API创建一个Socket对象,指定协议类型和通信模式。
- 绑定端口:将Socket绑定到本地的IP地址和端口号上。
- 监听连接请求(仅服务器端):对于服务器端,调用Socket API监听来自客户端的连接请求。
- 建立连接(仅客户端):对于客户端,调用Socket API与服务器端建立连接。
- 数据传输:通过Socket发送和接收数据。
- 关闭连接:在通信结束后,关闭Socket连接。
Socket编程可以用于各种网络应用,如Web服务器、邮件服务器、聊天应用、游戏等。它为应用程序提供了灵活、可靠和高效的网络通信方式。
二、Java实现socket通信
1. 使用TCP连接
使用TCP通信,它使用java.net.Socket
创建了一个Socket
对象。Socket
类通常用于TCP通信。
(1)服务端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
// 创建ServerSocket对象,指定监听的端口号
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("等待客户端连接...");
// 监听客户端的连接请求
Socket clientSocket = serverSocket.accept();
System.out.println("客户端已连接");
// 获取输入流和输出流 输入流和输出流是通过socket对象来进行数据传输的。
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
String message;
while (true) {
// 读取客户端发送的信息
message = in.readLine();
if (message.equalsIgnoreCase("exit")) {
// 如果接收到终止标志,退出循环
break;
}
System.out.println("收到客户端消息:" + message);
// 发送响应给客户端
out.println("已收到你的消息:" + message);
}
// 关闭连接
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
// 创建Socket对象,指定服务端的IP地址和端口号
Socket socket = new Socket("127.0.0.1", 12345);
// 获取输入流和输出流 输入流和输出流是通过socket对象来进行数据传输的。
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// 从控制台读取用户输入
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String message;
while (true) {
System.out.println("请输入要发送的信息(输入 'exit' 退出):");
message = reader.readLine();
if (message.equalsIgnoreCase("exit")) {
// 如果用户输入 'exit',发送终止标志给服务端并退出循环
out.println("exit");
break;
}
// 将用户输入的信息发送给服务端
out.println(message);
// 接收服务端的响应并打印
String response = in.readLine();
System.out.println("服务端响应:" + response);
}
// 关闭连接
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果:
2. 使用UDP连接
使用UDP通信,使用java.net.DatagramSocket
创建了一个DatagramSocket
对象。DatagramSocket
类通常用于UDP通信。
(1)服务端
package socket.UDP;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
public class UDPClient {
public static void main(String[] args) {
try {
// 创建DatagramSocket对象
DatagramSocket socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
int serverPort = 12345;
// 从控制台读取用户输入
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String message;
while (true) {
System.out.println("请输入要发送的信息(输入 'exit' 退出):");
message = reader.readLine();
if (message.equalsIgnoreCase("exit")) {
// 如果用户输入 'exit',退出循环
break;
}
byte[] sendData = message.getBytes();
// 创建发送数据的DatagramPacket对象
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverAddress, serverPort);
// 发送数据
socket.send(sendPacket);
byte[] receiveData = new byte[1024];
// 创建接收数据的DatagramPacket对象
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
// 接收服务端的响应
socket.receive(receivePacket);
// 将接收到的数据转换为字符串并打印
String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("服务端响应:" + response);
}
// 关闭Socket连接
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)客户端
package socket.UDP;
import java.io.IOException;
import java.net.*;
public class UDPServer {
public static void main(String[] args) {
try {
// 创建DatagramSocket对象,并指定监听的端口号
DatagramSocket socket = new DatagramSocket(12345);
System.out.println("等待客户端连接...");
byte[] receiveData = new byte[1024];
while (true) {
// 创建接收数据的DatagramPacket对象
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
// 接收客户端发送的数据
socket.receive(receivePacket);
// 获取客户端的IP地址和端口号
InetAddress clientAddress = receivePacket.getAddress();
int clientPort = receivePacket.getPort();
// 将接收到的数据转换为字符串
String message = new String(receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("收到客户端消息:" + message);
if (message.equalsIgnoreCase("exit")) {
// 如果接收到终止标志,退出循环
break;
}
// 构造发送数据的字节数组
String response = "已收到你的消息:" + message;
byte[] sendData = response.getBytes();
// 创建发送数据的DatagramPacket对象
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, clientAddress, clientPort);
// 发送响应给客户端
socket.send(sendPacket);
}
// 关闭Socket连接
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果: