当前位置: 首页 > news >正文

Java:TCP/UDP网络编程

目录

一、前言

1、计算机网络

2、软件结构

3、通信三要素

二、TCP和UDP简单介绍

TCP的三次握手四次挥手

三、TCP网络编程

1、通信流程

2、构造方法

3、基础案例

4、多线程反转案例

5、传输对象

四、UDP网络编程


一、前言

        网络编程的历史可以追溯到20世纪60年代,当时美国国防部高级研究计划局(ARPA)开发了ARPANET,这是互联网的前身。1983年,TCP/IP协议成为ARPANET的标准协议,奠定了现代互联网的基础

        Java的网络编程能力让开发者能够轻松构建客户端和服务器端应用程序,这也是Java在企业级应用中广泛使用的重要原因之一

        

        网络编程作用就是:

        通过编程的方式,使得计算机网络中不同计算机上的应用程序间能够进行数据的传输

1、计算机网络

        最简单的计算机网络:

        两台计算机,连接它们的一条链路

所以计算机网络其实就是

利用通信线路将分散在各个不同地方的、具有独立计算功能的计算机系统和通信设备

按照不同的形式连接起来

以功能完善的网络软件及协议实现资源共享和信息传递的系统

2、软件结构

常见的主要有 C/S B/S

Client / Server :

        客户端 / 服务器 的软件结构

        eg:QQ、微信、等各种软件,只要是我们下载安装的并且和服务器通信的

        都属于 C/S 软件结构

Browser / Server :

        浏览器 / 服务器 的软件结构

        eg:淘宝网、凤凰网、4399等,只要是使用浏览器并且和服务器通信的

        都属于 B/S 软件结构

C/S 和 B/S 对比:

1、CS图形表现及运行速度 > BS

2、CS需要客户端,不能跨平台,不同的操作系统安装包不一样

      BS不需要客服端,只要浏览器即可,BS基于网页语言,与操作系统无关,可以跨平台

3、通信三要素

  • IP地址:

域名:本质上也是ip,只是为了让ip更好记忆

           就是那些 www.xxx.com 网址

  • 端口:

端口号可以用来标识计算机中唯一的那个应用程序

一台计算机中的应用的端口号不能重复

常见端口号:

  •         80端口:前端的静态服务器
  •                 网页服务一般都是80端口
  •                 所以80可以省略
  •         BS架构的默认端口号是80,可以省略
  •         HTTP占用80
  •         FTP占用21 文件传输服务
  •         MySQL用3306
  •         oracle启动后默认占用端口号1521
  •         redis启动后默认占用端口号6379
  •         tomcat启动后默认占用端口号8080

  • 协议:

计算机与计算机通过网络进行数据和信息交换的时候

也要使用同样的“语言”,这个语言被称为网络通讯协议。

通信双方必须同时遵守才能完成数据交换,常见的协议有UDP协议和TCP协议

接下来进入本篇文章重点:

二、TCP和UDP简单介绍

完整的通信过程比较复杂

不过JavaAPI帮我们进行了细节的封装

给我们提供了类和接口直接使用

十分便利

java.net包 对这两种常见的通信协议进行了封装

UDP(不常用)
            传输层协议
            无连接通信协议

            在数据传输时,数据的发送端和接收端不建立连接,也不能保证对方能成功接收
            优点:
                通信效率高
            缺点:
                不能保证数据传输的成功率和完整性

        

TCP(重点)
            传输层协议

            面向连接
            优点:可靠的,无差错的
            缺点:效率低

            针对客户端和服务器,都进行了抽象:
                客户端:java.net.Socket
                服务器:java.net.ServerSocket

TCP的三次握手四次挥手

三次握手(建立连接):

  1. 客户端向服务端发送连接请求
  2. 服务端收到请求后向客户端发送确认
  3. 客户端收到服务端发来的确认信息后,向服务端发送确认收到的信息

四次挥手(断开连接):

  1. 客户端向服务端发送断开请求
  2. 服务端收到断开请求后,向客户端发送确认信息
  3. 服务端处理完剩余数据后,向客户端发送断开请求
  4. 客户端收到服务端的断开请求后,向服务端发送确认断开信息,然后客户端进入TIME_WAIT状态开始等待,等待2MSL时间后确保连接断开(服务端无需等待直接关闭)

