[JAVAEE] 网络编程

目录

一. 什么是socket套接字

二. socket套接字

2.1 socket套接字根据传输层协议分类

2.2 TCP流套接字 UDP数据报套接字主要特点

三. UDP数据报套接字编程

3.1 DatagramSocket 是UDP socket, 用于发送和接受数据报

3.2 DatagramPacket 是UDP socket 发送和接收的数据报

3.3 练习案例

回显服务器

 回显客户端

四. TCP字节流套接字编程

4.1 ServerSocket 

4.2 Socket

 4.3 练习案例

回显服务器

回显客户端

注意: 


一. 什么是socket套接字

socket套接字是由系统提供用于网络通信的技术, 是基于TCP/IP协议的网络通信的基本操作单元.

基于Socket套接字的网络程序开发就是网络编程.

简单来说, socket就是网络编程套接字, 用来对网卡进行操作.

读网卡就是从网上上收数据, 写网卡就是让网卡发数据.


二. socket套接字

2.1 socket套接字根据传输层协议分类

socket套接字根据传输层协议分类:

1. 字节流套接字 使用传输层TCP协议 Transmission Control Protocol(传输控制协议)

2. 数据报套接字 使用传输层UDP协议  User Datagram Protocol(⽤⼾数据报协议)

2.2 TCP流套接字 UDP数据报套接字主要特点

TCP流套接字: 有连接, 可靠传输, 面向字节流, 全双工

UDP数据报套接字: 无连接, 不可靠传输, 面向数据报, 全双工

1. 有连接 vs 无连接

TCP, 保存通信双方信息 (例如: A与B通信, A与B建立连接)

UDP, 不保存通信双方信息, 但是可以自己实现代码来保存双端信息.

2. 可靠传输 vs 不可靠传输

TCP, 尽可能提高传输成功的概率, 如果出现丢包, 可以感知到.

UDP, 只要把数据发送了, 就不管了.

3. 面向字节流 vs 面向数据报

TCP, 以字节为单位, 读写数据.

UDP, 以数据报为单位, 读写数据.

4. 全双工 vs 半双工

一个通信链路中, 支持双向通信(能读也能写) => TCP/UDP

~, 支持单向通信(要么读, 要么写)

三. UDP数据报套接字编程

3.1 DatagramSocket 是UDP socket, 用于发送和接受数据报

构造方法

成员方法

3.2 DatagramPacket 是UDP socket 发送和接收的数据报

构造方法

成员方法

        

3.3 练习案例

回显服务器

