网络编程【InetAddress , TCP 、UDP 、HTTP 案例】

2024-04-15 08:52

本文主要是介绍网络编程【InetAddress , TCP 、UDP 、HTTP 案例】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

day38上

网络编程

InetAddress

理解:表示主机类

一个域名 对应 多个IP地址

	public static void main(String[] args) throws UnknownHostException {//获取本机的IP地址
//		InetAddress localHost = InetAddress.getLocalHost();
//		System.out.println(localHost);//获取域名对应的服务器地址
//		InetAddress byName = InetAddress.getByName("www.baidu.com");
//		System.out.println(byName);//获取域名对应的所有的服务器地址InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");for (InetAddress inetAddress : allByName) {System.out.println(inetAddress);}      }
//输出:www.baidu.com/183.2.172.42
//	   www.baidu.com/183.2.172.185
//是可以通过服务器地址如183.2.172.42去访问的

Scoket

Scoket也叫套接字,其表示的是IP地址和端口号的组合。

网络编程主要就是指Socket编程,网络间的通信其实就是Socket间的通信,数据就通过IO流在两个Scoket间进行传递。

TCP

API:Socket,ServerSocket

客户端(发送一个请求) 服务端(接收到这个请求,给予响应)

案例

1.简单的TCP通信

  1. 编写服务端程序
  2. 编写客户端程序
  3. 客户端向服务端发送请求信息,服务端成功接收
  4. 服务端向客户端发送响应信息,客户端成功接收

2.升级服务端,使其处理多个客户端请求

3.继续优化服务端,让多个客户端的请求无需排队

4.关闭资源-提取工具类

简单的TCP通信
简单的TCP通信理解图

TCP理解图

ps:奇男子去会所按摩
简单的TCP通信理解图

简单的TCP通信

前提:在同一局域网下

先运行服务器

//服务端
public class Server {public static void main(String[] args) throws IOException {//大堂经理ServerSocket server = new ServerSocket(8080);//18号技师//注意:accept()是线程阻塞的方法,该方法会等待客户端的连接成功后才生成一个Socket对象与之交互Socket socket = server.accept();//2.接受来自客户端的数据
//		InputStream in = socket.getInputStream();
//		InputStreamReader isr = new InputStreamReader(in, "GBK");
//		BufferedReader br = new BufferedReader(isr);//一步步封装BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));String readLine = br.readLine();System.out.println(readLine);//3.向客户端发送数据PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("18号技师:今年18岁");br.close();ps.close();server.close();}
}

使用println、BufferedReader
底层识别换行,BufferedReader流的readLine() – 读取一行
接收是获取的通过转换流再转带缓冲区的流,注意编码格式以防乱码
socket不能随便关闭,最后关闭或者不关闭

//客户端
public class Client {public static void main(String[] args) throws UnknownHostException, IOException {//注意:关闭流相当于关闭Socket!!!//奇男子Socket socket = new Socket("127.0.0.1", 8080);//1.向服务端发送数据PrintStream ps = new PrintStream(socket.getOutputStream());ps.println("奇男子:小妹妹,你多大了?");//4.接受来自服务端的数据BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));String readLine = br.readLine();System.out.println(readLine);ps.close();br.close();socket.close();}
}
简单TCP通信运行图

注意运行显示接受信息

传输文件

类似文件拷贝

较简单TCP通信,使用流不同

public class Server {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8080);Socket socket = server.accept();BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));byte[] bs = new byte[1024];int len;while((len = bis.read(bs)) != -1){bos.write(bs, 0, len);}bis.close();bos.close();server.close();}
}
//读取写入文件
public class Client {public static void main(String[] args) throws UnknownHostException, IOException {Socket socket = new Socket("127.0.0.1", 8080);BufferedInputStream bis = new BufferedInputStream(new FileInputStream("奇男子.mp4"));//直接输出流转换为带有缓冲区的,效率更高BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());byte[] bs = new byte[1024];int len;while((len = bis.read(bs)) != -1){bos.write(bs, 0, len);}bis.close();bos.close();socket.close();}
}
//读取源文件写出
单聊
单聊

把流放在循环外面,防止每次次循环都new一个流,浪费资源,还有就是没有关闭资源

一对一,你一言我一语

public class Server {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8080);Socket socket = server.accept();Scanner scan = new Scanner(System.in);BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));PrintStream ps = new PrintStream(socket.getOutputStream());while(true){String readLine = br.readLine();System.out.println(readLine);ps.println("18号技师:" + scan.next());}}
}
public class Client {public static void main(String[] args) throws UnknownHostException, IOException {Socket socket = new Socket("127.0.0.1", 8080);Scanner scan = new Scanner(System.in);PrintStream ps = new PrintStream(socket.getOutputStream());BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));while(true){ps.println("奇男子:" + scan.next());String readLine = br.readLine();System.out.println(readLine);}}
}
优化

