JavaSE进阶——网络编程

news2025/2/8 10:34:35

文章目录

  • 前言
  • 一、网络编程
  • 二、通信
    • 1、两个重要的要素
    • 2、通信协议
  • 三 、Socket
  • 四、基于TCP的网络编程
    • 1、单向通信
      • 1.1 服务端
      • 1.2 客户端
    • 2、双向通信
      • 2.1 服务端
      • 2.2 客户端
    • 3、传输对象
      • 3.1 服务端
      • 3.2 客户端
    • 4、保持通信
      • 4.1 服务端
      • 4.2 客户端
  • 五、基于UDP的网络编程
    • 1、单向通信
      • 1.1 发送方
      • 1.2 接收方
    • 2、双向通信
      • 2.1 发送方
      • 2.2 接收方
    • 3、保持通信
      • 3.1 发送方
      • 3.2 接收方
  • 六、 总结

前言

📢 大家好,我是程序员Forlan,本篇内容主要分享网络编程的知识,属于基础内容,说实话,这块在大部分公司中,使用很少甚至可能用不上,游戏行业、视频行业可能使用多一些,可以根据情况学习,作一个知识补充~

一、网络编程

把分布在不同地方的计算机,用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息、共享硬件、软件、数据信息等资源

计算机在网络中进行数据的传输,发送/接收数据

二、通信

1、两个重要的要素

IP+端口号

  • 通过IP可以定位到每台机器的唯一IP(IP定位机器)
  • 通过端口号可以定位到机器中的应用程序(端口号定位应用程序)

InetAddress:封装了IP

InetAddress ia2 = InetAddress.getByName("localhost");// 本地ip地址
System.out.println(ia2);
InetAddress ia3 = InetAddress.getByName("127.0.0.1");// 本地ip地址
System.out.println(ia3);
InetAddress ia4 = InetAddress.getByName("Forlan");// 计算机名
System.out.println(ia4); // 计算机名+ip
InetAddress ia5 = InetAddress.getByName("www.baidu.com");// 域名
System.out.println(ia5); // 域名+ip

InetSocketAddress:封装了IP,端口号

InetSocketAddress isa = new InetSocketAddress("127.0.0.1",8080);
System.out.println(isa);
System.out.println(isa.getHostName());
System.out.println(isa.getPort());

2、通信协议

表面看来,计算机之间的通信,是应用层之间的通信,但实际传输需要经过多层,如下图:

在这里插入图片描述
主要看的是传输层的协议,有TCP和UDP,两者的一个区别就是可不可靠,TCP需要三次握手和四次挥手,是比较可靠的,后面我们也会演示下不同的编程方式

三 、Socket

一般网络编程也叫Socket编程,Socket就是套接字,中文意思是插座

所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。

Socket是由IP地址和端口结合的,它存在于通信区域,其实就是处理应用层和传输层,获取传输协议

  • 应用层:程序员写的代码,我们写的IO流,们最直接的感受,就是IO流的传输
  • 传输层:TCP或UDP传输

四、基于TCP的网络编程

1、单向通信

客户端给服务端发送一句话
注:先启动服务端,否则会报错Connection refused: connect

1.1 服务端

ServerSocket ss = null;
Socket s = null;
InputStream is = null;
DataInputStream dis = null;
try {
	// 1、创建套接字: 指定服务器的端口号
	ss = new ServerSocket(8888);
	// 2、阻塞等待接收客户端的数据,会返回客户端的Socket,才真正连接
	s = ss.accept();
	// 3、得到输入流,接收信息
	is = s.getInputStream();
	dis = new DataInputStream(is);
	System.out.println("收到客户端的信息:" + dis.readUTF());
} catch (IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (null != ss) {
			ss.close();
		}
		if (null != s) {
			s.close();
		}
		if (null != is) {
			is.close();
		}
		if (null != dis) {
			dis.close();
		}
	} catch (IOException e) {
		e.printStackTrace();
	}

1.2 客户端