package UDPNet;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class UDPEchoServer {DatagramSocket socket = null;public UDPEchoServer(int serverPort) throws IOException {socket = new DatagramSocket(serverPort); // 指定服务器端口号}public void start() throws IOException {System.out.println("服务器启动");ExecutorService executorService = Executors.newCachedThreadPool();while (true) {executorService.submit(() -> {while (true) { // 客户端发送多次请求// 1. 接收请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket); // 输出型参数String request = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2. 计算响应String response = process(request);// 3. 返回响应DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), 0, response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);// 打印日志System.out.printf("[%s:%d] req:%s res:%s\n", requestPacket.getAddress(), requestPacket.getPort(), request, response);}});}}public String process(String request) {return request;}public static void main(String[] args) throws IOException{UDPEchoServer udpEchoServer = new UDPEchoServer(3306);udpEchoServer.start();}
}

 回显客户端

package UDPNet;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;public class UDPEchoClient {DatagramSocket socket = null;String serverIP;int serverPort;UDPEchoClient(String serverIP, int serverPort) throws IOException {this.serverIP = serverIP;this.serverPort = serverPort;socket = new DatagramSocket();}public void start() throws IOException {Scanner scanner = new Scanner(System.in);while (true) {// 1. 接收用户输入String request = scanner.nextLine();// 2. 将请求发送到客户端DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 0, request.getBytes().length,InetAddress.getByName(serverIP), serverPort);socket.send(requestPacket);// 3. 接收服务器响应并解析DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println("服务器的响应为: " + response);}}public static void main(String[] args) throws IOException {UDPEchoClient udpEchoClient = new UDPEchoClient("127.0.0.1", 3306);udpEchoClient.start();}
}

四. TCP字节流套接字编程

4.1 ServerSocket 

用于创建TCP服务端socket.

构造方法

成员方法

4.2 Socket

用于创建TCP客户端socket, 或者是服务端与客户端建立连接(accept)后返回的服务端socket.

构造方法

成员方法

 

 4.3 练习案例

回显服务器

package TCPNet;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TCPEchoServer {// ServerSocket 服务器使用// socket 服务器和客户端都使用private ServerSocket serverSocket = new ServerSocket();public TCPEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port); // 给服务器分配端口号}public void start() throws IOException {System.out.println("服务器启动!");ExecutorService executors = Executors.newCachedThreadPool();while (true) { // 服务器可能与多个客户端建立连接Socket socket = serverSocket.accept(); // 服务器与客户端建立连接, 返回的是服务端socket// socket.getInetAddress 返回的是与服务器连接的客户端的IP地址.// socket.getPort 返回的是与服务器建立连接的客户端的Port端口号System.out.printf("[%s:%d] 客户端上线!\n", socket.getInetAddress(), socket.getPort());executors.submit(() -> {try {processConnection(socket); // 处理一次连接} catch (IOException e) {throw new RuntimeException(e);}});}}private void processConnection(Socket socket) throws IOException {try (socket; InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scannerNet = new Scanner(inputStream);PrintWriter writerNet = new PrintWriter(outputStream);while (true) { // 一次连接中可能会有多次请求if (!scannerNet.hasNextLine()) { // 从网卡中读不到数据了System.out.printf("[%s:%d] 客户端下线!\n", socket.getInetAddress(), socket.getPort());break;}// 1. 接收请求并解析String request = scannerNet.nextLine();// 2. 计算响应String response = process(request);// 3. 返回响应writerNet.println(response); // 将response放在内存缓冲区中, 并没有让网卡发送数据到客户端// 为什么要放在内存缓冲区中呢?// 因为TCP是面向字节流的, 数据是零散的, 放在缓冲区中等数据达到一定数量再发送.// 平衡了IO速度, 减少了发送次数, 提高了程序效率writerNet.flush(); // 刷新缓冲区, 让网卡发送数据到客户端// 打印日志System.out.printf("[%s:%d] req:%s res:%s\n", socket.getInetAddress(), socket.getPort(), request, response);}} catch (IOException e) {throw new RuntimeException(e);}// 一个客户端断开连接, 关闭客户端// 没有使用finally, 而是使用try with}private String process(String request) {return request;}public static void main(String[] args) throws IOException{TCPEchoServer tcpEchoServer = new TCPEchoServer(9999);tcpEchoServer.start();}
}

回显客户端

package TCPNet;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoClient {Socket socket = null;public TCPEchoClient(String serverIP, int serverPort) throws IOException {socket = new Socket(serverIP, serverPort);}public void start() throws IOException{Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scannerNet = new Scanner(inputStream);PrintWriter writerNet = new PrintWriter(outputStream);while (true) { // 一次连接中多次请求// 1. 用户输入请求String request = scanner.nextLine();// 2. 将请求发送到服务器writerNet.println(request);writerNet.flush();// 3. 接收响应String response = scannerNet.nextLine();// 打印响应System.out.println("服务器的响应为: " + response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException{TCPEchoClient tcpEchoClient = new TCPEchoClient("127.0.0.1", 9999);tcpEchoClient.start();}
}

注意: 

(1) 问题

如果只是单线程, 则服务器无法连接多个客户端, 这是因为服务端中的scannerNet.hasNextLine()阻塞, 导致不能进入外层循环, 服务器无法与其他客户端建立连接(accept).

(2) 解决

引入多线程和线程池, 把processConnection操作作为一个任务提交到线程池中. 就意味着一个客户端的连接相当于一个任务, 任务之间互不冲突. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/17103.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

SDF,一个从1978年运行至今的公共Unix Shell

关于SDF 最近发现了一个很古老的公共Unix Shell服务器,这个项目从1978年运行至今,如果对操作系统,对Unix感兴趣,可以进去玩一玩体验一下 SDF Public Access UNIX System - Free Shell Account and Shell Access 注册方式 我一…

物联网低功耗广域网LoRa开发(二):LoRa开发环境搭建及驱动移植

一、STM32CubeMX加载固件库 将F0固件库添加进来 二、IAR介绍、安装及快捷操作 (一)IAR介绍 1、简介 C/C编译器和调试器 集成开发环境(IDE) 实时操作系统和中间件 开发套件 硬件仿真器以及状态机建模工具2、IAR与Keil对比 MDK默认只创建工程&#xf…

RK3568平台开发系列讲解(设备树篇)device_node 转换成 platform_device

🚀返回专栏总目录 文章目录 一、DTB转换规则二、转换源码分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍通过设备树 device_node 转换成 platform_device 一、DTB转换规则 device 部分是用 platform_device 结构体来描述硬件资源的, 所以内核最终会…

深入理解 source 和 sh、bash 的区别

1 引言 在日常使用 Linux 的过程中,脚本的执行是不可避免的需求之一,而 source、sh、bash 等命令则是执行脚本的常用方式。尽管这些命令都能运行脚本,但它们之间的执行方式和效果却有着显著的区别。这些区别可能会影响到脚本的环境变量、工作…

基于Java Springboot鲜花商城系统

一、作品包含 源码数据库设计文档PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA 数据库:MySQL8.0 …

413: Quick Sort

解法&#xff1a; #include <bits/stdc.h> using namespace std; const int N1e55; int a[N]; int n;int main(int argc, char** argv) {cin>>n;for (int i0;i<n;i) cin>>a[i];sort(a,an);for (int i0;i<n;i) cout<<a[i]<<" "…

通过轻易云高效实现ERP数据无缝传输

高效集成领星ERP数据至金蝶云星空 领星ERP数据集成到金蝶云星空&#xff1a;发货结算报告对接销售出库单&#xff08;日本站&#xff09; 在企业的日常运营中&#xff0c;数据的高效流动和准确处理至关重要。本文将分享一个实际运行的系统对接集成案例&#xff1a;如何将领星E…

在 WSL2 Ubuntu22.04环境安装 MySQL

一、安装步骤 1.1. 确保/etc/apt/sources.list源配置文件一切正常 sudo nano /etc/apt/sources.list需要包括以下内容 deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted…

通信塔台、网点、线路数据

通信塔台&#xff1a; 数量&#xff1a; 通信电缆&#xff1a; 通信网点&#xff1a;

C#桌面应用制作计算器

C#桌面应用制作简易计算器&#xff0c;可实现数字之间的加减乘除、AC按键清屏、Del按键清除末尾数字、/-按键取数字相反数、%按键使数字缩小100倍、按键显示运算结果等...... 页面实现效果 功能实现 布局 计算器主体使用Panel容器&#xff0c;然后将button控件排列放置Pane…

【C++进阶】C++11 -- 智能指针

【C进阶】C11 -- 智能指针 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;C&#x1f96d; &#x1f33c;文章目录&#x1f33c; 1. 智能指针的使用场景分析 2. RAII和智能指针的设计思路 3. C标准库智能指针的使用 4. 智能指针的原…

web——upload-labs——第一关

今天新开一个upload-labs的靶场&#xff0c;文件上传&#xff0c;加油&#xff01;&#xff01;&#xff01;&#xff01; 先讲讲文件上传 文件上传&#xff1a;在Web开发中&#xff0c;文件上传功能是一个允许用户将文件&#xff08;例如图片、文档&#xff09;上传到服务器…

提升企业库存管理效率:聚水潭与金蝶云星空集成方案

查询聚水潭库存生成金蝶物料盘点作业 在企业的日常运营中&#xff0c;库存管理和物料盘点是至关重要的环节。为了实现高效、准确的数据对接&#xff0c;我们采用了轻易云数据集成平台&#xff0c;将聚水潭的库存数据无缝集成到金蝶云星空系统中。本案例将详细介绍如何通过API接…

MacOS下,如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能

MacOS下&#xff0c;如何在Safari浏览器中打开或关闭页面中的图片文字翻译功能 在Mac上的Safari浏览器中&#xff0c;可以通过实况文本功能来实现图片中的文本翻译。关闭步骤具体步骤如下&#xff1a; 在浏览器地址栏&#xff0c;鼠标右击翻译按钮&#xff0c;然后点击“首选…

使用 PyAnsys 在 Ansys 随机振动分析中检索螺栓连接中的力和应力

介绍 随机振动模拟通常用于评估组件承受运输过程中振动的能力。随机振动分析利用先前模态分析的频率和模式内容对通过功率谱密度 (PSD) 负载定义的频谱和功率内容进行线性叠加。在大多数装配模型中&#xff0c;螺栓连接&#xff08;由求解器变为 BEAM188 元素&#xff09;通常…

使用Axios函数库进行网络请求的使用指南

目录 前言1. 什么是Axios2. Axios的引入方式2.1 通过CDN直接引入2.2 在模块化项目中引入 3. 使用Axios发送请求3.1 GET请求3.2 POST请求 4. Axios请求方式别名5. 使用Axios创建实例5.1 创建Axios实例5.2 使用实例发送请求 6. 使用async/await简化异步请求6.1 获取所有文章数据6…

让你的 环境变量 更合理

PATH PATH 环境变量由 shell 或 libc 读取来查找并执行程序&#xff0c;这就是当在终端中键入 ls 时 shell 可以找到 /bin/ls 的方式。 在基于 Debian 的桌面系统上&#xff0c;默认 PATH 变量如下所示&#xff1a; PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sb…

vue3中将在线url地址转为图片显示方法教程

vue3中将在线url地址转为图片显示方法教程 转化后&#xff1a; 原来&#xff1a; 代码&#xff1a; <el-table-column label"制单人" align"center"><template #default"scope"><imgv-if"scope.row.maker":src"s…

idea项目运行时 java: 错误: 不支持发行版本 21

java项目运行时&#xff0c;同样的项目别的都是正常运行&#xff0c;单个这个项目一直报 java: 错误: 不支持发行版本 21&#xff0c; 报错的解释 这个错误表明你正在尝试使用Java编译器编译一个类&#xff0c;但是编译器遇到了一个它不支持的版本号&#xff0c;在这个上下文…

Unity图形学之Blend指令

1.渲染流程&#xff1a;Blend 决定了要渲染的像素和Gbuffer里像素到底怎么取舍 2.Blend 公式&#xff1a; 3.factor可以取值的内容有&#xff1a; One 1 Zero :0 SrcColor : 要渲染的像素 SrcAlpha : 要渲染像素的 a 通道。 DstColor &#xff1a; 已经渲染在gbuffer…