一、网络的相关概念

1.1 网络通信

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

image.png

1.2 网络

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

image.png

1.3 IP 地址

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

1.4 IPv4 地址分类

image.png
image.png

1.5 域名和端口号

域名:

  1. 形如:www.baidu.com
  2. 好处:为了方便记忆,解决记 ip 的困难
  3. 概念:将 ip 地址映射成域名,这里怎么映射上,HTTP 协议

端口号:

  1. 概念:用于标识计算机上某个特定的网络程序
  2. 表示形式:以整数形式,端口号 0 ~ 65535 [ 2个字节表示端口 0 ~2^16 - 1 ]
  3. 0 ~ 1024 已经被占用,比如 ssh 22, ftp 21,smtp 25,http 80
  4. 常见的网络程序端口号:
    1. tomcat:8080
    2. mysql:3306
    3. oracle:1521
    4. sqlserver:1433

1.6 网络通信协议

协议(TCP / IP)
TCP / IP(Transmission Control Protocol / Internet Protocol)的简写,中文名译为 传输控制协议 / 因特网互联协议,又叫网络通讯协议,这个协议是 Internet 最基本的协议,Internet 国际互联网的基础,简单地说,就是由网络层的 IP 协议和传输层的 TCP 协议组成的。
image.png

OSI 模型 TCP / IP 模型 TCP / IP 模型各层对应协议
应用层 应用层 HTTP、ftp、telnet、DNS……
表示层
会话层
传输层 传输层 TCP、UDP……
网络层 网络层 IP、ICMP、ARP……
数据链路层 物理 + 数据链路层 Link
物理层

1.7 TCP 和 UDP

TCP 协议:传输控制协议

  1. 使用 TCP 协议前,须先建立 TCP 连接,形成传输数据通道
  2. 传输前,采用“三次握手”方式,是 可靠的
  3. TCP 协议进行通信的两个应用进程:客户端、服务端
  4. 在连接中可进行大数据量的传输
  5. 传输完毕,需释放已建立的连接,效率低

举例:模拟三次握手,然后传输数据
汉奸:队长别开枪,是我
队长:原来是你小子,来干什么的?
汉奸:皇军让我给您捎句话
….然后是具体内容…

UDP 协议:用户数据协议

  1. 将数据、源、目的封装成数据包,不需要建立连接
  2. 每个数据包的大小限制在 64K 以内,不适合传输大数据量
  3. 因无需连接,所以是不可靠的
  4. 发送数据结束时无需释放资源(因为不是面向连接的),速度快

举例:
汉奸跑到八路军营地前,
大喊一声:皇军让我给你们捎句话,别再做无谓的抵抗,赶快投降
喊完汉奸就赶紧跑了

二、InetAddress 类

2.1 相关方法

  1. 获取本机 InetAddress 对象,getLocalHost
  2. 根据指定主机名 / 域名 获取 ip 地址对象 getByName
  3. 获取 InetAddress 对象的主机名 getHostName
  4. 获取 InetAddress 对象的地址 getHostAddress

2.2 应用案例

编写代码,获取计算机的主机名和 IP 地址相关 API

  1. package com.hspedu.api_;
  2. import java.net.InetAddress;
  3. import java.net.UnknownHostException;
  4. /**
  5. * @author HarborGao
  6. * @version 1.0
  7. */
  8. public class API_ {
  9. public static void main(String[] args) throws UnknownHostException {
  10. //1. 获取本机的 InetAddress 对象
  11. InetAddress localHost = InetAddress.getLocalHost();
  12. System.out.println(localHost);
  13. //2. 根据指定的主机名,获取 InetAddress 对象
  14. InetAddress host1 = InetAddress.getByName("Harvin");
  15. System.out.println("host1=" + host1);
  16. //3. 根据域名返回 InetAddress对象 比如 www.baidu.com 对应的Host
  17. InetAddress host2 = InetAddress.getByName("www.baidu.com");
  18. System.out.println("host2=" + host2);
  19. //4. 通过 InetAddress 对象,获取对应的的地址
  20. String hostAddress = host2.getHostAddress();
  21. System.out.println("host2 对应的 ip=" + hostAddress);
  22. //5. 通过 InetAddress 对象,获取对应的主机名/或者是域名
  23. String hostName = host2.getHostName();
  24. System.out.println("host2 对应的主机名/域名 = " + hostName);
  25. }
  26. }