Socket s = null;
OutputStream os = null;
DataOutputStream dos = null;
try {
	// 1、创建套接字Socket,指定ip和端口号
	s = new Socket("127.0.0.1", 8888);
	// 2、得到输出流
	os = s.getOutputStream();
	// 转为处理流DataOutputStream,方面我们发文本
	dos = new DataOutputStream(os);
	dos.writeUTF("你好,我是程序员Forlan");
} catch (IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (null != s) {
			s.close();
		}
		if (null != os) {
			os.close();
		}
		if (null != dos) {
			dos.close();
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

2、双向通信

客户端给服务端发送一句话,服务端回话
在单向通信的基础上,进行了优化简写,利用try(),无需关闭资源了

2.1 服务端

try (ServerSocket ss = new ServerSocket(8888);
	 Socket s = ss.accept();
	 InputStream is = s.getInputStream();
	 DataInputStream dis = new DataInputStream(is);
	 OutputStream os = s.getOutputStream();
	 DataOutputStream dos = new DataOutputStream(os);) {
	System.out.println("收到客户端的信息:" + dis.readUTF());
	dos.writeUTF("服务器已经收到啦~");
} catch (IOException e) {
	e.printStackTrace();
}

2.2 客户端

try (Socket s = new Socket("127.0.0.1", 8888);
	 OutputStream os = s.getOutputStream();
	 DataOutputStream dos = new DataOutputStream(os);
	 InputStream is = s.getInputStream();
	 DataInputStream dis = new DataInputStream(is);) {
	dos.writeUTF("你好,我是程序员Forlan");
	System.out.println("收到服务端的信息:" + dis.readUTF());
} catch (IOException e) {
	e.printStackTrace();
}

3、传输对象

定义Money对象,实现Serializable接口,进行传输

3.1 服务端

try (ServerSocket ss = new ServerSocket(8888);
	 Socket s = ss.accept();
	 InputStream is = s.getInputStream();
	 ObjectInputStream ois = new ObjectInputStream(is);
	 OutputStream os = s.getOutputStream();
	 DataOutputStream dos = new DataOutputStream(os);) {
	String msg = "转账成功";
	Money money = (Money) ois.readObject();
	System.out.println("收到客户端的信息:" + money);
	BigDecimal zero = new BigDecimal("0.0");
	if (null == money || money.getAmout().compareTo(zero) < 0) {
		msg = "转账失败";
	}
	dos.writeUTF(msg);
} catch (Exception e) {
	e.printStackTrace();
}

3.2 客户端

try (Socket s = new Socket("127.0.0.1", 8888);
	 OutputStream os = s.getOutputStream();
	 ObjectOutputStream oos = new ObjectOutputStream(os);
	 InputStream is = s.getInputStream();
	 DataInputStream dis = new DataInputStream(is);) {
	// 录入信息,发给服务端
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入账户:");
	String account = sc.next();
	System.out.println("请输入金额:");
	BigDecimal amout = sc.nextBigDecimal();
	Money money = new Money(account, amout);
	oos.writeObject(money);
	// 接收服务端信息
	System.out.println("收到服务端的信息:" + dis.readUTF());
} catch (IOException e) {
	e.printStackTrace();
}

4、保持通信

前面实现的服务器,是针对一个请求服务,之后服务器就关闭了,想让服务器必须一直在监听 ,一直开着,等待客户端的请求

4.1 服务端

try (ServerSocket ss = new ServerSocket(8888);
	 Socket s = ss.accept();
	 InputStream is = s.getInputStream();
	 ObjectInputStream ois = new ObjectInputStream(is);
	 OutputStream os = s.getOutputStream();
	 DataOutputStream dos = new DataOutputStream(os);) {
	while (true) {
		String msg = "转账成功";
		Money money = (Money) ois.readObject();
		System.out.println("收到客户端的信息:" + money);
		BigDecimal zero = new BigDecimal("0.0");
		if (null == money || money.getAmout().compareTo(zero) < 0) {
			msg = "转账失败";
		}
		dos.writeUTF(msg);
	}
} catch (Exception e) {
	e.printStackTrace();
}

4.2 客户端

try (Socket s = new Socket("127.0.0.1", 8888);
	 OutputStream os = s.getOutputStream();
	 ObjectOutputStream oos = new ObjectOutputStream(os);
	 InputStream is = s.getInputStream();
	 DataInputStream dis = new DataInputStream(is);) {
	while (true) {
		// 录入信息,发给服务端
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入账户:");
		String account = sc.next();
		if (Objects.equals("退钱", account)) {
			System.out.println("告辞");
			break;
		}
		System.out.println("请输入金额:");
		BigDecimal amout = sc.nextBigDecimal();
		Money money = new Money(account, amout);
		oos.writeObject(money);
		// 接收服务端信息
		System.out.println("收到服务端的信息:" + dis.readUTF());
	}
} catch (IOException e) {
	e.printStackTrace();
}

五、基于UDP的网络编程

1、单向通信

1.1 发送方

// 1、创建套接字,指定我方的端口号
try (DatagramSocket ds = new DatagramSocket(1111);) {
	// 2、准备数据包,需要四个参数:数据的字节数组、字节数组长度、接收方的ip、接收方的端口号
	String str = "hello";
	byte[] bytes = str.getBytes();
	DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 2222);
	// 3、发送数据包
	ds.send(dp);
} catch (IOException e) {
	e.printStackTrace();
}

1.2 接收方

// 1、创建套接字,指定我方的端口号
try (DatagramSocket ds = new DatagramSocket(2222);) {
	// 2、准备空的数据包,用来接收其它地方传过来的
	byte[] b = new byte[1024];
	DatagramPacket dp = new DatagramPacket(b, b.length);
	// 3、接收对方的数据包,填充到dp中
	ds.receive(dp);
	// 4、取出数据
	byte[] data = dp.getData();
	String s = new String(data, 0, dp.getLength());
	System.out.println("程序员B说:" + s);
} catch (IOException e) {
	e.printStackTrace();
}

不需要存在接收方也不会报错

2、双向通信

2.1 发送方

try (Socket s = new Socket("127.0.0.1", 8888);
	 OutputStream os = s.getOutputStream();
	 ObjectOutputStream oos = new ObjectOutputStream(os);
	 InputStream is = s.getInputStream();
	 DataInputStream dis = new DataInputStream(is);) {
	// 录入信息,发给服务端
	Scanner sc = new Scanner(System.in);
	System.out.println("请输入账户:");
	String account = sc.next();
	System.out.println("请输入金额:");
	BigDecimal amout = sc.nextBigDecimal();
	Money money = new Money(account, amout);
	oos.writeObject(money);
	// 接收服务端信息
	System.out.println("收到服务端的信息:" + dis.readUTF());
} catch (IOException e) {
	e.printStackTrace();
}

2.2 接收方

// 1、创建套接字,指定我方的端口号
try (DatagramSocket ds = new DatagramSocket(2222);) {
	// 2、准备空的数据包,用来接收其它地方传过来的
	byte[] b = new byte[1024];
	DatagramPacket dp = new DatagramPacket(b, b.length);
	// 3、接收对方的数据包,填充到dp中
	ds.receive(dp);
	// 4、取出数据
	byte[] data = dp.getData();
	String s = new String(data, 0, dp.getLength());
	System.out.println("程序员B说:" + s);
	// 5、回复信息
	String str = "hi";
	byte[] bytes = str.getBytes();
	DatagramPacket dp2 = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 1111);
	ds.send(dp2);
} catch (IOException e) {
	e.printStackTrace();
}

