Java网络编程笔记

Java网络编程笔记

1.1、网络通信的要素:

如何实现网络的通信?

需要通信双方的地址:

  • IP

  • 端口号

规则:网络通信的协议

TCP/IP参考模型:

image-20210301185158674

小结:

  1. 网络编程中有两个主要的问题:

    • 如何定位到网络上一台或多态主机?

    • 找到主机之后如何进行通信?

  2. 网络编程中的要素

    • IP和端口号

    • 网络通信协议:UDP、TCP

  3. 万物皆对象

 

1.2、IP

  1. Java中的IP类:InetAddress;

  2. IP地址的分类:

    • 公网

    • 私网

  3. ipv4/ipv6

    • ipv4(格式:127.0.0.1):由4个字节组成,范围0~255,一共有大约42亿,30亿在北美,4亿在亚洲,2011年就用尽了;

    • ipv6(格式:fe80::7def:75c4:3651:ce22%15):

 

package com.zq.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;

//测试ip
public class TestIp {
  public static void main(String[] args) throws UnknownHostException {
      //获取本机地址
      InetAddress localhost1 = InetAddress.getByName("127.0.0.1");
      InetAddress localhost2 = InetAddress.getByName("localhost");
      InetAddress localhost3 = InetAddress.getLocalHost();

      System.out.println(localhost1);
      System.out.println(localhost2);
      System.out.println(localhost3);

      //查询网址ip地址
      InetAddress baidu = InetAddress.getByName("www.baidu.com");
      System.out.println(baidu);
  }
}

 

1.3、端口

每个进程都会有一个端口

  • 不同进程有不同端口号,用来区分软件

  • 被规定为0~65535(TCP、UDP各有65535个)

  • 多个协议下,不同的协议可以用相同的端口

  • 端口分类

    • 公有端口0~1023

      • http默认端口:80

      • https默认端口:443

      • ftp默认端口:21

    • 程序注册端口1024~49151

      • Tomcat:8080

      • MySQL:3306

      • Oracle:1521

    • 动态私有端口:49152~65535

    •  

1.4、通信协议

TCP/IP协议:

重要:

  • TCP:用户传输协议

  • UDP:用户数据报协议

 

TCP与UDP的对比:

  • TCP:打电话

    • 连接,稳定

    • 三次握手四次挥手

      三次握手:最少需要三次,保证稳定连接!

      A:你瞅啥?

      B:瞅你咋地?

      A:干一场?

       

       

      四次挥手:

      A:我要断开了!

      B:你真的要断开了吗?

      B:你真的真的要断开了吗?

      A:我真的要断开了!

    • 客户端与服务端

    • 传输完成,释放连接,效率低

  • UDP:发短信

    • 不连接,不稳定

    • 客户端,服务端没有明确的界限

    • 不管有没有准备好都能发给你

 

1.6、TCP实现通讯

  1. 服务端

package com.zq.tcp;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