三、TCP网络编程

  • java.net.ServerSocket 类表示服务端
  • java.net.Socket 类表示客户端

1、通信流程

服务器端:

  • 创建ServerSocket(需要绑定端口号,方便客户连接)
  • 调用ServerSocket对象的 accept() 方法接收一个客户端请求,得到一个Socket
  • 调用Socket的 getInputStream() getOutputStream() 方法获取和客户端相连的IO流

输入流读取客户端发来的数据

输出流发送数据到客户端

  • 操作完成,关闭资源

客户端:

  • 创建Socket连接服务端(需指定服务器ip地址、端口),找对应的服务器进 行连接
  • 调用Socket的 getInputStream() getOutputStream() 方法获取和服务端相连的 IO流

输入流可以读取服务端输出流写出的数据

输出流可以写出数据到服务端的输入流

  • 操作完成,关闭资源

整个过程中

服务器不能主动连接客户端

必须等客户端先发起连接

2、构造方法

Socket socket2 = new Socket(InetAddress.getByName("www.baidu.com"), 80);Socket socket = new Socket("www.baidu.com", 80);

3、基础案例

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;public class TestSocket {public static void main(String[] args) throws IOException {String ip = "127.0.0.1";int port = 8888;Socket socket = new Socket(ip, port);System.out.println("成功连接:" + socket);InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();//传输数据给服务器os.write("hello server,我是客户端".getBytes());// 刷新缓冲区os.flush();byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println("服务器说:" + new String(bytes, 0, len));os.close();is.close();socket.close();}
}import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TestServerSocket {public static void main(String[] args) throws IOException {int port = 8888;ServerSocket server = new ServerSocket(port);System.out.println("服务器启动成功,等待客户端连接,端口:" + port);System.out.println("server:" + server);// 等待客户端连接,这里终端会阻塞Socket socket = server.accept();System.out.println("socket:" + socket);InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println("客户端说:" + new String(bytes, 0, len));os.write("hello client,我是服务器".getBytes());os.flush();os.close();is.close();socket.close();server.close();}
}

4、多线程反转案例

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class MyServerSocket {public static void main(String[] args) {int port = 8989;try {ServerSocket server = new ServerSocket(port);while(true){Socket socket  = server.accept();Thread t = new Thread(new Runnable() {public void run() {try {InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();byte[] buffer = new byte[1024];int len;while((len = is.read(buffer)) != -1){String msg = new String(buffer, 0, len);System.out.println("客户端说:" + msg);if(msg.equals("quit")){break;}// 反转字符串String reverse = new StringBuffer(msg).reverse().toString();os.write(reverse.getBytes());os.flush();}socket.close();} catch (Exception e) {e.printStackTrace();}}});t.start();}} catch (Exception e) {e.printStackTrace();}}
}import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;public class MySocket {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 8989);Scanner sc = new Scanner(System.in);OutputStream os = socket.getOutputStream();InputStream is = socket.getInputStream();System.out.println("请输入聊天信息,输入quit退出:");while (true) {String str = sc.nextLine();if(str.equals("quit")){os.write(str.getBytes());os.flush();break;}os.write(str.getBytes());os.flush();byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println("反转后的信息:" + new String(bytes, 0, len));}is.close();os.close();socket.close();} catch (Exception e) {e.printStackTrace();}}
}

5、传输对象

基础类:

import java.io.Serializable;public class Teacher implements Serializable{private String name;private int age;private double salary;public Teacher(String name, int age, double salary) {this.name = name;this.age = age;this.salary = salary;}public String getName() {return name;}public int getAge() {return age;}public double getSalary() {return salary;}@Overridepublic String toString() {return "Teacher [name=" + name + ", age=" + age + ", salary=" + salary + "]";}
}

客户端:

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;public class MySocket {public static void main(String[] args) {try {Socket socket = new Socket("127.0.0.1", 8002);Scanner sc = new Scanner(System.in);ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());ObjectInputStream is = new ObjectInputStream(socket.getInputStream());System.out.println("请输入老师信息(格式:姓名-年龄-工资),输入quit结束:");while(true){String msg = sc.next();if(msg.equals("quit")){os.writeObject(null);os.flush();break;}String[] parts = msg.split("-");if(parts.length == 3){Teacher t = new Teacher(parts[0],Integer.parseInt(parts[1]), Double.parseDouble(parts[2]));os.writeObject(t);os.flush();}else{System.out.println("输入格式错误");}}String response = (String) is.readObject();System.out.println("服务端回复:" + response);os.close();is.close();socket.close();} catch (Exception e) {e.printStackTrace();}}
}

服务端:

import java.io.FileWriter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;public class MyServerSocket {public static void main(String[] args) {int port = 8002;try {ServerSocket server = new ServerSocket(port);Socket socket = server.accept();ObjectInputStream is = new ObjectInputStream(socket.getInputStream());ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());List<Teacher> teachers = new ArrayList<>();Teacher t;while((t = (Teacher)is.readObject()) != null){teachers.add(t);}Writer writer = new FileWriter("day30/homework/T1/teacher.txt");for(Teacher teacher : teachers){writer.write(teacher.toString());writer.write("\n");}os.writeObject("ok");writer.flush();writer.close();os.close();is.close();socket.close();server.close();} catch (Exception e) {e.printStackTrace();}}
}

四、UDP网络编程

java.net.DatagramSocket java.net.DatagramPacket

是UDP编程中使用到的两个类,客户端和服务器端都使用这两个类

  • java.net.DatagramSocket 负责接收和发送数据
  • java.net.DatagramPacket 负责封装要发送的数据和接收到的数据

简单写一下了解即可:

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;public class TestSocket {public static void main(String[] args) {String ip = "127.0.0.1";int port = 8888;DatagramSocket socket = null;DatagramPacket packet = null;try {socket = new DatagramSocket();byte[] buff = "hello server".getBytes();packet = new DatagramPacket(buff,0,buff.length,InetAddress.getByName(ip),port);socket.send(packet);System.out.println("客户端发送成功");} catch (Exception e) {e.printStackTrace();}finally{if(socket != null){socket.close();}}}
}import java.net.DatagramPacket;
import java.net.DatagramSocket;public class TestServerSocket {public static void main(String[] args) {byte[] buff = new byte[1024];int port = 8888;DatagramSocket socket = null;DatagramPacket packet = null;try {socket = new DatagramSocket(port);packet = new DatagramPacket(buff, 0 , buff.length);socket.receive(packet);System.out.println("客户端说:" + new String(buff, 0, packet.getLength()));} catch (Exception e) {e.printStackTrace();}finally{if(socket != null){socket.close();}}}
}

http://www.dtcms.com/a/354648.html

相关文章:

  • DevOps篇之利用Jenkins实现多K8S集群的版本发布
  • Docker-compose常用命令
  • Helm 在 K8s 中的常见应用场景
  • 【K8s】整体认识K8s之K8s的控制器
  • Node.js + MongoDB 搭建 RESTful API 实战教程
  • 从入门到入土之——奇异值分解(SVD)
  • 重塑可观测性成本:解析Coralogix的智能成本优化之道
  • 深入浅出:贴片式eMMC存储与国产芯(君正/瑞芯微)的协同设计指南
  • GitHub 宕机自救指南:确保开发工作不间断
  • 学习做动画6.瞄准偏移
  • 5.2 I/O软件
  • STL库——list(类函数学习)
  • 搭建私有云3步法:cpolar简化Puter本地云端配置
  • leetcode238:除自身以外的数组的乘积(前缀和思想)
  • Fair Federated Learning with Biased Vision-Language Models
  • 一文读懂:自然语言处理中的语义理解技术
  • C# Deconstruct | 简化元组与对象的数据提取
  • 秋招笔记-8.28
  • 如何获取文件的MD5码
  • 读大语言模型09超级智能
  • 完整代码注释:实现 Qt 的 TCP 客户端,实现和服务器通信
  • 从集线器到路由器:计算机网络演进之路
  • 实现微信小程序的UniApp相机组件:拍照、录像与双指缩放
  • 在Xcode中查看设备日志的完整指南
  • 深度学习篇---VGGNet
  • 【SQL】计算一年内每个月份的周数据
  • 基于大型语言模型的自然语言到 SQL 转换研究综述:我们身处何处,又将前往何方?
  • MyBatis 动态 SQL 精讲:告别硬编码的智能拼接艺术
  • 【Depth与RGB对齐算法(D2C)】
  • PPT处理控件Aspose.Slides教程:在 C# 中将 PPTX 转换为 Markdown