三、Socket

3.1 基本介绍

  1. 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准
  2. 通信的两端都要有 Socket,是两台机器间通信的端点
  3. 网络通信其实就是 Socket 间的通信
  4. Socket 允许程序把网络连接当成一个流,数据在两个 Socket 间通过 IO 传输
  5. 一般主动发起通信的应用程序属于客户端,等待通信请求的是服务端

3.2 示意图

image.png

四、TCP 网络通信编程

4.1 基本介绍

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

image.png

4.2 应用案例1(使用字节流)

  1. 编写一个服务器端,和一个客户端
  2. 服务器端在 9999 端口监听
  3. 客户端连接到服务器端,发送”hello, server”,然后退出
  4. 服务器端接收到 客户端发送的信息,输出,并退出 ```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. //1. 在本机的 9999端口监听,等待连接
    2. //细节说明:要求在本机没有其他服务在监听9999,即9999端口没有被占用
    3. // ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]
    4. ServerSocket serverSocket = new ServerSocket(9999);
    5. System.out.println("服务端,在9999端口监听,等待连接..");
    6. //2. 当没有客户端连接9999端口时,程序会处于阻塞状态,等待连接
    7. //如果由客户端连接,则会返回一个 Socket对象,程序继续
    8. Socket socket = serverSocket.accept();
    9. System.out.println("服务器端 socket = " + socket.getClass());
    10. //3. 通过socket.getInputStream() 读取客户端写入到数据通道的数据,输出显示
    11. InputStream inputStream = socket.getInputStream();
    12. //4. IO读取
    13. byte[] buf = new byte[1024];
    14. int readLen = 0;
    15. while ((readLen = inputStream.read(buf)) != -1) {
    16. System.out.println(new String(buf,0,readLen)); //根据读取到的实际长度显示内容
    17. }
    18. //5.关闭流和 socket
    19. inputStream.close();
    20. socket.close();
    21. 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. //1. 连接服务端 (ip, 端口)
    2. //解读:连接 InetAddress.getLocalHost()主机的 9999端口,如果连接成功,返回 socket 对象
    3. Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
    4. System.out.println("客户端 socket = " + socket.getClass());
    5. //2. 连接上后,生成 socket ,通过socket.getOutputStream()
    6. // 得到 和 socket 对象关联的输出流对象
    7. OutputStream outputStream = socket.getOutputStream();
    8. //3. 通过输出流,写入数据到 数据通道
    9. outputStream.write("hello,server".getBytes());
    10. //4. 关闭流对象和 socket
    11. outputStream.close();
    12. socket.close();
    13. System.out.println("客户端退出..");

    } } ```