//tcp协议服务端
public class TestTcpServer {
  public static void main(String[] args) {
      ServerSocket server = null;
      Socket accept = null;
      InputStream is = null;
      ByteArrayOutputStream baos = null;

      while (true) {
          try {
              //1.首先得有一个地址
              server = new ServerSocket(8888);
              //2.等待连接客户端
              accept = server.accept();
              //3.获取客户端发过来的信息
              is = accept.getInputStream();
              baos = new ByteArrayOutputStream();

              byte[] buffer = new byte[1024];
              int len = 0;
              while ((len = is.read(buffer)) != -1) {
                  baos.write(buffer, 0, len);
              }

              //打印输出
              System.out.println(baos.toString());
          } catch (IOException e) {
              e.printStackTrace();
          } finally {
              //关闭资源
              if (baos != null) {
                  try {
                      baos.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if (is != null) {
                  try {
                      is.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if (accept != null) {
                  try {
                      accept.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              if (server != null) {
                  try {
                      server.close();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }
      }
  }
}
  1. 客户端

package com.zq.tcp;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

//tcp协议客户端
public class TestTcpClient {
  public static void main(String[] args) {
      Socket socket = null;
      OutputStream os = null;
      Scanner scanner = null;
      try {
          //1.首先得有对方的ip地址和端口
          InetAddress address = InetAddress.getByName("127.0.0.1");
          int port = 8888;

          //进行连接
          socket = new Socket(address, port);

          //发送消息
          os = socket.getOutputStream();
          os.write("Hello,World! 你好,世界!".getBytes());
      } catch (UnknownHostException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          //关闭资源
          if (os != null) {
              try {
                  os.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          if (socket != null) {
              try {
                  socket.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
  }

}

 

1.5、UDP

发送端:

package com.zq.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class TestUdpClient {
  public static void main(String[] args) throws Exception {
      //1.建立一个socket
      DatagramSocket socket = new DatagramSocket(8888);

      //2.需要一个包
      String message = "Hello,World!";
      InetAddress address = InetAddress.getByName("127.0.0.1");
      DatagramPacket packet = new DatagramPacket(message.getBytes(), 0, message.getBytes().length, address, 9999);

      //3.发送这个包
      socket.send(packet);

      //4.关闭连接
      socket.close();
  }
}

接收端:

package com.zq.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class TestUdpServer {
  public static void main(String[] args) throws Exception{
        //1.建立一个socket
      DatagramSocket socket = new DatagramSocket(9999);

      //2.需要一个包
      byte[] data = new byte[1024];
      DatagramPacket packet = new DatagramPacket(data,0, data.length);

      //3.接收发过来的包
      socket.receive(packet);

      //4.打印输出
      System.out.println("来自ip为" + packet.getAddress() + "发来的消息");
      String str = new String(packet.getData(),0,packet.getLength());
      System.out.println(str);

      //5.关闭连接
      socket.close();
  }
}

 

1.6、UDP实现聊天

  1. 创建发送消息的线程

package com.zq.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class UdpSend implements Runnable{

  private String username;

  private String address;

  private int toPort;

  private DatagramSocket socket;

  private BufferedReader bw;

  public UdpSend(String username, int fromPort, String address, int toPort){
      this.username = username;
      this.address = address;
      this.toPort = toPort;
      try {
          socket = new DatagramSocket(fromPort);
          bw = new BufferedReader(new InputStreamReader(System.in));
      } catch (Exception e){
          e.printStackTrace();
      }
  }

  @Override
  public void run(){
      while (true) {
          try {
              //发送消息
              String message = username + ":" + bw.readLine();
              DatagramPacket packet = new DatagramPacket(message.getBytes(), 0, message.getBytes().length, new InetSocketAddress(this.address, this.toPort));
              socket.send(packet);

              if(message.indexOf("bye") != -1)
                  break;
          } catch (IOException e) {
              e.printStackTrace();
          }
      }

      //关闭资源
      try {
          bw.close();
      } catch (IOException e) {
          e.printStackTrace();
      }
      socket.close();
  }
}
  1. 创建接收消息的线程

package com.zq.chat;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
* @author Mr.zhou
* @version 1.0
* @date 2021/3/3 20:53
*/
public class UdpReceive implements Runnable {

  private DatagramSocket socket;

  public UdpReceive(int port){
      try {
          socket = new DatagramSocket(port);
      } catch (SocketException e) {
          e.printStackTrace();
      }
  }

  @Override
  public void run() {
      while (true) {
          try {
              byte[] data = new byte[1024];
              DatagramPacket packet = new DatagramPacket(data, 0, data.length);

              //阻塞式接收
              socket.receive(packet);
              String message = new String(packet.getData(), 0, packet.getLength());
              System.out.println(message);

              //如果接收到bye,则关闭
              if (message.indexOf("bye") != -1)
                  break;
          } catch (IOException e) {
              e.printStackTrace();
          }
      }

      //关闭资源
      socket.close();
  }
}
  1. 模拟学生并创建两个线程

package com.zq.chat;

import java.net.InetAddress;

/**
* @author Mr.zhou
* @version 1.0
* @date 2021/3/3 21:08
*/
public class ChatStudent {
  public static void main(String[] args) {
      new Thread(new UdpSend("Student", 6666, "localhost", 8888)).start();
      new Thread(new UdpReceive(9999)).start();
  }
}
  1. 模拟老师并创建两个线程

package com.zq.chat;

/**
 * @author Mr.zhou
 * @version 1.0
 * @date 2021/3/3 21:08
 */
public class ChatTeacher {
    public static void main(String[] args) {
        new Thread(new UdpSend("Teacher", 7777, "localhost", 9999)).start();
        new Thread(new UdpReceive(8888)).start();
    }
}
  1. 启动两个类,模拟对话如下:

你好,teacher
Teacher:你好,Student
Student:你好,eacher
你好,Student

 

posted @   有梦想的程序员。  阅读(57)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示