Java网络编程基础学习与整理

网络编程

1网络通信的要素

1.1网络模型整理

TCP/IP参考模型

1.2 IP

  • ip定义:Internet Protocol,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务,可以唯一地定位一台网络计算机。(127.0.0.1为本机的localhost)
  • IP地址分类:
    • ipv4 : 由四个字节组成,例如 127.0.0.1 网络号+主机号
    • ipv6 : 128位,8组,每组4个16进制数,例如 2001:0db8:85a3:08d3:1319:8a2e:0370:7344,如果0000则省略
  • 公网(互联网)-私网(局域网)
    • 192.168.xx.xx属于局域网,专门给组织内部使用
    • ABCDE类地址根据网络号划分,如图所示,其中D类供组播使用,E类供科研使用
      ABCDE类划分图

1.3 端口

  • 端口表示计算机上一个程序的进程
  • 规定限制在2^16 0~65535之间
  • TCP UDP协议端口相隔离,但在单个协议下端口不能重复
  • 端口分类:
    • 公有端口:0~1023
      • HTTP:80
      • HTTPS:443
      • FTP:21
      • Telnet:23
    • 程序注册端口:1024~49151,程序或者用户使用
      • Tomcat:8080
      • MySQL:3306
      • Oracle:1521
      • Redis:6379
  • 动态端口、私有端口:49152~65535 不建议使用

1.4 传输层通信协议

  • TCP/UDP对比:
  • TCP:用户传输协议(打电话)
    • 连接、稳定
    • 三次握手、四次挥手
    三次握手:
    	第一次握手:客户端传输SYN=i给服务端,状态置为SYN_SEND;
    	第二次握手:服务端接受SYN=i后,返回ACK=i+1且返回SYN=j,状态置为SYN_RECV;
    	第三次握手:客户端接受ACK后状态置为ESTABLISHED,发送ACK=j+1,服务端接受后状态置为ESTABLISHED;
    四次挥手:
    	(1)客户端发送FIN,状态置为FIN_WAIT1,接受ACK后改为FIN_WAIT2
    	(2)服务端接受FIN,返回ACK,状态置为CLOSE_WAIT
    	(3)服务端数据传输完毕,返回FIN,状态改为LAST_ACK,接受客户端ACK后改为CLOSED
    	(4)客户端接受FIN后状态置为TIME_WAIT,2MS后置为CLOSED
    中间状态:
    	CLOSED:初始状态
    	LISTEN:监听中
    	SYN_SENT:发送SYN=i给服务端后
    	SYN_RCVD: 接受客户端的SYN=i后
    	ESTABLISHED:已连接
    	FIN_WAIT_1:ESTABLISHED状态下发送FIN=i给客户端后
    	FIN_WAIT_2:ESTABLISHED状态下发送FIN=i给客户端后接收到ACK返回则为2
    	CLOSE_WAIT:FIN接受方,收到后返回ACK并置为CLOSE_WAIT,数据传输完毕后返回FIN且状态改为LAST_ACK
    	TIME_WAIT:FIN发起方,收到对方返回的FIN后发送ACK,置为TIME_WAIT,2MS后会改为CLOSED
    	LAST_ACK:CLOSE_WAIT数据传输完毕后返回FIN且状态改为LAST_ACK
    	CLOSING:双方同时发起FIN
    
  • UDP:用户数据报协议(发短信)
    • 不连接、不稳定
    • 没明确的客户端服务端区分

