Java之TCP和UDP进行网络编程

目录

一.网络编程

1.1网络编程的作用

1.2网络编程的基本概念   

1.3网络编程的实现

二.UDP网络编程

2.1UDP数据报套的初步了解

2.2Java数据报套接字通信模型 

2.3Java编程实现UDP通信

三.TCP网络编程

 3.1TCP流套接字api

3.2TCP通信代码实现

3.2.1短连接实现代码

3.2.2长连接实现代码

四.总结


🎁个人主页:tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主
🎥 本文由 tq02 原创,首发于 CSDN🙉
🎄 本章讲解内容:TCP和UDP的编程讲解

🎥学习专栏:  C语言         JavaSE       MySQL基础     多线程学习

一.网络编程

1.1网络编程的作用

网络编程:指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)

换句话说:通过网络编程可以进行网络资源的数据传输,例如:腾讯视频观看网络电视

1.2网络编程的基本概念   

在一次网络数据传输时:

        发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。

        接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。

        收发端:发送端和接收端两端,也简称为收发端。

注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念

网络数据传输的请求和响应

一般而言,获取一个网络资源需要涉及到两次的网络数据传输:

  1. 请求数据的发送   -----客户端
  2. 响应数据的发送   ------服务端

注:客户端将资源保存在服务端,例如设置密码,将密码保存在服务端,这样即使换台客户端也能登陆。

1.3网络编程的实现

        网络编程的实现是通过Socket套接字,由系统供用于网络通信的技术,将传输层协议划主要划分为两类:TCP协议和UDP协议。因此TCP和UDP是网络资源数据传输的重要协议

重点:牢记Socket套接字。TCP和UDP都有其api,通过这个可以进行网络编程。

二.UDP网络编程

2.1UDP数据报套的初步了解

        在Java当中,实现UDP协议的通信的类是-----DatagramSocket(Socket对象),DatagramPacket(udp数据报)

  • DatagramPacket(udp数据报):将需要的传输数据写入其中,传输后也需要该类接收数据。
  • DatagramSocket(Socket对象):发送和接收udp数据报。

2.2Java数据报套接字通信模型 

         java中使用UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用

DatagramPacket 作为发送或接收的 UDP 数据报。对于一次发送及接收 UDP 数据报的流程如下:

  1. 发送端:使用DatagramPacket类构造发送的内容,由DatagramSocket发送出去。
  2. 接收端:使用DatagramPacket类保存接收的数据,由DatagramSocket接收该类。

注:在实际情况下,服务器需要提供多个客户端的请求处理及响应。

流程图如下:


2.3Java编程实现UDP通信

        在编程之前,我们先要了解两个类---- DatagramPacket和DatagramSocket。

注:服务器相当于家,客户端相当于你,当你想回家时,我们需要得到服务器的地址(IP地址),门牌号(端口号)

(1)DatagramPacket

构造方法

构造方法方法说明
DatagramPacket(byte[]
buf, int length)
接收数据报 ,接收的数据保存在字节数组(第一个参数buf )中,接收指定长度
(第二个参数length)
DatagramPacket(byte[]
buf, int offset, int length,
SocketAddress address)
发送数据报 ,发送的数据为字节 数组(第一个参数buf )中,从 0 到指定长度
(第二个参数 length)。 address 指定目的主机的 IP 和端口号

方法:

方法名方法说明
InetAddress
getAddress()
从接收的数据报中,获取发送端主机 IP 地址;或从发送的数据报中,获取接收端主机IP 地址
int getPort()
从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
byte[] getData()
获取数据报中的数据

(2)DatagramSocket

构造方法:

构造方法方法说明
DatagramSocket()
创建一个 UDP 数据报套接字的 Socket ,绑定到本机任意一个随机端口
(一般用于客户端)
DatagramSocket(int
port)
创建一个 UDP 数据报套接字的 Socket ,绑定到本机指定的端口(一般用
于服务端)
方法:
方法解析
void receive(DatagramPacket p)
从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacketp)
从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()
关闭此数据报套接字

我们这以自己的地址为例子,环回IP。

客户端代码:

