Java——网络编程套接字
目录
一、网络编程基础
1.1 为什么需要网络编程?——丰富的网络资源
二、什么是网络编程?
三、网络编程中的基本概念
3.2 请求和响应
3.3 客户端和服务端
常见的客户端服务端模型
四、Socket套接字
五、通信模型
5.1 Java数据报套接字通信模型
5.2 Java流套接字通信模型
Socket编程注意事项
5.3 UDP数据报套接字编程
示例一:
示例二:
一、网络编程基础
1.1 为什么需要网络编程?——丰富的网络资源
与本地打开视频文件类似,只是视频文件这个资源的来源是网络。
所谓的网络资源,其实就是在网络中可以获取的各种数据资源。
二、什么是网络编程?
- 进程A:编程来获取网络资源
- 进程B:编程来提供网络资源
三、网络编程中的基本概念
3.1 发送端和接收端
在一次网络数据传输时:
3.2 请求和响应
- 第一次:请求数据的发送
- 第二次:响应数据的发送。
好比在快餐店点一份炒饭:先要发起请求:点一份炒饭,再有快餐店提供的对应响应:提供一份炒饭
3.3 客户端和服务端
- 客户端获取服务资源
- 客户端保存资源在服务端
好比在银行办事:银行提供存款服务:用户(客户端)保存资源(现金)在银行(服务端)银行提供取款服务:用户(客户端)获取服务端资源(银行替用户保管的现金)
常见的客户端服务端模型
最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:
四、Socket套接字
- 有连接
- 可靠传输
- 面向字节流
- 有接收缓冲区,也有发送缓冲区
- 大小不限
对于字节流来说,可以简单的理解为,传输数据是基于 IO 流,流式数据的特征就是在 IO 流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。
- 无连接
- 不可靠传输
- 面向数据报
- 有接收缓冲区,无发送缓冲区
- 大小受限:一次最多传输64k
对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如 100 个字节,必须一次发送,接收也必须一次接收100 个字节,而不能分 100 次,每次接收 1 个字节。
4.3 原始套接字
五、通信模型
5.1 Java数据报套接字通信模型
5.2 Java流套接字通信模型

Socket编程注意事项

此时需要检查进程B绑定的是哪个端口,再查看该端口被哪个进程占用。以下为通过端口号查进程的方式:
- 在cmd输入 netstat -ano | findstr 端口号 ,则可以显示对应进程的pid。如以下命令显
- 在任务管理器中,通过pid查找进程

解决端口被占用的问题:
- 如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B
- 如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。
5.3 UDP数据报套接字编程
DatagramSocket API
DatagramSocket 方法:

DatagramPacket API

DatagramPacket 方法:

