网络编程

一、TCP和UDP

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

    1. 将数据、源、目的封装成数据包,不需要建立连接
    2. 每个数据包大小64k内,不适合传输大量数据
    3. 无需连接,不可靠
    4. 无需释放资源,速度快

      二、InetAddress类

      获取本机InetAddress对象 getLocalHost
      根据指定主机名/域名获取ip地址对象 getByName
      获取InetAddress对象的主机名 getHostName
      获取InetAddress对象的地址 getHostAddress

      1. public class InetAddress1 {
      2. public static void main(String[] args) throws UnknownHostException {
      3. // 获取本机的InetAddress对象
      4. InetAddress localHost = InetAddress.getLocalHost();
      5. System.out.println(localHost); // 输出设备名称/ip地址
      6. // 根据主机名获得InetAddress对象
      7. InetAddress byName = InetAddress.getByName("DESKTOP-I48QCK0");
      8. System.out.println(byName); // 输出设备名称/ip地址
      9. // 根据域名返回InetAddress对象
      10. InetAddress byName1 = InetAddress.getByName("www.baidu.com");
      11. System.out.println(byName1); // www.baidu.com/112.80.248.76
      12. // 通过InetAddress对象获取对应的地址
      13. String hostAddress = byName1.getHostAddress();
      14. System.out.println(hostAddress); // 182.61.200.6
      15. // 通过InetAddress对象获得主机名/域名
      16. String hostName = byName1.getHostName();
      17. System.out.println(hostName); // www.baidu.com
      18. }
      19. }

      三、Socket(套接字)

      通信的两端都要有Socket,是两台机器间通信的断电
      网络通信是Socket间的通信,Socket允许程序把网络当成一个流,数据在两个Socket间通过IO传输

      四、TCP网络编程

      4.1 使用字节流

      1. public class SocketTCP01Server {
      2. public static void main(String[] args) throws IOException {
      3. // 1. 9999端口监听,等待连接
      4. // ServerSocket可以通过accept()返回多个Socket,多个客户端连接 并发
      5. ServerSocket serverSocket = new ServerSocket(9999); // 前提是端口没被占用
      6. // 2. 没有客户端连接该端口,程序阻塞,等待连接;有客户端连接,返回socket对象继续执行
      7. Socket socket = serverSocket.accept();
      8. // 3. 通过socket.getInputStream()读取客户端写入到数据通道的数据
      9. InputStream inputStream = socket.getInputStream();
      10. // 4. 读取
      11. byte[] bytes = new byte[1024];
      12. int readLen = 0;
      13. while ((readLen = inputStream.read(bytes)) != -1) {
      14. System.out.println(new String(bytes,0, readLen));
      15. }
      16. // 5. 关闭流
      17. inputStream.close();
      18. socket.close();
      19. serverSocket.close();
      20. }
      21. }
      1. public class SocketTCP01Client {
      2. public static void main(String[] args) throws IOException {
      3. // 连接服务器 连接成功 返回socket对象
      4. Socket socket = new Socket(InetAddress.getLocalHost(),9999);
      5. // socket.getOutputStream()得到和socket对象关联的输出流对象
      6. OutputStream outputStream = socket.getOutputStream();
      7. // 通过输出流,写入数据到数据通道
      8. outputStream.write("hello".getBytes(StandardCharsets.UTF_8));
      9. // 关闭流对象和socket
      10. outputStream.close();
      11. socket.close();
      12. System.out.println("客户端关闭");
      13. }
      14. }
  • 客户端发送,并接收服务端;服务端接收,并发送

    1. public class SocketTCP02Server {
    2. public static void main(String[] args) throws IOException {
    3. // 1. 9999端口监听,等待连接
    4. // ServerSocket可以通过accept()返回多个Socket,多个客户端连接 并发
    5. ServerSocket serverSocket = new ServerSocket(9999); // 前提是端口没被占用
    6. // 2. 没有客户端连接该端口,程序阻塞,等待连接;有客户端连接,返回socket对象继续执行
    7. Socket socket = serverSocket.accept();
    8. // 3. 通过socket.getInputStream()读取客户端写入到数据通道的数据
    9. InputStream inputStream = socket.getInputStream();
    10. // 4. 读取
    11. byte[] bytes = new byte[1024];
    12. int readLen = 0;
    13. while ((readLen = inputStream.read(bytes)) != -1) {
    14. System.out.println(new String(bytes,0, readLen));
    15. }
    16. // 5. 获取socket相关联的输出流
    17. OutputStream outputStream = socket.getOutputStream();
    18. outputStream.write("hello,client".getBytes(StandardCharsets.UTF_8));
    19. // 设置结束标记
    20. socket.shutdownOutput();
    21. // 6. 关闭流
    22. outputStream.close();
    23. inputStream.close();
    24. socket.close();
    25. serverSocket.close();
    26. }
    27. }
    1. public class SocketTCP02Client {
    2. public static void main(String[] args) throws IOException {
    3. // 连接服务器 连接成功 返回socket对象
    4. Socket socket = new Socket(InetAddress.getLocalHost(),9999);
    5. // socket.getOutputStream()得到和socket对象关联的输出流对象
    6. OutputStream outputStream = socket.getOutputStream();
    7. // 通过输出流,写入数据到数据通道
    8. outputStream.write("hello".getBytes(StandardCharsets.UTF_8));
    9. // 设置结束标记
    10. socket.shutdownOutput();
    11. // 获取和socket关联的输入流,读取数据(字节)并显示
    12. InputStream inputStream = socket.getInputStream();
    13. byte[] bytes = new byte[1024];
    14. int readLen = 0;
    15. while ((readLen = inputStream.read(bytes)) != -1) {
    16. System.out.println(new String(bytes, 0, readLen));
    17. }
    18. // 关闭流对象和socket
    19. inputStream.close();
    20. outputStream.close();
    21. socket.close();
    22. System.out.println("客户端关闭");
    23. }
    24. }

    4.2 使用字符流

    1. public class SocketTCP03Server {
    2. public static void main(String[] args) throws IOException {
    3. // 1. 9999端口监听,等待连接
    4. // ServerSocket可以通过accept()返回多个Socket,多个客户端连接 并发
    5. ServerSocket serverSocket = new ServerSocket(9999); // 前提是端口没被占用
    6. // 2. 没有客户端连接该端口,程序阻塞,等待连接;有客户端连接,返回socket对象继续执行
    7. Socket socket = serverSocket.accept();
    8. // 3. 通过socket.getInputStream()读取客户端写入到数据通道的数据
    9. InputStream inputStream = socket.getInputStream();
    10. // 4. 读取
    11. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    12. String s = bufferedReader.readLine();
    13. System.out.println(s);
    14. // 5. 获取socket相关联的输出流
    15. OutputStream outputStream = socket.getOutputStream();
    16. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
    17. bufferedWriter.write("hello,client");
    18. bufferedWriter.newLine(); // 换行符表示结束
    19. bufferedWriter.flush(); // 刷新
    20. // 6. 关闭流
    21. bufferedReader.close(); // 关闭外层流
    22. bufferedWriter.close();
    23. socket.close();
    24. serverSocket.close();
    25. }
    26. }
    1. // 字符流
    2. public class SocketTCP03Client {
    3. public static void main(String[] args) throws IOException {
    4. // 连接服务器 连接成功 返回socket对象
    5. Socket socket = new Socket(InetAddress.getLocalHost(),9999);
    6. // socket.getOutputStream()得到和socket对象关联的输出流对象
    7. OutputStream outputStream = socket.getOutputStream();
    8. // 通过输出流,写入数据到数据通道
    9. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
    10. bufferedWriter.write("hello,server");
    11. bufferedWriter.newLine(); // 插入一个换行符,表示写入的内容结束 此时服务端要用readLine()读
    12. bufferedWriter.flush(); // 字符流要手动刷新
    13. // 设置写入结束标记
    14. socket.shutdownOutput();
    15. // 获取和socket关联的输入流,读取数据(字节)并显示
    16. InputStream inputStream = socket.getInputStream();
    17. BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    18. String s = bufferedReader.readLine();
    19. System.out.println(s);
    20. // 关闭流对象和socket
    21. bufferedReader.close(); // 关闭外层流
    22. bufferedWriter.close();
    23. socket.close();
    24. System.out.println("客户端关闭");
    25. }
    26. }
  • TCP传输

    1. public class TCPFileUploadServer {
    2. public static void main(String[] args) throws Exception {
    3. // 1. 监听本机端口
    4. ServerSocket serverSocket = new ServerSocket(9999);
    5. System.out.println("服务端监听ing");
    6. // 2. 等待连接
    7. Socket socket = serverSocket.accept();
    8. // 3. 读取客户端发送的数据
    9. // 得到输入流
    10. BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
    11. byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
    12. // 4. 将数据写入到指定的路径
    13. BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("C:\\Users\\ace\\Desktop\\b.png"));
    14. bufferedOutputStream.write(bytes);
    15. bufferedOutputStream.close();
    16. // 向客户端回复收到
    17. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    18. bufferedWriter.write("收到");
    19. bufferedWriter.flush();
    20. socket.shutdownOutput();
    21. // 关闭资源
    22. bufferedWriter.close();
    23. bufferedInputStream.close();
    24. socket.close();
    25. serverSocket.close();
    26. }
    27. }
    1. public class TCPFileUploadClient {
    2. public static void main(String[] args) throws Exception {
    3. // 客户端连接
    4. Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
    5. // 创建读取磁盘文件的输入流
    6. BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\ace\\Desktop\\a.png"));
    7. // bytes就是文件对应的字节数组
    8. byte[] bytes = StreamUtils.streamToByteArray(bufferedInputStream);
    9. // 通过socket获取到输出流,将bytes数据发送给服务端
    10. BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
    11. bufferedOutputStream.write(bytes); // 将文件写入通道
    12. bufferedInputStream.close();
    13. socket.shutdownOutput(); // 设置写入数据结束
    14. // 接收服务端消息
    15. InputStream inputStream = socket.getInputStream();
    16. String s = StreamUtils.streamToString(inputStream);
    17. System.out.println(s);
    18. // 关闭流
    19. bufferedOutputStream.close();
    20. socket.close();
    21. }
    22. }

    ```java public class StreamUtils { /**

    • 功能:将输入流转换成byte[], 即可以把文件的内容读入到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);//把读取到的数据,写入bos
      } byte[] array = bos.toByteArray();//然后将bos 转成字节数组 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){

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

      } return builder.toString();

      }

}

  1. <a name="BKbPF"></a>
  2. ## 五、UDP网络编程
  3. 类DatagramSocket和DatagramPacket[数据报]实现了基于UDP协议网络程序<br />UDP数据报通过数据报套接字DatagramSocket发送和接收,不保证安全<br />DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址、端口号以及接收端IP地址和端口号<br />UDP协议中每个数据报给出了完整地址信息,无须建立发送方和接收方的连接
  4. ```java
  5. public class UDPReceiveA {
  6. public static void main(String[] args) throws IOException {
  7. // 1. 创建DatagramSocket对象
  8. DatagramSocket datagramSocket = new DatagramSocket(9999);
  9. // 2. 构建一个DatagramPacket对象准备接收数据
  10. byte[] bytes = new byte[1024]; // UDP协议数据包最大64k
  11. DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
  12. // 3. 调用接收方法
  13. datagramSocket.receive(datagramPacket);
  14. // 4. packet进行拆包 取出数据并显示
  15. int length = datagramPacket.getLength(); // 实际接收到的数据长度
  16. byte[] data = datagramPacket.getData();
  17. String s = new String(data, 0, length);
  18. System.out.println(s);
  19. // 回复信息给B
  20. bytes = "hi".getBytes(StandardCharsets.UTF_8);
  21. datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(ip), 9998);
  22. datagramSocket.send(datagramPacket);
  23. // 5. 关闭
  24. datagramSocket.close();
  25. System.out.println("A close");
  26. }
  27. }
  1. public class UDPSenderB {
  2. public static void main(String[] args) throws IOException {
  3. // 创建DatagramSocket准备发送和接收数据
  4. DatagramSocket datagramSocket = new DatagramSocket(9998);
  5. // 装包
  6. byte[] bytes = "hello".getBytes(StandardCharsets.UTF_8);
  7. DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName(ip), 9999);
  8. datagramSocket.send(datagramPacket);
  9. // B接收
  10. // 1. 构建一个DatagramPacket对象准备接收数据
  11. bytes = new byte[1024]; // UDP协议数据包最大64k
  12. datagramPacket = new DatagramPacket(bytes, bytes.length);
  13. // 2. 调用接收方法
  14. datagramSocket.receive(datagramPacket);
  15. // 3. packet进行拆包 取出数据并显示
  16. int length = datagramPacket.getLength(); // 实际接收到的数据长度
  17. byte[] data = datagramPacket.getData();
  18. String s = new String(data, 0, length);
  19. System.out.println(s);
  20. // 关闭资源
  21. datagramSocket.close();
  22. System.out.println("B close");
  23. }
  24. }