一、网络的相关概念
1.1 网络通信
- 概念:两台设备之间通过网络实现数据传输
- 网络通信 :将数据通过网络从一台设备传输到另一台设备
- java.net 包下提供了一系列的类或接口,供程序员使用,完成网络通信

1.2 网络
- 概念:两台或多台设备通过一定物理设备连接起来构成了网络
- 根据网络的覆盖范围不同,对网络进行分类
- 局域网:覆盖范围最小,仅仅覆盖一个教室或者一个机房
- 城域网:覆盖范围较大,可以覆盖一个城市
- 广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广域网的代表

1.3 IP 地址
- 概念:用于唯一标识网络中的每台计算机/主机
- 查看 ip 地址:ipconfig
- ip 地址的表示形式:点分十进制 xx.xx.xx.xx
- 每一个十进制数的范围:0 ~ 255
- ip 地址的组成 = 网络地址 + 主机地址,比如:192.168.16.69
- IPv6 是互联网工程任务组设计的用于替代 IPv4 的下一代IP协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址
- 由于 IPv4 最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6 的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
1.4 IPv4 地址分类


1.5 域名和端口号
域名:
- 形如:www.baidu.com
- 好处:为了方便记忆,解决记 ip 的困难
- 概念:将 ip 地址映射成域名,这里怎么映射上,HTTP 协议
端口号:
- 概念:用于标识计算机上某个特定的网络程序
- 表示形式:以整数形式,端口号 0 ~ 65535 [ 2个字节表示端口 0 ~2^16 - 1 ]
- 0 ~ 1024 已经被占用,比如 ssh 22, ftp 21,smtp 25,http 80
- 常见的网络程序端口号:
- tomcat:8080
- mysql:3306
- oracle:1521
- sqlserver:1433
1.6 网络通信协议
协议(TCP / IP)
TCP / IP(Transmission Control Protocol / Internet Protocol)的简写,中文名译为 传输控制协议 / 因特网互联协议,又叫网络通讯协议,这个协议是 Internet 最基本的协议,Internet 国际互联网的基础,简单地说,就是由网络层的 IP 协议和传输层的 TCP 协议组成的。
| OSI 模型 | TCP / IP 模型 | TCP / IP 模型各层对应协议 |
|---|---|---|
| 应用层 | 应用层 | HTTP、ftp、telnet、DNS…… |
| 表示层 | ||
| 会话层 | ||
| 传输层 | 传输层 | TCP、UDP…… |
| 网络层 | 网络层 | IP、ICMP、ARP…… |
| 数据链路层 | 物理 + 数据链路层 | Link |
| 物理层 |
1.7 TCP 和 UDP
TCP 协议:传输控制协议
- 使用 TCP 协议前,须先建立 TCP 连接,形成传输数据通道
- 传输前,采用“三次握手”方式,是 可靠的
- TCP 协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
举例:模拟三次握手,然后传输数据
汉奸:队长别开枪,是我
队长:原来是你小子,来干什么的?
汉奸:皇军让我给您捎句话
….然后是具体内容…
UDP 协议:用户数据协议
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据包的大小限制在 64K 以内,不适合传输大数据量
- 因无需连接,所以是不可靠的
- 发送数据结束时无需释放资源(因为不是面向连接的),速度快
举例:
汉奸跑到八路军营地前,
大喊一声:皇军让我给你们捎句话,别再做无谓的抵抗,赶快投降
喊完汉奸就赶紧跑了
二、InetAddress 类
2.1 相关方法
- 获取本机 InetAddress 对象,getLocalHost
- 根据指定主机名 / 域名 获取 ip 地址对象 getByName
- 获取 InetAddress 对象的主机名 getHostName
- 获取 InetAddress 对象的地址 getHostAddress
2.2 应用案例
编写代码,获取计算机的主机名和 IP 地址相关 API
package com.hspedu.api_;import java.net.InetAddress;import java.net.UnknownHostException;/*** @author HarborGao* @version 1.0*/public class API_ {public static void main(String[] args) throws UnknownHostException {//1. 获取本机的 InetAddress 对象InetAddress localHost = InetAddress.getLocalHost();System.out.println(localHost);//2. 根据指定的主机名,获取 InetAddress 对象InetAddress host1 = InetAddress.getByName("Harvin");System.out.println("host1=" + host1);//3. 根据域名返回 InetAddress对象 比如 www.baidu.com 对应的HostInetAddress host2 = InetAddress.getByName("www.baidu.com");System.out.println("host2=" + host2);//4. 通过 InetAddress 对象,获取对应的的地址String hostAddress = host2.getHostAddress();System.out.println("host2 对应的 ip=" + hostAddress);//5. 通过 InetAddress 对象,获取对应的主机名/或者是域名String hostName = host2.getHostName();System.out.println("host2 对应的主机名/域名 = " + hostName);}}
三、Socket
3.1 基本介绍
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准
- 通信的两端都要有 Socket,是两台机器间通信的端点
- 网络通信其实就是 Socket 间的通信
- Socket 允许程序把网络连接当成一个流,数据在两个 Socket 间通过 IO 传输
- 一般主动发起通信的应用程序属于客户端,等待通信请求的是服务端
3.2 示意图

四、TCP 网络通信编程
4.1 基本介绍
- 基于客户端 - 服务端的网络通信
- 底层使用的是 TCP / IP 协议
- 应用场景举例:客户端发送数据,服务端接收并显示在控制台
- 基于 Socket 的 TCP 编程

4.2 应用案例1(使用字节流)
- 编写一个服务器端,和一个客户端
- 服务器端在 9999 端口监听
- 客户端连接到服务器端,发送”hello, server”,然后退出
- 服务器端接收到 客户端发送的信息,输出,并退出 ```java package com.hspedu.socket;
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
- 服务端 接收客户端发送的信息,输出,并退出
*/
public class SocketTCP01Server {
public static void main(String[] args) throws IOException {
} }//1. 在本机的 9999端口监听,等待连接//细节说明:要求在本机没有其他服务在监听9999,即9999端口没有被占用// ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]ServerSocket serverSocket = new ServerSocket(9999);System.out.println("服务端,在9999端口监听,等待连接..");//2. 当没有客户端连接9999端口时,程序会处于阻塞状态,等待连接//如果由客户端连接,则会返回一个 Socket对象,程序继续Socket socket = serverSocket.accept();System.out.println("服务器端 socket = " + socket.getClass());//3. 通过socket.getInputStream() 读取客户端写入到数据通道的数据,输出显示InputStream inputStream = socket.getInputStream();//4. IO读取byte[] buf = new byte[1024];int readLen = 0;while ((readLen = inputStream.read(buf)) != -1) {System.out.println(new String(buf,0,readLen)); //根据读取到的实际长度显示内容}//5.关闭流和 socketinputStream.close();socket.close();serverSocket.close();
java package com.hspedu.socket;
import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
客户端,发送”hello,server”给服务端 */ public class SocketTCP01Client { public static void main(String[] args) throws IOException {
//1. 连接服务端 (ip, 端口)//解读:连接 InetAddress.getLocalHost()主机的 9999端口,如果连接成功,返回 socket 对象Socket socket = new Socket(InetAddress.getLocalHost(), 9999);System.out.println("客户端 socket = " + socket.getClass());//2. 连接上后,生成 socket ,通过socket.getOutputStream()// 得到 和 socket 对象关联的输出流对象OutputStream outputStream = socket.getOutputStream();//3. 通过输出流,写入数据到 数据通道outputStream.write("hello,server".getBytes());//4. 关闭流对象和 socketoutputStream.close();socket.close();System.out.println("客户端退出..");
} } ```
4.3 应用案例2 (使用字节流)
- 编写一个服务器端,和一个客户端
- 服务器端在 9999端口监听
- 客户端连接到服务器端,发送 “hello,server”,并接收服务器端发回的”hello,client”,再退出
- 服务器端接收 客户端发送的信息,输出,并发送”hello,client”,再退出 ```java package com.hspedu.socket;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
服务器端 */ public class SocketTCP02Server { public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9997);Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();byte[] buf = new byte[100];int readLen = 0;while ((readLen = inputStream.read(buf)) != -1) {System.out.print(new String(buf,0,readLen));}//设置结束标记,表示输入结束socket.shutdownInput();OutputStream outputStream = socket.getOutputStream();outputStream.write("hello,client".getBytes());socket.shutdownOutput();inputStream.close();outputStream.close();socket.close();serverSocket.close();
} }
java package com.hspedu.socket;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
客户端 */ public class SocketTCP02Client { public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9997);OutputStream outputStream = socket.getOutputStream();outputStream.write("hello.server".getBytes());//设置结束标记,表示输出结束socket.shutdownOutput();InputStream inputStream = socket.getInputStream();byte[] buf = new byte[100];int readLen = 0;while ((readLen = inputStream.read(buf)) != -1) {System.out.print(new String(buf,0,readLen));}socket.shutdownInput();outputStream.close();inputStream.close();socket.close();
} } ```
4.4 应用案例3 (使用字符流)
- 编写一个服务端,和一个客户端
- 服务端在9999端口监听
- 客户端连接到服务端,发送”hello, server”,并接收服务端回发的”hello,client”,再退出
- 服务端接收到客户端发送的信息,输出,并发送”hello, client”,再退出 ```java package com.hspedu.socket;
import java.io.*; import java.net.InetAddress; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
客户端 */ public class SocketTCP03Client { public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9997);OutputStream outputStream = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));writer.write("hello,server服务端");//也可以是使用 writer.newLine() 设置结束标记 注意要求对方使用readLine()接收writer.newLine();writer.flush();InputStream inputStream = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String s = reader.readLine();System.out.println(s);reader.close();writer.close();socket.close();
} }
java package com.hspedu.socket;
import java.io.*; import java.net.ServerSocket; import java.net.Socket;
/**
- @author HarborGao
- @version 1.0
服务器端 */ public class SocketTCP03Server { public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9997);Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String s = reader.readLine();System.out.println(s);OutputStream outputStream = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));writer.write("hello,client客户端");writer.newLine();writer.flush();reader.close();writer.close();socket.close();serverSocket.close();
} } ```
4.5 应用案例4
- 编写个服务端,和一个客户端
- 服务器端在8888端口监听
- 客户端连接到服务端,发送一张图片 e:\img.jpg
- 服务器端接收到客户端发送的图片,保存到src下,发送”收到图片”再退出
- 客户端接收到服务端发送的”收到图片”, 再退出
- 该程序要求使用StreamUtils.java ```java package com.hspedu.upload;
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;
/**
此类用于演示关于流的读写方法 / public class StreamUtils { /**
- 功能:将输入流转换成byte[]
- @param is
- @return
- @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];
int len;
while((len=is.read(b))!=-1){
} byte[] array = bos.toByteArray(); bos.close(); return array; } /**bos.write(b, 0, len);
- 功能:将InputStream转换成String
- @param is
- @return
@throws Exception */
public static String streamToString(InputStream is) throws Exception{ BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder builder= new StringBuilder(); String line; while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
builder.append(line+"\r\n");
} return builder.toString();
}
}
```javapackage com.hspedu.upload;import java.io.*;import java.net.ServerSocket;import java.net.Socket;/*** @author 韩顺平* @version 1.0* 文件上传的服务端*/public class TCPFileUploadServer {public static void main(String[] args) throws Exception {//1. 服务端在本机监听8888端口ServerSocket serverSocket = new ServerSocket(8888);System.out.println("服务端在8888端口监听....");//2. 等待连接Socket socket = serverSocket.accept();//3. 读取客户端发送的数据// 通过Socket得到输入流BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());byte[] bytes = StreamUtils.streamToByteArray(bis);//4. 将得到 bytes 数组,写入到指定的路径,就得到一个文件了String destFilePath = "src\\abc.mp4";BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));bos.write(bytes);bos.close();// 向客户端回复 "收到图片"// 通过socket 获取到输出流(字符)BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));writer.write("收到图片");writer.flush();//把内容刷新到数据通道socket.shutdownOutput();//设置写入结束标记//关闭其他资源writer.close();bis.close();socket.close();serverSocket.close();}}
package com.hspedu.upload;import java.io.*;import java.net.InetAddress;import java.net.Socket;/*** @author 韩顺平* @version 1.0* 文件上传的客户端*/public class TCPFileUploadClient {public static void main(String[] args) throws Exception {//客户端连接服务端 8888,得到Socket对象Socket socket = new Socket(InetAddress.getLocalHost(), 8888);//创建读取磁盘文件的输入流//String filePath = "e:\\qie.png";String filePath = "e:\\abc.mp4";BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));//bytes 就是filePath对应的字节数组byte[] bytes = StreamUtils.streamToByteArray(bis);//通过socket获取到输出流, 将bytes数据发送给服务端BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道bis.close();socket.shutdownOutput();//设置写入数据的结束标记//=====接收从服务端回复的消息=====InputStream inputStream = socket.getInputStream();//使用StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串String s = StreamUtils.streamToString(inputStream);System.out.println(s);//关闭相关的流inputStream.close();bos.close();socket.close();}}
4.6 netstat 指令
- netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an | more 可以分页显示
- 要求在 dos 控制台下执行
说明:
- Listening 表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息
- 可以输入 ctrl + c 退出指令
4.7 TCP网络通讯不为人知的秘密
- 当客户端连接到服务器后,实际上客户端也是通过一个端口和服务端进行通讯的,
这个端口是 TCP / IP 来分配的,是不确定的,随机的。 - 示意图

- 程序验证

五、 UDP 网络通信编程 [ 了解 ]
5.1 基本介绍
- 类 DatagramSocket 和 DatagramPacket[数据包/数据报] 实现了基于 UDP 协议网络程序
- UDP 数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证 UDP 数据报一定能够安全送到目的地,也不能确定什么时候能够送达
- DatagramPacket 对象封装了 UDP 数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方和接收方的连接

5.2 基本流程
- 核心的两个类/对象 DatagramSocket 与 DatagramPacket
- 建立发送端,接收端(没有服务端和客户端概念)
- 发送数据前,建立数据报/包 DatagramPacket 对象
- 调用 DatagramSocket 的发送、接收方法
- 关闭 DatagramSocket

5.3 应用案例
- 编写一个接收端 A,和一个发送端 B
- 接收端 A 在9999端口等待接收数据(receive)
- 发送端 B 向接收端 A 发送数据”hello,明天吃火锅~”
- 接收端 A 接收到 发送端 B 发送的数据,回复”好的,明天见”,再退出
- 发送端 接收回复的数据,再退出 ```java package com.hspedu.udp;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/**
- @author HarborGao
- @version 1.0
接收端 ==> 也可以变成发送端 */ public class UDPReceiverA { public static void main(String[] args) throws IOException {
//1. 创建一个 DatagramSocket 对象,准备在端口9999发送和接收数据DatagramSocket socket = new DatagramSocket(9999);//2. 构建一个 DatagramPacket 对象,准备接收数据byte[] buf = new byte[1024];DatagramPacket packet = new DatagramPacket(buf, buf.length);//3. 调用接收方法,将通过网络传输的 DatagramPacket 对象 填充到 packet 对象//细节提示:当有数据报发送到本机的9999端口,下面就会接收到,否则就会阻塞等待System.out.println("接收端A等待接收数据...");socket.receive(packet);//4. 可以把 packet 进行拆包,取出数据,并显示int length = packet.getLength(); //实际接收到的数据字节长度byte[] data = packet.getData();String s = new String(data,0,length);System.out.println(s);// ===回复===byte[] data2 = "好的,明天见".getBytes();packet = new DatagramPacket(data2, data2.length, InetAddress.getByName("192.168.0.182"),9998);socket.send(packet);//5.关闭 socket 端口socket.close();System.out.println("A端退出...");
} }
java package com.hspedu.udp;
import java.io.IOException; import java.net.*;
/**
- @author HarborGao
- @version 1.0
发送端 ==> 也可以变成接收端 */ public class UDPSenderB { public static void main(String[] args) throws IOException {
//1. 创建 DatagramSocket 对象,准备发送和接收数据DatagramSocket socket = new DatagramSocket(9998);//2. 将需要发送的数据,封装到 DatagramPacket 对象byte[] data = "hello,明天吃火锅~".getBytes();//说明:封装的DatagramPacket 由四部分组成:数据(字节数组),数据长度(大小 <= 64KB),接收端主机地址,接收端接收端口DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.182"),9999);socket.send(packet);// ===接收回复===byte[] buf = new byte[1024];packet = new DatagramPacket(buf, buf.length);System.out.println("接收端B等待接收数据...");socket.receive(packet);int length = packet.getLength(); //实际接收到的数据字节长度byte[] data2 = packet.getData();String s = new String(data2,0,length);System.out.println(s);//关闭资源socket.close();System.out.println("B端退出...");
} } ```
六、本章作业
- 编程题
Homework01Server.java Homework01Client.java com.hspedu.homework
- 使用字符流的方式,编写一个客户端程序和服务器端程序,
- 客户端发送”name”,服务器端接收到后,返回”我是nova”,nova是你自己的名字.
- 客户端发送”hobby”,服务器端接收到后,返回”编写java程序”
- 不是这两个问题,回复”你说啥呢” ```java package com.hspedu.homework;
import java.io.*; import java.net.ServerSocket; import java.net.Socket;
/**
- @author HarborGao
@version 1.0 */ public class Homework01Server { public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9999);System.out.println("等待接收数据");Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String s = reader.readLine();System.out.println(s);String feedback = null;switch (s) {case "name":feedback = "我是 nova";break;case "hobby":feedback = "编写Java程序";break;default:feedback = "你说啥呢";break;}OutputStream outputStream = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));writer.write(feedback);writer.newLine();writer.flush();reader.close();writer.close();socket.close();serverSocket.close();
} }
java package com.hspedu.homework;
import java.io.*; import java.net.InetAddress; import java.net.Socket;
/**
- @author HarborGao
@version 1.0 */ @SuppressWarnings({“all”}) public class Homework01Client { public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9999);OutputStream outputStream = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));writer.write("name");//writer.write("hobby");//writer.write("es");writer.newLine();writer.flush();InputStream inputStream = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String s = reader.readLine();System.out.println(s);writer.close();reader.close();socket.close();
} } ```
- 编程题
Homework02ReceiverA.java Homework02SenderB.java com.hspedu.homework
- 编写一个接收端A,和一个发送端B,使用UDP协议完成
- 接收端在8888端口等待接收数据(receive)
- 发送端向接收端发送数据”四大名著是哪些”
- 接收端接收到发送端发送的问题后,返回”四大名著是《红楼梦》…” 否则返回 what?
- 接收端和发送端程序退出 ```java package com.hspedu.homework;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/**
- @author HarborGao
@version 1.0 */ public class Homework02ReceiverA { public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8888);byte[] buf = new byte[1024];DatagramPacket packet = new DatagramPacket(buf, buf.length);System.out.println("等待接收...");socket.receive(packet);int length = packet.getLength();byte[] data = packet.getData();String s = new String(data,0,length);System.out.println(s);if ("四大名著是哪些".equals(s)) {data = "四大名著是《红楼梦》,《三国演义》,《水浒传》,《西游记》".getBytes();} else {data = "what?".getBytes();}packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),8887);socket.send(packet);socket.close();
} }
java package com.hspedu.homework;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/**
- @author HarborGao
@version 1.0 */ public class Homework02SenderB { public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8887);byte[] data = "四大名著是哪些".getBytes();data = "???".getBytes();DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),8888);socket.send(packet);byte[] buf = new byte[1024];packet = new DatagramPacket(buf, buf.length);socket.receive(packet);int length = packet.getLength();data = packet.getData();String s = new String(data,0,length);System.out.println(s);socket.close();
} } ```
- 编程题
Homework03Server.java Homework03Client.java
- 编写客户端程序和服务器端程序
- 客户端可以输入一个音乐文件名,比如 高山流水,服务端收到音乐名后,可以给客户端返回这个音乐文件,如果服务器没有这个文件,返回一个默认的音乐即可.
- 客户端收到文件后,保存到本地 e:\
- 提示:该程序可以使用 StreamUtils.java
本质:其实就是指定下载文件的应用,先自己结合前面讲的文件上传来做.
package com.hspedu.homework;import java.io.*;import java.net.ServerSocket;import java.net.Socket;/*** @author HarborGao* @version 1.0*/public class Homework03Server {public static void main(String[] args) throws Exception {ServerSocket serverSocket = new ServerSocket(7777); //开通服务器端监听端口System.out.println("等待接收信息...");Socket socket = serverSocket.accept(); //监听接入的端口//接收其他用户发送来的请求信息InputStream inputStream = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); //用字符流读入String s = reader.readLine(); //读入数据System.out.println("接收到请求的歌名是 " + s);//根据用户请求选择相应的 mp3文件String filePath = "src\\无名.mp3"; //初始化服务器上的本地文件,默认是 无名.mp3if ("高山流水".equals(s)) {filePath = "src\\高山流水.mp3"; //如果请求的是高山流水,就将文件地址指向 高山流水.mp3,否则保持默认}BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); //读入本地文件byte[] data = StreamUtils.streamToByteArray(bis); //将文件保存到 data[]//发送文件OutputStream outputStream = socket.getOutputStream();BufferedOutputStream bos = new BufferedOutputStream(outputStream);bos.write(data);socket.shutdownOutput(); //结束标识//关闭相关接口reader.close();bis.close();bos.close();socket.close();serverSocket.close();System.out.println("服务器端关闭.");}}
package com.hspedu.homework;import java.io.*;import java.net.InetAddress;import java.net.Socket;import java.util.Scanner;/*** @author HarborGao* @version 1.0*/public class Homework03Client {public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);//连接服务器端Socket socket = new Socket(InetAddress.getLocalHost(),7777);//发送请求OutputStream outputStream = socket.getOutputStream();BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));System.out.println("请输入要下载的文件名: ");String musicName = scanner.next();writer.write(musicName);writer.newLine();writer.flush();//接收文件InputStream inputStream = socket.getInputStream();BufferedInputStream bis = new BufferedInputStream(inputStream);byte[] data = StreamUtils.streamToByteArray(bis);//将文件保存到本地String filePath = "e:\\" + musicName + ".mp3";BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));bos.write(data);writer.close();bis.close();bos.close();socket.close();System.out.println("客户端关闭");}}
学习参考(致谢):
- B站 @程序员鱼皮 Java学习一条龙
- B站 @韩顺平 零基础30天学会Java
