TCP协议收发数据、文件上传案例--java进阶day17

1.TCP协议

2.TCP协议收发数据

[1]客户端方面

1.创建Socket对象,指定ip和端口

2.获取传输数据的流对象,这里的流对象是针对服务端进行数据传输,与本地文件读写无关

3.读写操作

4.关流

[2]服务端方面

1.创建SeverSocket对象,指定ip和端口

2.使用SeverSocket接收响应

3.获取传输数据的流对象

4.读写操作

5.关流

代码演示

1.客户端方面

1.创建Socket对象,指定端口

2.获取流对象

3.读写操作,因为是字节流,不能直接传字符串。os是写给服务端的,is是读取服务端的

4.关流

2.服务端方面

1.创建SeverSocket对象,指定端口,确保服务端和客户端连接,端口要一致

2.服务端响应客户端需求

3.获取流对象

4.读写操作,read一次只能读一个字节,所以我们创建一个数组,一次性读取。

获取read返回值得到有效字节个数,通过String构造方法去除乱码

通过SeverSocket对象获取到客户端的ip对象,调用方法获取对方ip地址

5.关流

3.TCP细节补充

TCP协议包含“三次握手”、“四次挥手”

“三次握手”即建立联系

“三次握手”是通过客户端和服务端互相发包来确认连接

客户端首先发送一个SYN包给服务端,服务端接收后发送SYN和额外的ACK包给客户端,再由客户端发送回ACK包确认连接

建立连接发送三次而不是两次的原因是防止SYN包在网络节点中卡住而导致资源浪费

客户端向服务端第一次发送SYN包,如果SYN包中途卡住,客户端就会再发一次,此时服务端接收包,将SYN包和ACK包都返回客户端,此时连接建立

如果之前的卡住的SYN包又发送给服务端,服务端又会以为要建立连接,但是客户端认为这是第一次连接,不会建立连接,导致第二次连接资源浪费

案例1

通过网络传输将文件传给别的磁盘

通过关流本地文件的流对象将文件传给客户端,再由客户端通过网络传输到服务端,服务端再通过流对象传给其他磁盘

代码演示

客户端准备工作,创建Socket对象,获取传输数据的流对象

文件上传过程会有中文,所以我们要使用字符流,通过转换流将字节流转换成字符流

为了方便读取,我们再创建字符缓冲流,参数要给Reader的实现类,转换的字符流也是Reader的实现类,直接放入

服务端进行准备工作,创建SeverSocket对象,其他步骤与上述一致

封装要上传的对象,先将文件的名称传给服务端,涉及字符串,我们使用字符流进行读写

服务端读取到名称后,向客户端发送ok标志

客户端读取到ok,开始传输数据给服务端

创建本地字节输入流,读取字节到客户端,再由客户端的字节流将数据传给服务端

服务端封装要上传到本地的路径文件,通过子父极拼接实现,父极为要存的磁盘,子级即是最初读取到的名称

服务端创建本地字节输出流,然后再读取客户端传来的数据,因为是字节形式,所以用服务端的字节流读取,再由本地字节流写出

服务端回写消息给客户端,读取成功,使用字符流传输字符串

客户端读取服务端回写的消息,关流

总览

右键运行,发现控制台卡住了

程序卡住有多个因素:

1.readline的结束标志是换行,我们应该手动写出一个换行符,readline才会结束

2.字符流内置数组,我们要使用flush刷出才有内容

3.服务端的网络流读取不到-1,导致循环一直持续

fis是关联文件的流对象,是可以读到-1的,但是is是网络流,读不到文件中-1的结束标记

所以,我们要手动给服务端一个结束的标记

总览

处理用户名重复问题

如果用户上传的图片名称一致,就会导致图片被覆盖

使用UUID生成随机字符串解决该问题

在文件存储位置上加上固定的代码,通过生成的随机字符串就可以保证文件名称不重复

处理多用户

目前我们的代码只能供一个用户使用,我们需要优化代码使其能让多用户使用

在服务端方面,通过无限循环包裹响应,以此多次接收客户端的请求,达到多用户使用需求

响应的代码及后续的读写的代码都会一直运行,客户端多次运行传来的数据均可接收

仅仅循环还不够,现在的代码是单线程,多个用户发来的数据需要排队进行传输,假如第一个用户传了10G文件,读取的代码就要运行较长时间,后面的用户就要等待很久

因此,我们还需要开启多线程,在响应请求后,开启线程

但如果直接将后续的代码都放入run方法就会显的特别臃肿,所以我们额外写一个线程类,通过该类实现线程

接下来,将后续的读取代码全部放入实现类中

红线的代码只是有异常,主要问题是socket报错,因为实现类找不到socket变量

只需要通过实现类的构造方法,将服务端的socket传递过来即可

总览

代码优化,通过线程池开启线程,配置好参数后,将实现类放入submit,开启后续线程任务

posted @ 2025-05-24 14:23  直実  阅读(96)  评论(0)    收藏  举报