package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;// 服务器的 ip 和 服务器的端口.public UdpEchoClient(String ip, int port) throws SocketException {serverIp = ip;serverPort = port;// 这个 new 操作, 就不再指定端口了. 让系统自动分配一个空闲端口.socket = new DatagramSocket();}// 让这个客户端反复的从控制台读取用户输入的内容. 把这个内容构造成 UDP 请求, 发给服务器. 再读取服务器返回的 UDP 响应// 最终再显示在客户端的屏幕上.public void start() throws IOException {Scanner scanner = new Scanner(System.in);System.out.println("客户端启动!");while (true) {// 1. 从控制台读取用户输入的内容System.out.print("-> "); // 命令提示符, 提示用户要输入字符串.String request = scanner.next();// 2. 构造请求对象, 并发给服务器.DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), 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());// 4. 显示到屏幕上.System.out.println(response);}}public static void main(String[] args) throws IOException {//服务器ip与端口UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
}

服务器代码:

package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;// UDP 的 回显服务器.
// 客户端发的请求是啥, 服务器返回的响应就是啥.
public class UdpEchoServer {private DatagramSocket socket = null;// 参数是服务器要绑定的端口public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}// 使用这个方法启动服务器.public void start() throws IOException {System.out.println("服务器启动!");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(), response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);// 记录日志, 方便观察程序执行效果.System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(), requestPacket.getPort(),request, response);}}// 根据请求计算响应. 由于是回显程序, 响应内容和请求完全一样.public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}

三.TCP网络编程

 3.1TCP流套接字api

        如果想实现TCP的通信,我们需要使用到ServerSocket和Socket。

注意:TCP传输数据,是根据流操作,因此我们需要使用IO流操作

(一)ServerSocket

  • ServerSocket:创建TCP服务端的Socket的API,服务器端通常用于监听指定的端口并等待客户端的连接请求

        构造方法:

构造方法方法说明
ServerSocket(int port)
创建一个服务端流套接字 Socket ,并绑定到指定端口

        方法:

方法方法说明
Socket  accept()
监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端 Socket 对象,并基于该Socket 建立与客户端的连接,否则阻塞等待
close()
关闭此套接字

(二)Socket

  • Scoket:用于客户端,服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket

注:socket通常是一个对网络通信进行抽象的对象,通过它可以实现客户端和服务器之间的数据传输。

构造方法:

构造方法方法说明
Socket(String host, int port)
创建一个客户端流套接字 Socket ,并与对应 IP 的主机上,对应端口的进程建立连接

方法:

方法名方法说明
InetAddress getInetAddress()
返回套接字所连接的地址
InputStream getInputStream()
返回此套接字的输入流
OutputStream getOutputStream()
返回此套接字的输出流

3.2TCP通信代码实现

TCP代码实现通信,需要先建立连接,而确认什么时候关闭,却可以分为2种----短连接和长连接!
  1. 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
  2. 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

长、短连接区别:

  1. 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要 第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时 的,长连接效率更高。
  2. 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  3. 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于 客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

3.2.1短连接实现代码

        短连接,则是一发一收,客户端发送请求,服务器接收请求,只有请求,没有回应。

服务端:

package org.example.tcp.demo1;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {//服务器socket要绑定固定的端口private static final int PORT = 8888;public static void main(String[] args) throws IOException {// 1.创建一个服务端ServerSocket,用于收发TCP报文ServerSocket server = new ServerSocket(PORT);// 不停的等待客户端连接while(true) {System.out.println("---------------------------------");System.out.println("等待客户端建立TCP连接...");// 2.等待客户端连接,注意该方法为阻塞方法Socket client = server.accept();System.out.printf("客户端IP:%s%n", client.getInetAddress().getHostAddress());System.out.printf("客户端端口号:%s%n", client.getPort());// 5.接收客户端的数据,需要从客户端Socket中的输入流获取System.out.println("接收到客户端请求:");InputStream is = client.getInputStream();// 为了方便获取字符串内容,可以将以上字节流包装为字符流BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));String line;// 一直读取到流结束:TCP是基于流的数据传输,一定要客户端关闭Socket输出流才表示服
务端接收IO输入流结束while ((line = br.readLine()) != null) {System.out.println(line);}// 6.双方关闭连接:服务端是关闭客户端socket连接client.close();}}
}

客户端

package org.example.tcp.demo1;
import java.io.*;
import java.net.Socket;
public class TcpClient {//服务端IP或域名private static final String SERVER_HOST = "localhost";//服务端Socket进程的端口号private static final int SERVER_PORT = 8888;public static void main(String[] args) throws IOException {// 3.创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接Socket client = new Socket(SERVER_HOST, SERVER_PORT);// 4.发送TCP数据,是通过socket中的输出流进行发送OutputStream os = client.getOutputStream();// 为了方便输出字符串作为发送的内容,可以将以上字节流包装为字符流PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));// 4-1.发送数据:pw.println("hello world!");// 4-2.有缓冲区的IO操作,真正传输数据,需要刷新缓冲区pw.flush();// 7.双方关闭连接:客户端关闭socket连接client.close();}
}

以上便是短连接,客户端不会收到回应。

3.2.2长连接实现代码