4.3 应用案例2 (使用字节流)

  1. 编写一个服务器端,和一个客户端
  2. 服务器端在 9999端口监听
  3. 客户端连接到服务器端,发送 “hello,server”,并接收服务器端发回的”hello,client”,再退出
  4. 服务器端接收 客户端发送的信息,输出,并发送”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 {

    1. ServerSocket serverSocket = new ServerSocket(9997);
    2. Socket socket = serverSocket.accept();
    3. InputStream inputStream = socket.getInputStream();
    4. byte[] buf = new byte[100];
    5. int readLen = 0;
    6. while ((readLen = inputStream.read(buf)) != -1) {
    7. System.out.print(new String(buf,0,readLen));
    8. }
    9. //设置结束标记,表示输入结束
    10. socket.shutdownInput();
    11. OutputStream outputStream = socket.getOutputStream();
    12. outputStream.write("hello,client".getBytes());
    13. socket.shutdownOutput();
    14. inputStream.close();
    15. outputStream.close();
    16. socket.close();
    17. 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 {

    1. Socket socket = new Socket(InetAddress.getLocalHost(),9997);
    2. OutputStream outputStream = socket.getOutputStream();
    3. outputStream.write("hello.server".getBytes());
    4. //设置结束标记,表示输出结束
    5. socket.shutdownOutput();
    6. InputStream inputStream = socket.getInputStream();
    7. byte[] buf = new byte[100];
    8. int readLen = 0;
    9. while ((readLen = inputStream.read(buf)) != -1) {
    10. System.out.print(new String(buf,0,readLen));
    11. }
    12. socket.shutdownInput();
    13. outputStream.close();
    14. inputStream.close();
    15. socket.close();

    } } ```

4.4 应用案例3 (使用字符流)

  1. 编写一个服务端,和一个客户端
  2. 服务端在9999端口监听
  3. 客户端连接到服务端,发送”hello, server”,并接收服务端回发的”hello,client”,再退出
  4. 服务端接收到客户端发送的信息,输出,并发送”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 {

    1. Socket socket = new Socket(InetAddress.getLocalHost(),9997);
    2. OutputStream outputStream = socket.getOutputStream();
    3. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
    4. writer.write("hello,server服务端");
    5. //也可以是使用 writer.newLine() 设置结束标记 注意要求对方使用readLine()接收
    6. writer.newLine();
    7. writer.flush();
    8. InputStream inputStream = socket.getInputStream();
    9. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    10. String s = reader.readLine();
    11. System.out.println(s);
    12. reader.close();
    13. writer.close();
    14. 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 {

    1. ServerSocket serverSocket = new ServerSocket(9997);
    2. Socket socket = serverSocket.accept();
    3. InputStream inputStream = socket.getInputStream();
    4. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    5. String s = reader.readLine();
    6. System.out.println(s);
    7. OutputStream outputStream = socket.getOutputStream();
    8. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
    9. writer.write("hello,client客户端");
    10. writer.newLine();
    11. writer.flush();
    12. reader.close();
    13. writer.close();
    14. socket.close();
    15. serverSocket.close();

    } } ```

4.5 应用案例4

  1. 编写个服务端,和一个客户端
  2. 服务器端在8888端口监听
  3. 客户端连接到服务端,发送一张图片 e:\img.jpg
  4. 服务器端接收到客户端发送的图片,保存到src下,发送”收到图片”再退出
  5. 客户端接收到服务端发送的”收到图片”, 再退出
  6. 该程序要求使用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){
      1. bos.write(b, 0, len);
      } byte[] array = bos.toByteArray(); bos.close(); return array; } /**
    • 功能:将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时,就表示结束

      1. builder.append(line+"\r\n");

      } return builder.toString();

      }

}

  1. ```java
  2. package com.hspedu.upload;
  3. import java.io.*;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6. /**
  7. * @author 韩顺平
  8. * @version 1.0
  9. * 文件上传的服务端
  10. */
  11. public class TCPFileUploadServer {
  12. public static void main(String[] args) throws Exception {
  13. //1. 服务端在本机监听8888端口
  14. ServerSocket serverSocket = new ServerSocket(8888);
  15. System.out.println("服务端在8888端口监听....");
  16. //2. 等待连接
  17. Socket socket = serverSocket.accept();
  18. //3. 读取客户端发送的数据
  19. // 通过Socket得到输入流
  20. BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
  21. byte[] bytes = StreamUtils.streamToByteArray(bis);
  22. //4. 将得到 bytes 数组,写入到指定的路径,就得到一个文件了
  23. String destFilePath = "src\\abc.mp4";
  24. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
  25. bos.write(bytes);
  26. bos.close();
  27. // 向客户端回复 "收到图片"
  28. // 通过socket 获取到输出流(字符)
  29. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
  30. writer.write("收到图片");
  31. writer.flush();//把内容刷新到数据通道
  32. socket.shutdownOutput();//设置写入结束标记
  33. //关闭其他资源
  34. writer.close();
  35. bis.close();
  36. socket.close();
  37. serverSocket.close();
  38. }
  39. }
  1. package com.hspedu.upload;
  2. import java.io.*;
  3. import java.net.InetAddress;
  4. import java.net.Socket;
  5. /**
  6. * @author 韩顺平
  7. * @version 1.0
  8. * 文件上传的客户端
  9. */
  10. public class TCPFileUploadClient {
  11. public static void main(String[] args) throws Exception {
  12. //客户端连接服务端 8888,得到Socket对象
  13. Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
  14. //创建读取磁盘文件的输入流
  15. //String filePath = "e:\\qie.png";
  16. String filePath = "e:\\abc.mp4";
  17. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
  18. //bytes 就是filePath对应的字节数组
  19. byte[] bytes = StreamUtils.streamToByteArray(bis);
  20. //通过socket获取到输出流, 将bytes数据发送给服务端
  21. BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
  22. bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道
  23. bis.close();
  24. socket.shutdownOutput();//设置写入数据的结束标记
  25. //=====接收从服务端回复的消息=====
  26. InputStream inputStream = socket.getInputStream();
  27. //使用StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串
  28. String s = StreamUtils.streamToString(inputStream);
  29. System.out.println(s);
  30. //关闭相关的流
  31. inputStream.close();
  32. bos.close();
  33. socket.close();
  34. }
  35. }