单聊一言一语改进:用多线程,一个线程发送、一个线程接受

改进后一个人可以发多条消息

public class Server {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8080);Socket socket = server.accept();//接收消息new ReceiveThread(socket).start();//发送消息Scanner scan = new Scanner(System.in);PrintStream ps = new PrintStream(socket.getOutputStream());while(true){ps.println("18号技师:" + scan.next());}}
}
public class Client {public static void main(String[] args) throws UnknownHostException, IOException {Socket socket = new Socket("127.0.0.1", 8080);//接收消息new ReceiveThread(socket).start();//发送消息Scanner scan = new Scanner(System.in);PrintStream ps = new PrintStream(socket.getOutputStream());while(true){ps.println("奇男子:" + scan.next());}}
}

添加一个接受消息的线程

//接受的线程
public class ReceiveThread extends Thread{private Socket socket;public ReceiveThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));while(true){String readLine = br.readLine();System.out.println(readLine);}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
群聊

多线程,发送在子线程,接受在主线程

设想是几个客户端之间互相发送消息,但由于这里使用TCP,而(面向连接)TCP必须通过服务端进行交流,不能这么操作

TCP群聊理解图

服务端连接成功一个就会产生一个Socket,ServerSocket不算进去

这里接受当前客户端的消息再发送给其他客户端,key就直接做成输出流,而不是Socket对象

TCP群聊理解图

客户端没有问题,就直接用Client、ReceiveThread,服务端需要更改

简单测试需要多个电脑操作进行群聊,即多个客户端

public class Server {public static final ConcurrentHashMap<String, PrintStream> map = new ConcurrentHashMap<>();public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8080);while(true){Socket socket = server.accept();String ip = socket.getInetAddress().toString();PrintStream ps = new PrintStream(socket.getOutputStream());map.put(ip, ps);new ServerThread(socket).start();}}
}

添加一个服务端的线程