        客户端发送请求,服务器接收请求,然后将其分析对其作出回应,传回客户端。

服务端:

import java.io.*;
import java.net.*;public class TCPServer {public static void main(String[] args) throws IOException {System.out.println("服务器已启动");// 创建ServerSocket对象,监听指定端口ServerSocket serverSocket = new ServerSocket(8888);while (true) {// 等待客户端连接Socket socket = serverSocket.accept();System.out.println("已连接客户端:" + socket.getInetAddress() + ":" + socket.getPort());// 接收客户端消息BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String readLine = null;while ((readLine = br.readLine()) != null) {System.out.println("客户端消息:" + readLine);// 回复客户端消息PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);pw.println("Server reply: " + readLine);}}}
}

客户端:

import java.io.*;
import java.net.*;public class TCPClient {public static void main(String[] args) throws IOException {// 创建Socket对象,连接指定IP和端口Socket socket = new Socket("localhost", 8888);// 发送消息给服务器PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);pw.println("Hello server, I am a client.");// 接收服务器消息BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String readLine = null;while ((readLine = br.readLine()) != null) {System.out.println("服务器消息:" + readLine);}// 关闭资源br.close();pw.close();socket.close();}
}

四.总结

        其实,TCP的编程比UDP要难一点点,但是只要我们理解了UDP的编程实现,我们可以更方便理解TCP的编程知识。

        TCP的通信代码实现,需要操作流操作,我们需要理解充分!

   在学习本文之前,如果你有时间,我希望你可以查看一下:网络的发展史、通信基础和原理

                                                                                                TCP和UDP的由浅到深的详细讲解

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

钉钉数字校园小程序开发:开启智慧教育新时代

随着信息技术的快速发展和校园管理的日益复杂化,数字校园已成为现代教育的重要趋势。钉钉数字校园小程序作为一种创新应用,以其专业性、思考深度和逻辑性,为学校提供了全新的管理、教学和沟方式。本文从需求分析、技术实现和应用思考三个方面…

websocket逆向-protobuf序列化与反序列化

系列文章目录 训练地址:https://www.qiulianmao.com 基础-websocket逆向基础-http拦截基础-websocket拦截基础-base64编码与解码基础-protobuf序列化与反序列化视频号直播弹幕采集实战一:Http轮询更新中 websocket逆向-protobuf序列化与反序列化基础 系…

Apipost连接数据库详解

Apipost提供了数据库连接功能,在接口调试时可以使用数据库获取入参或进行断言校验。目前的Apipost支持:Mysql、SQL Sever、Oracle、Clickhouse、达梦数据库、PostgreSQL、Redis、MongoDB 8种数据库的连接操作 新建数据库连接: 在「项目设置…

【Redis】使用Java客户端操作Redis

目录 引入jedis依赖连接Redis命令get/setexists/delkeysexpire/ttltype 引入jedis依赖 连接Redis 命令 get/set exists/del keys expire/ttl type

C++笔记之获取线程ID以及线程ID的用处

C笔记之获取线程ID以及线程ID的用处 code review! 文章目录 C笔记之获取线程ID以及线程ID的用处一.获取ID二.线程ID的用处2.1.线程池管理2.2.动态资源分配2.3.使用线程同步机制实现互斥访问共享资源2.4.使用线程 ID 辅助线程同步2.5.任务分发:线程ID可以用于将任务…

Qt 窗口与部署应用程序发布包 day6

Qt 窗口与部署应用程序发布包 day6 QWidget QWidget是所有可视控件的基类,每个控件都是矩形按照Z轴顺序排序如果控件没有父控件,则称为窗口 设置exe窗口图标 在项目文件中新建一个文件夹Resource,来存放图标文件 第一种方法 用绝对路…

UE4和C++ 开发--HUD类

HUD 平视显示器(Head Up Display),简称HUD。在蓝图中是指在屏幕上面绘制的二维物体。 1. 创建HUD 打开蓝图编辑器,创建一个蓝图类,搜索HUD,选择并命名BP_HUD。 2. 开始绘制 打开事件列表,右键搜索 EventReceive Draw HUD。有两…

互联网Java工程师面试题·Java 并发编程篇·第三弹

目录 26、什么是线程组,为什么在 Java 中不推荐使用? 27、为什么使用 Executor 框架比使用应用创建和管理线程好? 27.1 为什么要使用 Executor 线程池框架 27.2 使用 Executor 线程池框架的优点 28、java 中有几种方法可以实现一个线程…

【牛客网刷题(数据结构)】:环形链表的约瑟夫问题

描述 编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。 下一个人继续从 1 开始报数。 n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少? O(n) 示例1 好环形链表的约瑟夫问题是一个经典的问…

分布式链路追踪如何跨线程

背景 我们希望实现全链路信息,但是代码中一般都会异步的线程处理。 解决思路 我们可以对以前的 Runable 和 Callable 进行增强。 可以使用 ali 已经存在的实现方式。 TransmittableThreadLocal (TTL) 解决异步执行时上下文传递的问题 核心的实现思路如下&#…

内部类概述

一、内部类 1.内部类概述 2.内部类的四种实现形式 1.成员内部类 public class Outer {private int age99;public static String a;//成员内部类public class Inner{private int age88;private String name; // public static String school; //jdk 16开始才支持定义静态…

nvm、node、npm解决问题过程记录

在Windows10如何降级Node.js版本:可以尝试将Node.js版本降级到一个较旧的版本,以查看问题是否得以解决。可以使用Node Version Manager (nvm) 来轻松切换Node.js版本,具体完整步骤: 首先,需要安装Node Version Manager…

C++项目:【负载均衡式在线OJ】

文章目录 一、项目介绍 二、技术栈与开发环境 1.所用技术: 2.开发环境: 三、项目演示 1.运行代码 2.进入项目首页 3.题目列表 4.点击具体一道题 5.编辑代码并提交 四、项目思维导图 五、项目宏观结构 六、Comm公共模块 1.日志工具log.hpp 2.其他工具…

如何在 Spring Boot 中进行分布式追踪

在 Spring Boot 中进行分布式追踪 分布式系统中的应用程序由多个微服务组成,它们可以位于不同的服务器、容器或云中。当出现问题时,如性能瓶颈、错误或延迟,了解问题的根本原因变得至关重要。分布式追踪是一种用于跟踪和分析分布式应用程序性…

linux安装filebeat并收集日志到elasticsearch

摘要: 通过filebeat收集服务器上各个应用的日志到elasticsearch,通过tags区分不同的应用创建不同的索引保存日志。 官网地址: https://www.elastic.co/cn/downloads/past-releases#filebeat 安装步骤: 1:下载并解…

如何利用IP地址定位保护网络安全?

通过IP地址定位可以在一定程度上增强网络安全,但它并不是唯一的安全措施。以下是如何利用IP地址定位来保护网络安全的一些方法: 异常检测和入侵检测:监控网络上的IP地址流量,定位异常活动,如大规模的连接尝试、不寻常的…

微信浏览器大字体模式 按钮文字居中用line-height 显示异常

按钮文字居中用line-height 的css 在微信浏览器大字体模式,会导致显示错误。改成flex 居中就好了

对称加密和非对称加密以及CA证书

对称加密 对称加密只用到了公匙,这个公匙是消息的发送方和消息的接收方共享的,也就是消息发送方使用这个公匙对消息加密,然后接收方使用公匙对消息解密,最典型的例子比如像 encrypt 加密,比如我们有个 springboot 应用,需要对 application.yml 文件里的密码做加密,我们…

【LeetCode高频SQL50题-基础版】打卡第8天:第41~45题

文章目录 【LeetCode高频SQL50题-基础版】打卡第8天:第41~45题⛅前言好友申请II🔒题目🔑题解 2016年的投资🔒题目🔑题解 部门工资前三高的所有员工🔒题目🔑题解 修复表中的名字🔒题目…

阿里云服务器不能访问网络之安装mysql 提示连接超时

wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm 过了一段时间后提示 fail .......time out 链接超时 有可能你的服务器不能访问网络 因为宽带套餐 我购买的时候没有购 重新购买就行了