4.6 netstat 指令

  1. netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
  2. netstat -an | more 可以分页显示
  3. 要求在 dos 控制台下执行

说明:

  1. Listening 表示某个端口在监听
  2. 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息
  3. 可以输入 ctrl + c 退出指令

4.7 TCP网络通讯不为人知的秘密

  1. 当客户端连接到服务器后,实际上客户端也是通过一个端口和服务端进行通讯的,
    这个端口是 TCP / IP 来分配的,是不确定的,随机的。
  2. 示意图
    image.png
  3. 程序验证
    image.png

五、 UDP 网络通信编程 [ 了解 ]

5.1 基本介绍

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

image.png

5.2 基本流程

  1. 核心的两个类/对象 DatagramSocket 与 DatagramPacket
  2. 建立发送端,接收端(没有服务端和客户端概念)
  3. 发送数据前,建立数据报/包 DatagramPacket 对象
  4. 调用 DatagramSocket 的发送、接收方法
  5. 关闭 DatagramSocket

image.png

5.3 应用案例

  1. 编写一个接收端 A,和一个发送端 B
  2. 接收端 A 在9999端口等待接收数据(receive)
  3. 发送端 B 向接收端 A 发送数据”hello,明天吃火锅~”
  4. 接收端 A 接收到 发送端 B 发送的数据,回复”好的,明天见”,再退出
  5. 发送端 接收回复的数据,再退出 ```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. //1. 创建一个 DatagramSocket 对象,准备在端口9999发送和接收数据
    2. DatagramSocket socket = new DatagramSocket(9999);
    3. //2. 构建一个 DatagramPacket 对象,准备接收数据
    4. byte[] buf = new byte[1024];
    5. DatagramPacket packet = new DatagramPacket(buf, buf.length);
    6. //3. 调用接收方法,将通过网络传输的 DatagramPacket 对象 填充到 packet 对象
    7. //细节提示:当有数据报发送到本机的9999端口,下面就会接收到,否则就会阻塞等待
    8. System.out.println("接收端A等待接收数据...");
    9. socket.receive(packet);
    10. //4. 可以把 packet 进行拆包,取出数据,并显示
    11. int length = packet.getLength(); //实际接收到的数据字节长度
    12. byte[] data = packet.getData();
    13. String s = new String(data,0,length);
    14. System.out.println(s);
    15. // ===回复===
    16. byte[] data2 = "好的,明天见".getBytes();
    17. packet = new DatagramPacket(data2, data2.length, InetAddress.getByName("192.168.0.182"),9998);
    18. socket.send(packet);
    19. //5.关闭 socket 端口
    20. socket.close();
    21. 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. //1. 创建 DatagramSocket 对象,准备发送和接收数据
    2. DatagramSocket socket = new DatagramSocket(9998);
    3. //2. 将需要发送的数据,封装到 DatagramPacket 对象
    4. byte[] data = "hello,明天吃火锅~".getBytes();
    5. //说明:封装的DatagramPacket 由四部分组成:数据(字节数组),数据长度(大小 <= 64KB),接收端主机地址,接收端接收端口
    6. DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.182"),9999);
    7. socket.send(packet);
    8. // ===接收回复===
    9. byte[] buf = new byte[1024];
    10. packet = new DatagramPacket(buf, buf.length);
    11. System.out.println("接收端B等待接收数据...");
    12. socket.receive(packet);
    13. int length = packet.getLength(); //实际接收到的数据字节长度
    14. byte[] data2 = packet.getData();
    15. String s = new String(data2,0,length);
    16. System.out.println(s);
    17. //关闭资源
    18. socket.close();
    19. System.out.println("B端退出...");

    } } ```