3、保持通信

下面实现一种可以保持通信的UDP,发送方发送的时候,接收方要启动,不然发送方一直等着,接收方也一直等着

3.1 发送方

// 1、创建套接字,指定我方的端口号
try (DatagramSocket ds = new DatagramSocket(1111);) {
	while (true) {
		// 2、准备数据包,需要四个参数:数据的字节数组、字节数组长度、接收方的ip、接收方的端口号
		Scanner sc = new Scanner(System.in);
		System.out.print("请输入消息:");
		String msg = sc.next();
		byte[] bytes = msg.getBytes();
		DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 2222);
		// 3、发送数据包
		ds.send(dp);
		if (Objects.equals("bye", msg)) {
			System.out.println("溜了~");
			break;
		}
		// 4、接收回复
		byte[] b = new byte[1024];
		DatagramPacket dp2 = new DatagramPacket(b, b.length);
		ds.receive(dp2);
		byte[] data = dp2.getData();
		String s = new String(data, 0, dp2.getLength());
		System.out.println("程序员A说:" + s);
	}
} catch (IOException e) {
	e.printStackTrace();
}

3.2 接收方

// 1、创建套接字,指定我方的端口号
try (DatagramSocket ds = new DatagramSocket(2222);) {
	while (true) {
		// 2、准备空的数据包,用来接收其它地方传过来的
		byte[] b = new byte[1024];
		DatagramPacket dp = new DatagramPacket(b, b.length);
		// 3、接收对方的数据包,填充到dp中
		ds.receive(dp);
		// 4、取出数据
		byte[] data = dp.getData();
		String msg = new String(data, 0, dp.getLength());
		System.out.print("程序员B说:" + msg);
		if (Objects.equals("bye", msg)) {
			System.out.println("程序员B开心去了");
			break;
		}
		// 5、回复信息
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入消息:");
		String str = sc.next();
		byte[] bytes = str.getBytes();
		DatagramPacket dp2 = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"), 1111);
		ds.send(dp2);
	}
} catch (IOException e) {
	e.printStackTrace();
}