1.5 TCP通信连接

  • 客户端:
    1.建立Socket连接服务器Socket
    2.发送消息
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            //获取服务端地址和端口
            InetAddress serverIp = InetAddress.getByName("localhost");
            int port = 9999;
            //创建Socket连接
            socket = new Socket(serverIp, port);
            //输出流输出信息
            outputStream = socket.getOutputStream();
            outputStream.write("hello".getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
        }
    }
    
  • 服务端
    1.建立ServerSocket
    2.等待客户端连接
    3.接受信息并处理
    public static void main(String[] args) {
        try {
            //等待Socket
            java.net.ServerSocket serverSocket = new java.net.ServerSocket(9999);
            while (true) {
                //等待客户端连接
                Socket clientSocket = serverSocket.accept();
                //读取
                InputStream inputStream = clientSocket.getInputStream();
                //管道流
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    bos.write(buffer, 0, len);
                }
                System.out.println(bos.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
        }
    }

1.6 TCP文件传输

  • 客户端:
     public static void main(String[] args) {
        try {
            InetAddress inetAddress = InetAddress.getByName("localhost");
            int port = 8888;
            Socket socket = new Socket(inetAddress, port);
            OutputStream outputStream = socket.getOutputStream();
            FileInputStream fileInputStream = new FileInputStream(new File("test.jpg"));
            int len;
            byte[] buffer = new byte[1024];
            while ((len = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer,0,len);
            }
            //通知服务端输出关闭
            socket.shutdownOutput();
            int len2;
            byte[] buffer2 = new byte[1024];
            //接受服务端返回信息并打印
            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            while ((len2 = inputStream.read(buffer2)) != -1) {
                byteArrayOutputStream.write(buffer2, 0, len2);
            }
            System.out.println(byteArrayOutputStream.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
        }
    }
  • 服务端:
	    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream("new.jpg");
            int len;
            byte[] buffer = new byte[1024];
            while ((len = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer,0,len);
            }
            //给客户端返回结束信息
            OutputStream outputStream = accept.getOutputStream();
            outputStream.write("end transfer".getBytes());
            //结束后需要关闭套接字,否则会导致客户端读取中断抛出异常
            accept.close();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
        }
    }

1.7 UDP发送信息

  • 定义:不用建立稳定连接,往指定IP 端口发送信息,不管有没有接受成功
  • 发送端:
    public static void main(String[] args) throws Exception {
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;
        //1.建立socket
        DatagramSocket datagramSocket = new DatagramSocket();
        //2.建立数据包
        String msg = "message";
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(), 0,
                msg.getBytes().length, localhost, port);
        //3.发送包
        datagramSocket.send(datagramPacket);
        //4.关闭流
        datagramSocket.close();
    }
  • 接受端:
    public static void main(String[] args) throws Exception {
        //开放端口
        DatagramSocket datagramSocket = new DatagramSocket(9090);
        //接受数据包
        byte[] buffer = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
        datagramSocket.receive(datagramPacket);
        System.out.println(datagramPacket.getAddress());
        System.out.println(new String(datagramPacket.getData(),0,datagramPacket.getLength()));
        //关闭连接
        datagramSocket.close();
    }

1.8 UDP实现简易聊天

//聊天工具类,构造方法记录本端端口及目标端口,新起线程持续监听控制台输入并传输
//到信息到目标端口处,本端线程持续监听本端IP,并打印接受到的信息
public class TalkSendUtil {
   DatagramSocket targetSocket = null;
   DatagramSocket receiveSocket = null;
   DatagramPacket receivePacket = null;
   DatagramPacket sendPacket = null;

   private int toPort;

   public TalkSendUtil(int toPort, int localPort) throws Exception {
       this.toPort = toPort;
       targetSocket = new DatagramSocket();
       receiveSocket = new DatagramSocket(localPort);
   }

   public void invoke() throws Exception {
       new Thread(() -> {
           while (true) {
               BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
               try {
                   String data = bufferedReader.readLine();
                   sendPacket = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, InetAddress.getByName("localhost"), toPort);
                   targetSocket.send(sendPacket);
                   if (data.equals("bye")) {
                       targetSocket.close();
                       receiveSocket.close();
                       break;
                   }
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
       }).start();
       while (true) {
           byte[] buffer = new byte[1024];
           receivePacket = new DatagramPacket(buffer, 0, buffer.length);
           try{
               receiveSocket.receive(receivePacket);
           }catch(SocketException exception){
               System.out.println("聊天已关闭");
               return;
           }
           String receive = new String(receivePacket.getData(), 0, receivePacket.getLength());
           System.out.println(receivePacket.getPort() + ":" + receive);
           if (receive.equals("bye")) {
               receiveSocket.close();
               break;
           }
       }
   }
}

聊天者1:

public class UDPChat1 {
    public static void main(String[] args) throws Exception {
        TalkSendUtil talkSendUtil = new TalkSendUtil(1112,1111);
        talkSendUtil.invoke();
    }
}

聊天者2:

public class UDPChat2 {
    public static void main(String[] args) throws Exception {
        TalkSendUtil talkSendUtil = new TalkSendUtil(1111,1112);
        talkSendUtil.invoke();
    }
}

效果图:
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值