1.说明
Socket(套接字)是计算机网络编程中用于实现网络通信的一种编程接口或抽象概念。
它提供了一种标准的接口,使应用程序能够通过网络与其他计算机进行通信。
Socket可以看作是应用程序与网络之间的一个通信端点,类似于电话中的插座。
通过Socket,应用程序可以创建、连接、发送和接收数据,以实现网络通信。
Socket通常使用TCP/IP协议栈作为底层网络协议,
但也可以与其他协议一起使用,
如UDP(User Datagram Protocol)和ICMP(Internet Control Message Protocol)等。
Java中基于TCP协议实现网络通信的类
- 客户端的Socket类
- 服务器端的ServerSocket类
服务端和客户端使用Socket通信的步骤:
- 创建ServerSocket和Socket
- 打开连接到Socket的输入/输出流
- 按照协议对Socket进行读/写操作
- 关闭输入输出流、关闭Socket
2.服务端编程
服务端使用ServerSocket编程步骤:
- 创建ServerSocket对象,绑定监听端口
- 通过accept()方法监听客户端请求
- 连接建立后,通过输入流读取客户端发送的请求信息
- 通过输出流向客户端发送乡音信息
- 关闭相关资源
package edu.java.net.socket.tcp;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;/*** TCP Socket 套接字服务端*/
public class ServerSocketDemo {public static void main(String[] args) throws Exception {// simpleServer();concurrentServer();}/*** 单线程服务端,只能接收一个客户端的请求,并且会话结束后服务端自动停止*/public static void simpleServer() throws IOException {// 基于TCP协议的Socket通信,实现用户登录,服务端// 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口// 1024-65535的某个端口ServerSocket serverSocket = new ServerSocket(10086);System.out.println("服务端已经启动,等待客户端的连接...");// 2.调用accept()方法开始监听,等待客户端的连接// 进程阻塞直到接收到客户端请求Socket socket = serverSocket.accept();// 3.获取输出流,响应客户端的请求OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);pw.write("欢迎您访问服务端!" + System.lineSeparator());pw.flush();// 4.获取输入流,并读取客户端信息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);pw.write("服务端收到:" + info + System.lineSeparator());}pw.flush();// 关闭输入流socket.shutdownInput();// 5.关闭资源pw.close();os.close();br.close();isr.close();is.close();socket.close();serverSocket.close();}
}
3.客户端编程
客户端使用Socket编程步骤:
- 创建Socket对象,指明需要连接的服务器的地址和端口号
- 连接建立后,通过输出流想服务器端发送请求信息
- 通过输入流获取服务器响应的信息
- 关闭响应资源
package edu.java.net.socket.tcp;import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;/*** TCP Socket 套接字客户端**/
public class ClientSocketDemo {public static void main(String[] args) throws Exception {// 1.创建客户端Socket,指定服务器地址和端口Socket socket = new Socket("localhost", 10086);// 2.获取输出流,向服务器端发送信息OutputStream os = socket.getOutputStream();// 字节输出流PrintWriter pw = new PrintWriter(os);// 将输出流包装成打印流// 注意结尾的换行,提示服务端一行结束pw.write("用户名:admin" + System.lineSeparator());pw.write("密码:123456" + System.lineSeparator());pw.flush();socket.shutdownOutput();// 3.获取输入流,并读取服务器端的响应信息InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String info = null;while ((info = br.readLine()) != null) {System.out.println("客户端收到消息:" + info);}// 4.关闭资源br.close();is.close();pw.close();os.close();socket.close();}
}
4.服务端多线程编程
实际场景中,一个服务端往往可以支持多个客户端的连接,为多个客户端提供服务。
实现服务器与多客户端之间的通信步骤:
- 服务器端创建ServerSocket,循环调用accept()等待客户端连接
- 客户端创建一个socket并请求和服务器端连接
- 服务器端接受客户端请求,创建socket与该客户建立专线连接
- 建立连接的两个socket在一个单独的线程上通信
- 服务器端继续等待新的连接
package edu.java.net.socket.tcp;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;/*** TCP Socket 套接字服务端*/
public class ServerSocketDemo {public static void main(String[] args) throws Exception {concurrentServer();}/*** 多线程服务端,能同时接收多个客户端的请求,并且会话结束后关掉对应Socket通道,服务端继续运行*/public static void concurrentServer() {int count = 0;try {@SuppressWarnings("resource")ServerSocket serverSocket = new ServerSocket(10086);while (true) {System.out.println("服务端已经启动,等待客户端的连接...");Socket socket = serverSocket.accept();count++;System.out.println("监听到客户端的连接数量=" + count);// 启动一个线程ServerThread serverThread = new ServerThread(socket);serverThread.start();}} catch (Exception e) {e.printStackTrace();}}}// 服务器多线程处理的实际线程类
class ServerThread extends Thread {private int serverName = this.hashCode();// 和本线程相关的socketprivate Socket socket = null;public ServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {// 1.获取输出流,响应客户端的请求OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);pw.write(serverName + ">欢迎您访问服务端!" + System.lineSeparator());pw.flush();// 2.获取输入流,并读取客户端信息InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));String info = null;while ((info = br.readLine()) != null) {System.out.println(serverName + ">服务端接收到消息:" + info);pw.write("服务端收到:" + info + System.lineSeparator());}pw.flush();socket.shutdownInput();// 3.关闭资源pw.close();os.close();br.close();is.close();socket.close();} catch (IOException e) {e.printStackTrace();}}
}