六、 总结

TCP和UDP网络编程的区别:

  • TCP

客户端: 使用Socket,发送使用输出流,接收使用输入流
服务端: 使用ServerSocket监听得到Socket,接收使用输入流,发送使用输出流
客户端和服务端地位不平等
由客户端主动发起,和服务端建立连接,完成通信
服务端得先启动,不然客户端会报错

  • UDP

发送方和接收方,都是使用DatagramSocket 发送和接收的是DatagramPacket(数据包)
发送方和接收方的地位是平等的

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

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

相关文章

软件开发流程管理中的6个重点

1、需求的确定 充分了解用户真实需求&#xff0c;与用户保持沟通交流&#xff1b;需求文档需详尽、准确&#xff0c;明确功能和客户期望&#xff1b;确保需求的合理性、完整性和可行性&#xff0c;并对需求进行优先级排序。 软件开发流程管理中的6个重点 2、设计原则 设计包括概…

【机器学习】一个简单的神经网络例子教你理解前向传播

在开始这个例子前&#xff0c;希望你已经了解了神经网络的相关内容&#xff0c;可以参见如下文章 https://blog.csdn.net/weixin_45434953/article/details/131048661 在计算机中&#xff0c;有一种很基础的运算称之为与运算&#xff0c;这是一个二元运算符&#xff0c; x 1 &…

web前端-TypeScript学习

web前端-TypeScript学习 TypeScript 介绍TypeScript 初体验安装编译TS的工具包编译并运行TS代码 TypeScript 常用类型类型注解常用基础类型原始类型数组类型类型别名函数类型对象类型接口元祖类型推论类型断言字面量类型枚举any类型typedof TypeScript 高级类型class类class的基…

6.Opencv-图像腐蚀、膨胀(开运算,闭运算)

1.图像腐蚀 这个操作会把前景物体的边界腐蚀掉。这是怎么做到的呢&#xff1f;卷积核沿着图像滑动&#xff0c;如果与卷积核对应的图像的所有像素值都是1&#xff0c;那么该区域的所有像素值就是1&#xff0c;否则为0。用于去除白噪声和断开两个连在一起的物体等。 语法&…

剑走偏锋,无头浏览器是什么神奇的家伙

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」&#xff0c;专注于 Java技术 及周边生态。 我的个人网站&#xff1a;古时的风筝 浏览器是再熟悉不过的东西了&#xff0c;几乎每个人用过&#xff0c;比如 Chrome、FireFox、Safari&#xff0c;尤其是我们程序员&a…

ASEMI代理台湾光宝LTV-3120光耦合器中文资料

编辑-Z LTV-3120是一种高性能光耦&#xff0c;由于其可靠性、效率和多功能性&#xff0c;在各种应用中都很受欢迎。本文将全面了解LTV-3120其功能、应用以及它如何改进您的电子设计。 什么是光电耦合器&#xff1f; 光耦&#xff0c;也称为光隔离器&#xff0c;是一种利用光在…

时序数据库的流计算支持

一、时序数据及其特点 时序数据&#xff08;Time Series Data&#xff09;是基于相对稳定频率持续产生的一系列指标监测数据&#xff0c;比如一年内的道琼斯指数、一天内不同时间点的测量气温等。时序数据有以下几个特点&#xff1a; 历史数据的不变性数据的有效性数据的时效…

Linux:cp、mv、rm命令

1、cp命令&#xff1a;用于复制文件/文件夹&#xff0c;语法&#xff1a; cp [-r] 参数1 参数2 r参数可选&#xff0c;用于对文件夹进行复制&#xff0c;表示递归 参数1&#xff1a;Linux路径&#xff0c;表示被复制的文件或文件夹 参数2&#xff1a;Linux&#xff0c;表示要复…

数据库期末复习第一章(看完包过)

目录 第一章 第一章 主要是一些概念&#xff0c;了解几个基本概念&#xff0c;并且记住英文缩写 DB是数据库&#xff08;database&#xff09; 0.数据 Data 1.数据库 DB &#xff08;database 数据库&#xff09; 2.数据库管理系统 DBMS &#xff08;M&#xff1a;mange 管…