public class ServerThread extends Thread{private Socket socket;public ServerThread(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {//接受当前客户端的消息BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));while(true){String readLine = br.readLine();System.out.println(readLine);//发送给其他客户端消息Set<Entry<String,PrintStream>> entrySet = Server.map.entrySet();for (Entry<String, PrintStream> entry : entrySet) {String ip = entry.getKey();PrintStream ps = entry.getValue();if(!socket.getInetAddress().toString().equals(ip)){ps.println(readLine);}}}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

三次握手、四次挥手

三次握手
四次挥手

UDP

简介

UDP(User Datagram Protocol)用户数据报包协议,UDP和TCP位于同一层-传输层,但它对于数据包的顺序错误或重发没有TCP可靠;UDP是一种面向无连接的通信协议。UDP向应用程序提供一种发送封装的原始IP数据报的方法,并且发送时无需建立连接,不保证可靠数据的传输

UDP理解图

适用:视频聊天

UDP理解图

简单的UDP通信

协议的Socket是DatagramSocket

trim()去首尾空格,因为传的数据不到容量就会是空白,超过容量也接收不了

public class Client01 {public static void main(String[] args) throws IOException {//注意:7070表示的是自己的端口号,不是对方的端口号DatagramSocket socket = new DatagramSocket(7070);//1.向客户端2发送数据byte[] buf = "小桥流水人家".getBytes();DatagramPacket p = new DatagramPacket(buf , 0, buf.length, InetAddress.getByName("127.0.0.1"), 8080);socket.send(p);//4.接受来自客户端1的数据buf = new byte[1024];p = new DatagramPacket(buf , buf.length);socket.receive(p);System.out.println(new String(buf).trim());socket.close();}
}
public class Client02 {public static void main(String[] args) throws IOException {DatagramSocket socket = new DatagramSocket(8080);//2.接受来自客户端1的数据byte[] buf = new byte[1024];DatagramPacket p = new DatagramPacket(buf , buf.length);socket.receive(p);System.out.println(new String(buf).trim());//3.向客户端2发送数据buf = "古道西风瘦马".getBytes();p = new DatagramPacket(buf , 0, buf.length, InetAddress.getByName("127.0.0.1"), 7070);socket.send(p);socket.close();}
}

单聊

客户端之间发送消息

public class Client01 {public static void main(String[] args) throws SocketException {DatagramSocket socket = new DatagramSocket(7070);new ReceiveThread(socket).start();new SendThread("奇男子", "127.0.0.1", 8080, socket).start();}
}
public class Client02 {public static void main(String[] args) throws SocketException {DatagramSocket socket = new DatagramSocket(8080);new ReceiveThread(socket).start();new SendThread("小小", "127.0.0.1", 7070, socket).start();}
}

添加一个发送线程、一个接收线程

public class SendThread extends Thread{private String nickName;private String ip;private int port;private DatagramSocket socket;public SendThread(String nickName, String ip, int port, DatagramSocket socket) {this.nickName = nickName;this.ip = ip;this.port = port;this.socket = socket;}@Overridepublic void run() {Scanner scan = new Scanner(System.in);while(true){byte[] buf = (nickName + ":" + scan.next()).getBytes();try {DatagramPacket p = new DatagramPacket(buf, buf.length, InetAddress.getByName(ip), port);socket.send(p);} catch (IOException e) {e.printStackTrace();}}}}
public class ReceiveThread extends Thread{private DatagramSocket socket;public ReceiveThread(DatagramSocket socket) {this.socket = socket;}@Overridepublic void run() {while(true){byte[] buf = new byte[1024];DatagramPacket p = new DatagramPacket(buf , buf.length);try {socket.receive(p);System.out.println(new String(buf).trim());} catch (IOException e) {e.printStackTrace();}}}
}

TCP vs UDP

TCPUDP
是否连接面向连接无面向连接
传输可靠性可靠不可靠
应用场合传输大量数据少量数据
速度

UDP — 发短信

TCP — 打电话

HTTP

查询淘宝商品

需求:获取淘宝商品周边类别
市面上服务器一般都默认为utf-8,设置编码格式,解决乱码

public class Test01 {public static void main(String[] args) throws IOException {String path = "https://suggest.taobao.com/sug?code=utf-8&q=%E8%80%90%E5%85%8B&callback=cb";//创建链接对象URL url = new URL(path);//获取连接对象//玩的是他的子类,父类为抽象类HttpURLConnection connection = (HttpURLConnection) url.openConnection();//设置参数connection.setConnectTimeout(5000);//设置连接超时时间connection.setReadTimeout(5000);//设置读取数据超时时间connection.setDoInput(true);//设置是否允许使用输入流connection.setDoOutput(true);//设置是否允许使用输出流//获取响应状态码int code = connection.getResponseCode();if(code == HttpURLConnection.HTTP_OK){BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));char[] cs = new char[1024];int len;while((len = br.read(cs)) != -1){System.out.println(new String(cs, 0, len));}}else if(code == HttpURLConnection.HTTP_NOT_FOUND){System.out.println("页面未找到");}}
}

下载图片

更改流即可【不同数据源用不同的流即可】

public class Test02 {public static void main(String[] args) throws IOException {String path = "https://wx2.sinaimg.cn/mw690/e2438f6cly1hoo3qpm7vrj21111jk4mn.jpg";//创建链接对象URL url = new URL(path);//获取连接对象HttpURLConnection connection = (HttpURLConnection) url.openConnection();//设置参数connection.setConnectTimeout(5000);//设置连接超时时间connection.setReadTimeout(5000);//设置读取数据超时时间connection.setDoInput(true);//设置是否允许使用输入流connection.setDoOutput(true);//设置是否允许使用输出流//获取响应状态码int code = connection.getResponseCode();if(code == HttpURLConnection.HTTP_OK){BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("金智媛.jpg"));byte[] bs = new byte[1024];int len;while((len = bis.read(bs)) != -1){bos.write(bs, 0, len);}bis.close();bos.close();}else if(code == HttpURLConnection.HTTP_NOT_FOUND){System.out.println("页面未找到");}}
}

所需学习类

DatagramPacket —此类表示数据报包

DatagramSocket —此类用来发送和接受数据报包的套接字

SocketAddress getLocalSocketAddress() 返回此套接字绑定的端点的地 址,如果尚未绑定则返回 null

Voidsend(DatagramPacket p) 从此套接字发送数据报包。

Voidreceive(DatagramPacket p) 从此套接字接收数据报包。

SocketAddress —抽象类,IP+端口号

总结

1.网络编程
1.1 InetAddress
1.2 TCP
传输文件
单聊、优化单聊
群聊
三次握手、四次挥手
1.3 UDP
单聊
TCP vs UDP
1.4 HTTP
查询淘宝商品
下载图片

这篇关于网络编程【InetAddress , TCP 、UDP 、HTTP 案例】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/905385

相关文章

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

MySQL不使用子查询的原因及优化案例

《MySQL不使用子查询的原因及优化案例》对于mysql,不推荐使用子查询,效率太差,执行子查询时,MYSQL需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响,本文给大家... 目录不推荐使用子查询和JOIN的原因解决方案优化案例案例1:查询所有有库存的商品信息案例2:使用EX

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五