构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创
示例一:
实现一个基于TCP的回显服务
客户端:
mport java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoClient {// 定义一个用于客户端的Socket对象private Socket clientSocket;/*** 初始化客户端的Socket** @param serverIp 服务器IP地址* @param serverPort 服务器的端口号* @throws IOException*/public TCPEchoClient (String serverIp, int serverPort) throws IOException {this.clientSocket = new Socket(serverIp, serverPort);}public void start () throws IOException {System.out.println("客户端已启动...");// 获取Socket中的输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的输入while (true) {System.out.println("->");// 接收用户的输入内容Scanner requestScanner = new Scanner(System.in);String request = requestScanner.nextLine();// 发送用户的请求PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);// 强制刷新缓冲区printWriter.flush();// 接收服务器的响应Scanner responseScanner = new Scanner(inputStream);// 获取响应数据String response = responseScanner.nextLine();// 打印响应内容System.out.println("接收到服务器的响应:" + response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public static void main(String[] args) throws IOException {TCPEchoClient client = new TCPEchoClient("127.0.0.1", 9999);client.start();}
} 服务端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ProtocolException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 基于TCP的服务器程序* @Date 2023-05-23*/
public class TCPEchoServer {// 声明一个用于服务端的Socket对象private ServerSocket server;/*** 通过指定端口号实例化服务** @param port 端口号* @throws IOException*/public TCPEchoServer(int port) throws IOException {if (port < 1025 || port > 65535) {throw new RuntimeException("端口号要在 1025 ~ 65535之间.");}// 实例化ServerSocket并指定端口号this.server = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动成功...");// 创建一个线程池ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 10, 1, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10));// 循环接收客户端的连接while (true) {Socket clientSocket = server.accept();// 每接收到一个新连接请求,就创建一个新的子线程
// Thread thread = new Thread(() -> {
// // 处理Socket中的数据
// try {
// processConnections(clientSocket);
// } catch (IOException e) {
// e.printStackTrace();
// }
// });
// // 启动线程
// thread.start();// 提交任务到线程池中poolExecutor.submit(() -> {try {processConnections(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}// 处理数据private void processConnections(Socket clientSocket) throws IOException {// 打印日志String clientInfo = MessageFormat.format("[{0}:{1}] 客户端已上线", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);// 处理数据之前要获取一下输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的请求while (true) {// 通过Scanner读取用户请求中的数据Scanner requestScanner = new Scanner(inputStream);if (!requestScanner.hasNextLine()) {// 日志clientInfo = MessageFormat.format("[{0}:{1}] 客户端已下线.", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);break;}// 获取真实的用户请求数据String request = requestScanner.nextLine();// 根据请求计算响应String response = process(request);// 把响应写回客户端PrintWriter printWriter = new PrintWriter(outputStream);// 写入输出流printWriter.println(response);// 强制刷新缓冲区printWriter.flush();// 打印日志clientInfo = MessageFormat.format("[{0}:{1}], request: {2}, response: {3}",clientSocket.getInetAddress(), clientSocket.getPort(), request, response);System.out.println(clientInfo);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}private String process(String request) {System.out.println("收到新消息:" + request);Scanner scanner = new Scanner(System.in);String response = scanner.nextLine();return response;}public static void main(String[] args) throws IOException {TCPEchoServer server = new TCPEchoServer(9999);server.start();}
}
示例二:
实现一个基于UDP的回显服务:
客户端:
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** @Date 2023-05-20*/
public class UDPEchoClient {// 定义一个用于客户端的DatagramSocketprivate DatagramSocket client;// 定义服务器的IP地址private String serverIp;// 定义服务器的端口号private int port;private SocketAddress address;/*** 构造方法,指定服务器的Ip地址和端口号** @param serverIp 服务器IP* @param port 端口号*/public UDPEchoClient (String serverIp, int port) throws SocketException {this.client = new DatagramSocket();this.serverIp = serverIp;this.port = port;this.address = new InetSocketAddress(serverIp, port);}public void start () throws IOException {System.out.println("客户端已启动.");// 循环接收用户的输入Scanner scanner = new Scanner(System.in);while (true) {System.out.println("->");// 接收用户输入String request = scanner.next();// 1. 把请求内容包装成DatagramPacketDatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),request.getBytes().length, address);// 2. 发送数据client.send(requestPacket);// 3. 接收响应DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);// 4. 在receive方法中填充响应数据client.receive(responsePacket);// 5. 解析响应数据String response = new String(responsePacket.getData(), 0, responsePacket.getLength(), "UTF-8");// 6. 打印日志System.out.printf("request: %s, response: %s.\n", request, response);}}public static void main(String[] args) throws IOException {UDPEchoClient client = new UDPEchoClient("127.0.0.1", 9999);// 启动服务client.start();}}
服务端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;/*** UDP 回显服务器** @Date 2023-05-20*/
public class UDPEchoServer {// 定义一个用于服务器端的DatagramSocketprivate DatagramSocket server;/*** 构造方法,完成服务器的初始化* @param port 端口号*/public UDPEchoServer (int port) throws Exception {if (port > 65535 || port < 1024) {throw new Exception("端口号必须在1024 ~ 65535之间");}// 初始化服务器端的UDP服务this.server = new DatagramSocket(port);}/*** 对外提供服务*/public void start () throws IOException {System.out.println("服务器已启动....");// 循环接收用户的请求while (true) {// 1. 创建一个用于接收请求数据的DatagramPacketDatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);// 2. 接收请求, 把真实的内容填充到requestPacketserver.receive(requestPacket);// 3. 从requestPacket获取数据String request = new String(requestPacket.getData(), 0, requestPacket.getLength(), "UTF-8");// 4. 根据请求获取响应String response = processor (request);// 5. 把响应封装到DatagramPacketDatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),response.getBytes().length, requestPacket.getSocketAddress());// 6. 发送数据server.send(responsePacket);// 7. 打印日志System.out.printf("[%s:%d] request: %s, response: %s.\n", requestPacket.getAddress().toString(),requestPacket.getPort(), request, response);}}public String processor(String request) {return request;}public static void main(String[] args) throws Exception {// 初始化服务器UDPEchoServer server = new UDPEchoServer(9999);// 启动服务server.start();}}
简单的字典功能
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** @Date 2023-05-20*/
public class UDPDictServer extends UDPEchoServer{private Map<String, String> map = new HashMap<>();/*** 构造方法,完成服务器的初始化** @param port 端口号*/public UDPDictServer(int port) throws Exception {super(port);// 初始化字典内容map.put("dog", "小狗");map.put("cat", "小猫");map.put("pig", "小猪");map.put("tiger", "大老虎");map.put("veryGood", "牛P");}@Overridepublic String processor(String request) {return map.getOrDefault(request, "查无此词");}public static void main(String[] args) throws Exception {UDPDictServer server = new UDPDictServer(9999);server.start();}
} 相关文章:
Java——网络编程套接字
目录 一、网络编程基础 1.1 为什么需要网络编程?——丰富的网络资源 二、什么是网络编程? 三、网络编程中的基本概念 3.2 请求和响应 3.3 客户端和服务端 常见的客户端服务端模型 四、Socket套接字 五、通信模型 5.1 Java数据报套接字通信模型 5.2 Java流…...
160套小程序源码
源码列表如下: AppleMusic (知乎日报) 微信小程序 d artand 今日更新求职招聘类 医药网 口碑外卖点餐 城市天气 外卖小程序 定位天气 家居在线 微信小程序-大好商城,wechat-weapp 微信小程序的掘金信息流 微信跳一跳小游戏源码 微票源码-demo 急救应急处…...
有效项目进度管理的 10 条规则
项目进度管理是项目中比较关键的方面之一,因为它将决定事情的进展方式、进展速度以及是否会取得进展。换句话说,它可以让你较好地控制项目,帮助你预测不可预测的情况,并使所有相关团队能够高效地协同工作。 以下是有效项目进度管…...
javaWebssh服装租赁店信息管理系统台myeclipse开发mysql数据库MVC模式java编程计算机网页设计
一、源码特点 java ssh服装租赁店信息管理系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要 采用B/S模式开发。开发环境为TO…...
概率论:样本与总体分布,Z分数与概率
参考书目:《行为科学统计精要》(第八版)——弗雷德里克J格雷维特 数据及其样本的分布 描述一组数据分布 描述一组样本数据的分布 描述样本数据的均值和整体数据一样,但是样本标准差的公式除以了n-1,这里引入自由度的…...
【JavaSE】Java基础语法(十二):ArrayList
文章目录 1. ArrayList的构造方法和添加方法2. ArrayList类常用方法3. ArrayList存储学生对象并遍历 集合和数组的区别 : 共同点:都是存储数据的容器不同点:数组的容量是固定的,集合的容量是可变的 1. ArrayList的构造方法和添加方法 ArrayL…...
c++—封装:运算符重载、友元
1. 友元 (1)友元函数 ①是一种允许非类成员函数访问类的私有成员的一种机制;可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元; ②友元函数在类作用域外定义,但需要在类体中进行声明&…...
【K8s】安全认证与DashBoard
文章目录 一、概述1、客户端2、认证、鉴权与准入控制 二、认证管理1、认证方式2、HTTPS证书认证 三、授权管理1、授权与RBAC2、Role 与 ClusterRole3、RoleBinding 与 ClusterRoleBinding4、案例:创建一个只能管理dev空间下Pods资源的账号 四、准入控制五、DashBoar…...
SpringMVC第七阶段:SpringMVC的增删改查(01)
SpringMVC的增删改查 1、准备单表的数据库 drop database if exists springmvc;create database springmvc;use springmvc; ##创建图书表 create table t_book(id int(11) primary key auto_increment, ## 主键name varchar(50) not null, ## 书名 author varchar(50) no…...
接口测试-Mock测试方法
一、关于Mock测试 1、什么是Mock测试? Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取的比较复杂的对象(如 JDBC 中的ResultSet 对象&#…...
关于宝塔部署jar包和war包
文章目录 前言一、jar包部署二、war包部署1.maven如果打包不了使用命令打包2.安装Tomcat进行访问是否成功2.进入Tomcat目录进行配置war包 一、项目访问方法 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、jar包部署 1.其实jar包没什么讲的&…...
SpringMVC框架面试专题(初级-中级)-第十节
欢迎大家一起探讨~如果可以帮到大家请为我点赞关注哦~ 截止到本节关于SpringMVC的内容已经更新完毕,后续会更新SpringBoot框架的面试题;大家在背题的时候切记不要死记硬背,需要理解 这是什么?有什么操作&a…...
PCIe TLB事务层详解过程
目录 1.What is TLP 2.PCIe 4种不同的事务 2.1.Memory事务 2.2.IO事务 2.3.Configuration事务 2.4.Message...
RK3588平台开发系列讲解(项目篇)YOLOv5部署测试
平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、YOLOv5环境安装二、YOLOv5简单使用2.1、获取预训练权重文2.2、YOLOv5简单测试2.3、转换为rknn模型2.4、部署到 RK 板卡三、airockchip/yolov5简单测试3.1、转换成rknn模型并部署到板卡沉淀、分享、成长,让自己和他…...
基于变形模板的弱监督体图像分割
文章目录 Weakly Supervised Volumetric Image Segmentation with Deformed Templates摘要本文方法实验结果 Weakly Supervised Volumetric Image Segmentation with Deformed Templates 摘要 背景 有许多方法可以对网络进行弱监督训练来分割2D图像。依赖于对3D图像的2D切片的…...
python实现单例模式及其应用
单例模式是一种常见的设计模式,它保证一个类只能被实例化一次,并提供了一个全局访问点来获取这个唯一的实例。 在 Python 中,可以通过使用装饰器、元类或模块等方式实现单例模式。下面分别介绍这三种方法: 1.使用装饰器实现单例…...
SSM 如何使用 Seata 框架实现分布式事务?
SSM 如何使用 Seata 框架实现分布式事务? 分布式事务是现代分布式系统中必不可少的一部分,而 Seata 框架是一种常用的分布式事务处理方式。在 SSM 框架中,我们可以使用 Seata 框架来管理分布式事务。本文将介绍如何在 SSM 框架中使用 Seata …...
FreeRTOS任务相关API函数
任务创建和删除API函数 xTaskCreate() 创建任务。RAM BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务函数const char* const pcName, //任务名字const uint16_t usStackDepth,//任务堆栈大小void * const …...
VBA之正则表达式(42)-- 提取代码中变量名称
实例需求:待处理代码段如下所示,现在需要提取其中的变量名称。 Public pFactor As Integer Sub TestCode() Dim reg As New RegExp, a As Workbook Dim ms As VBScript_RegExp_55.MatchCollection Dim m As VBScript_RegExp_55.Match Dim i, j Dim x1, y…...
Unity Lightmapping Setting
如下图: Lightmapper: 使用什么硬件或算法渲染 Progressive CPU、Progressive GPU、Enlighten(新的算放目前用的比较少) 此数值会被用于分别乘以Direct Samples,Indirect Samples和Environment Samples这三个数值。这三个数值会被应用于…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