论文解读 | 基于蒙特卡罗树搜索的触觉目标识别主动末端执行器姿态选择

原创 | 文 BFT机器人 本论文提出了一种新颖的方法&#xff0c;使用仅触觉来进行主动物体识别。该算法通过蒙特卡罗树搜索来选择最佳的手腕姿态序列进行物体识别。 具体来说&#xff0c;该算法将问题建模为马尔可夫决策过程&#xff08;MDP&#xff09;&#xff0c;并通过观察和…

记一次简单的SQL调优

记一次简单的SQL调优 前言排查分析问题分析SQL的执行流程存在的问题优化思路 验证解决验证执行流程一些执行计划的基本知识 优化先执行where条件过滤不需要的行&#xff0c;再进行左连接提示排序走索引为常用查询条件创建索引调整查询条件的顺序 前言 相信大家对后端数据库的S…

【Uniapp】小程序携带Token请求接口+无感知登录方案2.0

本次改进原文《【Uniapp】小程序携带Token请求接口无感知登录方案》&#xff0c;在实际使用过程中我发现以下bug&#xff1a; 若token恰好在用户访问接口时到期&#xff0c;就会直接查询为空&#xff0c;不反映token过期问题&#xff08;例如&#xff1a;弹窗显示订单查询记录…

使用python脚本将视频素材转化为图片数据集并打标

1.前言 在深度学习的训练过程中&#xff0c;第一步要做的制作数据集。本文所介绍的内容就是在面临视频素材时&#xff0c;如何将这个视频素材转换成图片&#xff0c;并将生成的图片给打上标签。 2.视频转图片的代码展示 # codingutf-8 import cv2 import osroot "F:\H…

MySQL数据库及基础操作

MySQL数据库 一、数据库的基本概念二、数据库发展史1、第一代数据库2、第二代数据库3、第三代数据库 三、当今主流数据库介绍四、关系型数据库1、结构2、理解关系数据库 五、非关系数据库六、数据库基本操作1、常用的数据类型2、查看数据库结构3、SQL语句3.1 DDL3.2 DML3.3 DQL…

pycharm 命令行创建版本库

pycharm中已建好的项目如何上传自已的git服务器中 通过命令行创建一个新的版本库 touch README.mdgit initgit add README.mdgit commit -m "first commit"git remote add origin ssh://XXXXip:29418/newbb.gitgit push -u origin master 通过命令行推送一个已存在的…

数据挖掘课件01-07

1、数挖的定义、产生原因&#xff0c;解决问题 数据挖掘就是寻找数据中隐含的知识并用于产生商业价值。 数据挖掘产生动因&#xff1a;海量数据、维度众多、问题复杂 解决问题&#xff1a;分类问题&#xff0c;聚类问题、回归问题、关联问题、 分类算法&#xff1a;C4.5&…

微信如何设置快速回复?

目前微信线上沟通已经成为绝大多数人士的首选&#xff0c;尤其不管是企业还是个人&#xff0c;都会利用微信打造私域。而做微信沟通的话&#xff0c;大家最为关心的就是怎么做到最快捷的回复对方。 可以看看这个功能&#xff0c;提前设置好常见问题的回复话术&#xff0c;可个…

JS + 浮动 + 递归实现图片瀑布流懒加载

思路 页面 pege 分成左浮动的数列 lineBox&#xff0c;每列中图片 sinImg 依次向下摆放每加载一张图片时&#xff0c;判断页面中哪列的高度最小&#xff0c;将当前图片放到最小的那列尾部监听当前图片 onload 事件&#xff0c;当前图片加载完成后&#xff0c;再加载下一张图片…

【python】前方弹幕高能:教你一键实现自动化指定直播间发送弹幕,为你喜欢的女主播疯狂打call叭~

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 不知道你们平时看不看直播&#xff0c;每次看到界面中的滚动弹幕&#xff0c;还挺有意思。 无中生事—— 前几天看到喜欢的主播打比赛呢~ 精彩时刻恨不得双手打字打call的飞快&#xff0c;那激动的无语轮次了都&#…

Android生态下的Kotlin有哪些更新#GoogleIO 2023

Android生态下Kotlin有哪些更新#GoogleIO 2023 自Android官方宣布Kotlin作为Android开发的第一语言&#xff0c;过去将近6年时间。下面是GoogleIO 2023宣布的Android生态的4项重要更新。 Kotlin编译器2.0版本 如果你是一位Kotlin开发者&#xff0c;你可能会对听到这个消息感…