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

网络编程【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
查询淘宝商品
下载图片

http://www.lryc.cn/news/338839.html

相关文章:

  • 软考中级工程师网络技术第二节网络体系结构
  • Mac 软件清单
  • 【Leetcode每日一题】 分治 - 颜色分类(难度⭐⭐)(57)
  • 微信登录功能-保姆级教学
  • 嵌入式MCU BootLoader开发配置详细笔记教程
  • Unity 中消息提醒框
  • 好数(蓝桥杯)
  • 自动化收集Unity版本更新日志
  • 【CSS】CSS水平居中方案
  • SQL注入sqli_labs靶场第二题
  • 基于机器学习的人脸发型推荐算法研究与应用实现
  • 【服务器部署篇】Linux下Nginx的安装和配置
  • React搭建一个文章后台管理系统
  • Elasticsearch 支持的插件 —— 筑梦之路
  • HTML:链接
  • vscode远程连接centos
  • scala---面向对象(类,对象,继承,抽象类,特质)
  • 【机器学习300问】68、随机初始化神经网络权重的好处?
  • 数据结构与算法——20.B-树
  • Tomcat源码解析——Tomcat的启动流程
  • 蓝桥杯真题演练:2023B组c/c++
  • 微信小程序实现预约生成二维码
  • 专业140+总分410+北京理工大学826信号处理导论考研经验北理工电子信息通信工程,真题,参考书,大纲。
  • 做一个后台项目的架构
  • 嵌入式单片机 TTL电平、232电平、485电平的区别和联系
  • 2024年大唐杯备考
  • Spring Boot(06):Spring Boot与MySQL搭配,打造极简高效的数据管理系统
  • Vue3 + Vite 构建组件库发布到 npm
  • Vite多环境配置与打包:灵活高效的Vue开发工作流
  • 从零实现诗词GPT大模型:数据集介绍和预处理