基于套接字的Java网络编程
1.Socket
通信
Socket 网络编程简介
- 客户端和服务器端建立连接后,连接两端将会建立一个虚拟“线缆”,在网络编程中称之为Socket(套接字);其后在网络两端传输数据都是通过Socket进行的
- Socket借助
IP
地址和端口号,对应某一台主机中的某一个应用程序 - Socket的主要作用是维护网络连接、在网络双方传输数据
- Socket借助
2.Socket
通信的过程
Socket网络编程核心操作类
Socket类:
-
客户端套接字类。实现客户端向服务器发送数据、接收服务器数据等功能;实现服务器端向客户端发送数据、接收客户端数据等功能
构造方法:
Socket(InetAddress address, int port); Socket(String host, int port);
常用方法:
getInputStream(); // 获得网络输入流 getOutputStream(); // 获得网络输出流 close(); // 关闭Socket连接
-
客户端与服务器端通信时,借助网络输入/输出流进行传输;但是对于客户端和服务器而言,输入流或输出流是相对的
-
客户端Socket应用程序所做的工作主要有:
1.与服务器端建立连接(通过IP和端口号确定主机上的程序)
Socket client = new Socket(“localhost”, 80)
2.向服务器端发送数据,接收服务器端数据
向服务器端发送数据:
os = client.getOutputStream()
接收服务器端数据:is = client.getInputStream()
3.关闭Socket连接:
client.close()
-
客户端Socket应用程序
Socket client = new Socket("127.0.0.1", 8888); // 获得网络输入/输出流 InputStream is = client.getInputStream(); // 获得网络输入流 OutputStream os = client.getOutputStream(); // 获得网络输出流 // 发送数据到server String request = "this is a client request!"; os.write(request.getBytes()); os.flush();// 刷新请求 // 接收响应 byte[] b = new byte[1024]; StringBuffer strb = new StringBuffer(); while (is.read(b) != -1) { strb.append(new String(b)); } System.out.println(strb.toString()); // 关闭连接 is.close(); os.close(); client.close();
ServerSocket
类:
-
服务器端套接字类。监听服务器指定端口,接收客户端连接请求
-
构造方法:
ServerSocket(int port)
-
常用方法:
accept(); // 用于产生“阻塞”,直到接收一个连接,返回客户端Socket对象 close(); // 关闭服务器端Socket监听
-
服务器端所做的主要工作有:
1.监听特定端口
ServerSocket server = new ServerSocket(8888)
2.接收客户端连接
Socket client = server.accept()
3.接收客户端请求,向客户端发送响应
接收客户端请求数据:is = client.getInputStream()
向客户端响应数据:os = client.getOutputStream()
4.关闭连接
关闭客户端:client.close()
关闭服务器端:server.close()
-
服务器端Socket应用程序
server = new ServerSocket(8888); // 接收客户端连接 System.out.println("server listener"); Socket client = server.accept(); // 获得客户端请求 InputStream is = client.getInputStream(); byte[] b = new byte[1024]; is.read(b); System.out.println("Server received:" + new String(b)); // 向客户端发送响应 OutputStream os = client.getOutputStream(); os.write(("this is server return string !").getBytes()); // 关闭网络连接 is.close(); os.close(); client.close(); server.close();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B6jaxQuM-1687141452827)(C:\Users\wuruoheng\Desktop\基于套接字的服务器和客户端交互.png)]
单Socket客户端和单服务器端一次通讯 | 单服务器端接收多次通讯 |
---|---|
1.ServerSocket 建立后,通过accept来等待Client连接 | 1.ServerSocket 建立后,通过accept来等待Client连接 |
2.Client 连接Server 端 | 2.Client 连接Server 端 |
3.Server 端建立inputstream 和outputstream | 3.Server 端建立inputstream 和outputstream |
4.Client 端建立inputstream 和outputstream | 4.Client 端建立inputstream 和outputstream |
5.双方一次通讯 | 5.双方一次通讯 |
6.各自关闭自己的inputstream 和outputstream | 6.Client 关闭,Server端等待下次连接 |
3.Socket
基于TCP协议的网络编程
-
在客户端,可以把处理服务器端响应消息的任务放到一个单独线程中,在主线程中接收用户输入和发送请求消息
-
服务器的作用就是为了服务多个客户端,对于多个客户端并发请求的处理,在网络编程中,采用多线程处理方式解决。每当服务器端接收到客户端请求后,产生一个新的线程处理客户端请求
- 开启线程比较消耗系统资源,所以应用程序中可以开辟的线程个数总是有限的
- 可以结合使用线程池技术,实现服务器端的并发处理请求
单服务器端多线程接收多次通讯
ServerSocket建立后,通过accept来等待Client连接
Client连接Server端
Server开启一个新的线程去处理
Server端建立inputstream和outputstream
Client端建立inputstream和outputstream
Client关闭
Server端等待下次连接
4.Socket
基于UDP
协议的网络编程
建立网络连接时,有两种传输层协议(TCP传输协议和UDP传输协议)
UDP传输协议:一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务
比较项 | TCP 协议 | UDP 协议 |
---|---|---|
连接性 | 网络双方需要建立连接 | 不需要网络双方建立连接 |
安全性 | 完全可靠,确保数据可达 | 不可靠,数据可能传输失败 |
传输速度 | 无限制 | 数据包大小不越过64K |
传输方式 | 在连接的虚拟线路上传输 | 在网络中传输 |
UDP
网络编程核心类
-
UDP
传输协议通过数据包方式向服务器发送数据,那么在数据包中肯定需要包含服务器的IP信息、端口信息等内容。因此,UDP
网络编程必须提供以下对象来完成不同的任务:- 网络两端接收消息或发送消息的对象(监听本机端口、发送消息、接收消息)
- 数据包对象(包含目的地
IP
和端口信息、数据报文信息)
-
DatagramSocket
类:客户端/服务器端网络Socket端口对象- 构造方法:
DatagramSocket(); // 创建一个空的Socket对象 DatagramSocket(int port); // 创建指定监听端口的Socket对象
- 常用方法:
void send(DatagramPacket p); // 发送数据报文 void receive(DatagramPacket p); // 接收数据报文
- 构造方法:
-
DatagramPacket
类:数据报文对象- 构造方法:
DatagramPacket(byte[] buf, int len);
// 用空数组创建对象,用来接收数据
DatagramPacket(byte[] buf, int offset, int len);
// 接收数据的特定部分
DatagramPacket(byte[] buf, int len, InetAddress addr, int port);
// 包含数据的数组创建对象,用来发送数据,同时指明数据目的地和目标端口号
DatagramPacket(byte[] buf, int offset, int len, InetAddress addr, int port);
// 发送数据的指定部分`
- 构造方法:
UDP网络编程实例
客户端程序 | 服务器程序 |
---|---|
创建DatagramSocket 对象 | 创建DatagramSocket 对象,监听特定端口创建 |
封装请求数据,创建DatagramPacket 对象 | 创建DatagramPacket 对象(空缓冲区) |
发送请求 | 接收客户端请求封装服务器响应数据,创建DatagramPacket 对象 |
创建DatagramPacket 对象发送服务器响应给指定客户端 |
服务器端:
// 创建DatagramSocket对象,监听特定端口
DatagramSocket server = new DatagramSocket(8888);
// 准备空缓冲区
byte[] buf = new byte[1024];
// 循环等待客户端请求
while (true) {
// 创建DatagramPacket对象
DatagramPacket request = new DatagramPacket(buf, buf.length);
// 接收客户端请求
server.receive(request);
// 准备服务器端响应数据包
byte[] resBuf = "from server: ".getBytes();
DatagramPacket response = new DatagramPacket(
resBuf, resBuf.length, request.getAddress(), request.getPort());
// 发送服务器响应
server.send(response);