六、本章作业

  1. 编程题

Homework01Server.java Homework01Client.java com.hspedu.homework

  1. 使用字符流的方式,编写一个客户端程序和服务器端程序,
  2. 客户端发送”name”,服务器端接收到后,返回”我是nova”,nova是你自己的名字.
  3. 客户端发送”hobby”,服务器端接收到后,返回”编写java程序”
  4. 不是这两个问题,回复”你说啥呢” ```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 {

    1. ServerSocket serverSocket = new ServerSocket(9999);
    2. System.out.println("等待接收数据");
    3. Socket socket = serverSocket.accept();
    4. InputStream inputStream = socket.getInputStream();
    5. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    6. String s = reader.readLine();
    7. System.out.println(s);
    8. String feedback = null;
    9. switch (s) {
    10. case "name":
    11. feedback = "我是 nova";
    12. break;
    13. case "hobby":
    14. feedback = "编写Java程序";
    15. break;
    16. default:
    17. feedback = "你说啥呢";
    18. break;
    19. }
    20. OutputStream outputStream = socket.getOutputStream();
    21. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
    22. writer.write(feedback);
    23. writer.newLine();
    24. writer.flush();
    25. reader.close();
    26. writer.close();
    27. socket.close();
    28. 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 {

    1. Socket socket = new Socket(InetAddress.getLocalHost(),9999);
    2. OutputStream outputStream = socket.getOutputStream();
    3. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
    4. writer.write("name");
    5. //writer.write("hobby");
    6. //writer.write("es");
    7. writer.newLine();
    8. writer.flush();
    9. InputStream inputStream = socket.getInputStream();
    10. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    11. String s = reader.readLine();
    12. System.out.println(s);
    13. writer.close();
    14. reader.close();
    15. socket.close();

    } } ```

  1. 编程题

Homework02ReceiverA.java Homework02SenderB.java com.hspedu.homework

  1. 编写一个接收端A,和一个发送端B,使用UDP协议完成
  2. 接收端在8888端口等待接收数据(receive)
  3. 发送端向接收端发送数据”四大名著是哪些”
  4. 接收端接收到发送端发送的问题后,返回”四大名著是《红楼梦》…” 否则返回 what?
  5. 接收端和发送端程序退出 ```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 {

    1. DatagramSocket socket = new DatagramSocket(8888);
    2. byte[] buf = new byte[1024];
    3. DatagramPacket packet = new DatagramPacket(buf, buf.length);
    4. System.out.println("等待接收...");
    5. socket.receive(packet);
    6. int length = packet.getLength();
    7. byte[] data = packet.getData();
    8. String s = new String(data,0,length);
    9. System.out.println(s);
    10. if ("四大名著是哪些".equals(s)) {
    11. data = "四大名著是《红楼梦》,《三国演义》,《水浒传》,《西游记》".getBytes();
    12. } else {
    13. data = "what?".getBytes();
    14. }
    15. packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),8887);
    16. socket.send(packet);
    17. 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 {

    1. DatagramSocket socket = new DatagramSocket(8887);
    2. byte[] data = "四大名著是哪些".getBytes();
    3. data = "???".getBytes();
    4. DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),8888);
    5. socket.send(packet);
    6. byte[] buf = new byte[1024];
    7. packet = new DatagramPacket(buf, buf.length);
    8. socket.receive(packet);
    9. int length = packet.getLength();
    10. data = packet.getData();
    11. String s = new String(data,0,length);
    12. System.out.println(s);
    13. socket.close();

    } } ```

  1. 编程题

Homework03Server.java Homework03Client.java

  1. 编写客户端程序和服务器端程序
  2. 客户端可以输入一个音乐文件名,比如 高山流水,服务端收到音乐名后,可以给客户端返回这个音乐文件,如果服务器没有这个文件,返回一个默认的音乐即可.
  3. 客户端收到文件后,保存到本地 e:\
  4. 提示:该程序可以使用 StreamUtils.java

本质:其实就是指定下载文件的应用,先自己结合前面讲的文件上传来做.

  1. package com.hspedu.homework;
  2. import java.io.*;
  3. import java.net.ServerSocket;
  4. import java.net.Socket;
  5. /**
  6. * @author HarborGao
  7. * @version 1.0
  8. */
  9. public class Homework03Server {
  10. public static void main(String[] args) throws Exception {
  11. ServerSocket serverSocket = new ServerSocket(7777); //开通服务器端监听端口
  12. System.out.println("等待接收信息...");
  13. Socket socket = serverSocket.accept(); //监听接入的端口
  14. //接收其他用户发送来的请求信息
  15. InputStream inputStream = socket.getInputStream();
  16. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); //用字符流读入
  17. String s = reader.readLine(); //读入数据
  18. System.out.println("接收到请求的歌名是 " + s);
  19. //根据用户请求选择相应的 mp3文件
  20. String filePath = "src\\无名.mp3"; //初始化服务器上的本地文件,默认是 无名.mp3
  21. if ("高山流水".equals(s)) {
  22. filePath = "src\\高山流水.mp3"; //如果请求的是高山流水,就将文件地址指向 高山流水.mp3,否则保持默认
  23. }
  24. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); //读入本地文件
  25. byte[] data = StreamUtils.streamToByteArray(bis); //将文件保存到 data[]
  26. //发送文件
  27. OutputStream outputStream = socket.getOutputStream();
  28. BufferedOutputStream bos = new BufferedOutputStream(outputStream);
  29. bos.write(data);
  30. socket.shutdownOutput(); //结束标识
  31. //关闭相关接口
  32. reader.close();
  33. bis.close();
  34. bos.close();
  35. socket.close();
  36. serverSocket.close();
  37. System.out.println("服务器端关闭.");
  38. }
  39. }
  1. package com.hspedu.homework;
  2. import java.io.*;
  3. import java.net.InetAddress;
  4. import java.net.Socket;
  5. import java.util.Scanner;
  6. /**
  7. * @author HarborGao
  8. * @version 1.0
  9. */
  10. public class Homework03Client {
  11. public static void main(String[] args) throws Exception {
  12. Scanner scanner = new Scanner(System.in);
  13. //连接服务器端
  14. Socket socket = new Socket(InetAddress.getLocalHost(),7777);
  15. //发送请求
  16. OutputStream outputStream = socket.getOutputStream();
  17. BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
  18. System.out.println("请输入要下载的文件名: ");
  19. String musicName = scanner.next();
  20. writer.write(musicName);
  21. writer.newLine();
  22. writer.flush();
  23. //接收文件
  24. InputStream inputStream = socket.getInputStream();
  25. BufferedInputStream bis = new BufferedInputStream(inputStream);
  26. byte[] data = StreamUtils.streamToByteArray(bis);
  27. //将文件保存到本地
  28. String filePath = "e:\\" + musicName + ".mp3";
  29. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
  30. bos.write(data);
  31. writer.close();
  32. bis.close();
  33. bos.close();
  34. socket.close();
  35. System.out.println("客户端关闭");
  36. }
  37. }

学习参考(致谢):

  1. B站 @程序员鱼皮 Java学习一条龙
  2. B站 @韩顺平 零基础30天学会Java