网络编程基础知识

  • 先来思考两个问题( 在这里先不解决 )
    • 如何准确的找到一台 或 多台主机?
    • 找到之后如何进行通讯?
  • 网络编程中的几个要素

    • IP 和 端口号
    • 网络通讯协议:TCP / UDP
  • 最后一句话

    • 万物皆对象

1、IP介绍——英文:inetAdress——IP地址

  • 作用:标记网络中每台计算机的身份,网络中每台计算机都有一个唯一的身份号码,就和人的身份证一样

    • 举个例子:如127.0.0.1——指:本机地址( localhost )
  • IP的表示方法

    • ipv4 / ipv6

      • ipv4:由一个4字节32位的整数构成( 如:192.168.100.1 ),每8位用0 ~ 255表示( 即:例子中的每一个数字不超过255 ),它们彼此之间用  " . " 隔开,所以这个ipv4能够表示42亿多个ip地址。但是有30多亿在北美,而亚洲只有4亿多点,而人这么多,所以这种表示方式根本不够用,因此:在2011年的时候这些ip地址就已经用完了——————咋个办?所以弄出了ipv6
      • ipv6:有一个16字节128位的整数构成( 如:Y.Y.Y.Y.Y.Y.Y.Y ),每段的范围是0 ~ 65535
  • IP分类

    • 公网( 互联网) 、 私网( 局域网 )————直接看图

      • 其中,不想详细了解的话,作为程序员只需要知道两个命令即可——ipconfig 和 ping
        • ipconfig:是查看自己的计算机ip地址————即:在dos窗口中输入这个命令回车即可看到
        • ping:是查看自己的计算机是否链接上知道ip地址的计算机————即:ping 接要查看的计算机ip地址
  • 在java中怎么玩儿ip?

    • 多提一句:java中和网络相关的都在java.net包下
    • java中已经封装好了一个类————inetAdress类:这个类没有构造方法,所以不能new对象,直接通过 类名. 调用方法( 方法也不多,就下图中的这几个,而且也没多大用 )


      • // 1、获取ip名字————参数是String host
        System.out.println( InetAddress.getByName("127.0.0.1") ); System.out.println( InetAddress.getByName("www.baidu.com") ); // 这个没啥好玩的

        效果如下:

2、端口

  • 先来思考一个问题

    • 一台计算机它是怎么读取数据的?————换句话说:它是怎么知道一个 / 一些数据是哪个软件发过来的?( 接收的时候对数据进行处理嘛 )
  • 为了解决上述的问题————端口就来了

    • 端口:指的是计算机上一个程序的进程
    • 端口的范围: 0 ~ 65535
    • 不同的应用程序,端口都不一样,这样就可以通过固定的端口进行收发数据了
  • 常见的默认端口如下

    • MySQL ————>  3306

      Tomcat ————> 8080

      HTTP ————>  80

      SSH ————> 22 这是linux下的安全传输协议端口

      FTP ————> 21

    • 多一点了解的话,就看下图
  • 在java中怎么玩端口?————也是封装好了的,使用一个类InetSocketAddress————也没什么好玩的

3、通信协议——这才是重点

  • 协议:就是一种约定嘛,就好比————我们说的普通话
  • 网络通信协议:也就是网络之间进行通讯的约定嘛————管速率、传输码率、传输控制............
  • 由网络通信协议看出:麻不麻烦?

    • 当然麻烦涩,大事化小咯————分层,如下图所示

    • 看起来好多啊,但是没事儿,又不是专门搞网络的,所以不需要整那么多,就几个而已
  • 1、TCP / UDP协议

    • TCP:传输控制层协议( 用户传输协议 )
      • 特点:

        • 面向连接式协议:指 应用程序在使用TCP协议之前必须先建立TCP连接,在传送数据完毕后必须释放已经建立的TCP连接
        • 每一条TCP连接只能有两个端点,即:A和B连接,A就不能再用TCP和其他的连接在一起 ( 点对点连接嘛 )
        • TCP可靠,即:通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达
        • 提供全双工通信:即:TCP允许通信双方( 断开不行啊 )的应用进程在任何时候都能发送数据
        • 面向字节流传输:即:传输的数据是字节流,关注点是:字节。什么意思?
          • 假如:两个端点之间传输了一句话,但是这句话在TCP里面不是文字,而是这句话的每个字符对应的字节数字,如:a ———> 97
    • 在这里需要了解两个东西:三次握手、四次挥手(四次分手)

      • 先看这两个的图

        • 三次握手


        • 四次挥手( 四次分手 )


        • 三次握手到底是什么意思?

          • 如上图

            • A:你瞅啥? ————> 客户端发送连接的请求,服务端对这个请求进行监听
            • B:瞅你咋地 ————> 然后服务端回应客户端: 可以 / 不可以 进行传输
            • A、B:走,干一架 ————> 最后客户端 进行 / 不进行 数据传输
        • 那四次挥手又到底是个啥子玩意儿?

          • 不是备注了一下:四次分手吗,那就用分手来理解一下

            • 男:我想跟你分手 ————> 客户端向服务端发送连接的请求
            • 女:你要分手?—————> 服务端响应客服端
            • 女:你真的要分手??? ————> 服务端询问客户端是否准备链接
            • 男:老子确定分手 ————> 服务端 和 客户端建立连接
    • UDP:用户数据报协议

      • 特点:

        • 面向无连接式协议:即:发送数据之前不需要建立连接
        • UDP不可靠(不稳定):即:数据的传输中只是尽最大努力把数据送达,不保证一点不丢失( 如:停电了、断网了 ,哦豁 ~ 数据没穿得过去 )
        • 支持一对一、一对多、多对多通信
    • TCP和UDP的对比

      • TCP( 好比:打电话 )

        • 安全、可靠
        • 连接稳定( 三次握手、四次挥手 )
        • 客户端 和 服务端界限明确
        • 缺点:要等传输完成,才能释放连接,效率低
      • UDP( 好比:发短信、写信 )
        • 不稳定、不靠谱
        • 客户端 和 服务端界限不明确
        • 不管有没有准备好,都可以发给你( 就好比:导弹,想整你的时候,还需要管你准没准备好吗 )
        • 漏洞就来了

          • 黑别人的时候,发布洪水攻击( 即:疯狂发送东西,看好的还是坏的信息啊 )————最后:直接把别人网络干趴
  •  2、TCP协议编程———即:Socket编程

    • Socket就相当于是 服务端 和 客户端 之间的那个连接通道

    • 服务器端使用ServerSocket套接字 并绑定监听端口
    • 服务端 阻塞等待连接
    • 客户端使用 Socket 并指定服务端IP 和 端口
      • 服务端
        • //1. 服务器端套接字
          ServerSocket server = new ServerSocket(8848);
          //2. 监听客户端连接
          Socket socket = server.accept(); 
      • 客户端

        • //1. 创建客户端套接字
          Socket socket = new Socket( "127.0.0.1" , 8848);
    • 实操一手儿  

      • 1、客户端 给 服务端 发送数据

        • package cn.xieGongZi.test;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.net.ServerSocket;
          import java.net.Socket; // 服务端
          public class Server { public static void main(String[] args) { Socket socket = null;
          BufferedReader br = null; // 1、需要建立一个连接的通道sorket————即:套接字
          try { ServerSocket serverSocket = new ServerSocket(9999);// 需要一个端口号————即:这个链接通道的名字是什么
          // 这个东西就是底层中封装的3次握手 // 2、有了这个通道之后就可以等着客户端来链接了——————使用accept()方法
          System.out.println("正在等待链接:");
          socket = serverSocket.accept(); // 等待客户端的链接————客户端和服务端真正建立了连接通道 // 3、如果客户端链接上就可以进行文件的 读 / 写了
          // 读取文件————这里是传输的文字,所以直接一行一行的读取,快一点嘛
          br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); String buffer;
          while ( ( buffer = br.readLine() ) != null ){
          System.out.println("服务端收到了:" + buffer );
          } } catch (IOException e) {
          e.printStackTrace();
          }finally { // 最后关闭流管道和网络链接通道————但是Socket 和 流管道 是在try中,这里拿不到,所以:提升作用域————全局变量
          // 倒着关闭
          if ( socket != null ){
          try {
          socket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( br != null ){
          try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } }
          }
          }
        • package cn.xieGongZi.test;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket; // 客户端
          public class Client { public static void main(String[] args) { Socket clientSocket = null;
          BufferedWriter bw = null; // 1、建立链接通道————需要ip和端口号
          try {
          clientSocket = new Socket("127.0.0.1", 9999); // 2、开始传输文件————建立流管道
          bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
          bw.write("不球晓得传输个啥子东西"); } catch (IOException e) {
          e.printStackTrace();
          }finally { // 关闭流管道 和 网络链接通道
          if ( bw != null ){
          try {
          bw.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( clientSocket != null ){
          try {
          clientSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
        • 效果如下:
      • 2、多个客户端 给 服务端发送数据

        • package cn.xieGongZi.testManyClientToServer;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.net.ServerSocket;
          import java.net.Socket; // 服务端————可以让多个客户端来进行链接
          public class Server { public static void main(String[] args) { // 1、建立链接通道
          try {
          ServerSocket serverSocket = new ServerSocket(2020); while ( true ){ // 保证服务端能够多开,不然只开启一个准备链接通道,那多个客户端链接只能链接第一个了 // 2、等待客户端来链接
          System.out.println("等待连接");
          Socket socket = serverSocket.accept(); // 3、但是:如果在这里直接进行数据的读写,那又不行
          // 因为:万一第一个链接通道一致没有客户端传输数据过来,那不就堵着了吗
          // 所以:开线程————让每一个客户端 和 服务端进行链接之后都去单独的一个线程中进行读写数据
          // 开线程
          new openThread(socket).start();
          } } catch (IOException e) {
          e.printStackTrace();
          }
          }
          } // 开线程
          class openThread extends Thread{ private Socket socket; public openThread( Socket socket ){
          this.socket = socket;
          } @Override
          public void run() { // 这个线程里面要干的事情:就是让服务端 和 客户端进行数据读写
          // 但是:问题来了
          // 怎么能够保证是哪一个连接通道进行读写数据?
          // 所以:需要把链接通道传进来————组合的方式 // 客户端 和 服务端 的链接通道正式开始进行读写数据
          BufferedReader br = null;
          try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String data;
          while ( ( data = br.readLine() ) != null ){
          System.out.println(data);
          }
          } catch (IOException e) {
          e.printStackTrace();
          }finally { if ( br != null ){
          try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( socket != null ){
          try {
          socket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
        • package cn.xieGongZi.testManyClientToServer;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket; // 客户端
          public class Client { public static void main(String[] args) { Socket clientSocket = null;
          BufferedWriter bw = null; // 1、建立链接通道————需要ip和端口号
          try {
          clientSocket = new Socket("127.0.0.1", 2020); // 2、开始传输文件————建立流管道
          bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
          bw.write("不球晓得传输个啥子东西"); } catch (IOException e) {
          e.printStackTrace();
          }finally { // 关闭流管道 和 网络链接通道
          if ( bw != null ){
          try {
          bw.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } if ( clientSocket != null ){
          try {
          clientSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }
      • 3、客户端给客户端发送数据( 即:多人聊天 )————注意:直接通过客户端 和 客户端交互是不可以的

        • package cn.xieGongZi.clientToClient;
          
          import java.io.BufferedReader;
          import java.io.IOException;
          import java.io.InputStreamReader;
          import java.io.PrintWriter;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.ArrayList;
          import java.util.List; // 服务端————玩儿客户端 与 客户端进行聊天
          public class Server { static List<Socket> socketList= new ArrayList<>(); public static void main(String[] args) { ServerSocket serverSocket = null; // 1、建立通信管道链接
          try {
          serverSocket = new ServerSocket(3030); // 2、等待客户端来链接
          System.out.println("正在等待链接:");
          Socket acceptSocket = serverSocket.accept(); // 3、如果客户端链接上了,则:进行数据的读写
          // 读取客户端的数据————照样的放在这里不好,应该单独让它们去一下线程里做事
          // 所以:开线程
          new openServerThread(acceptSocket).start(); // 最后搞一件事情————把从客户端接过来的链接通道这个客人给我放到集合中去
          Server.socketList.add(acceptSocket);

          } catch (IOException e) {
          e.printStackTrace();
          }finally { if (serverSocket != null ){
          try {
          serverSocket.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
          }
          }


          // 开线程
          class openServerThread extends Thread{ // 一样的保证:客户端 与 客户端在一个连接通道中————还是用组合
          private Socket socket;
          public openServerThread( Socket socket ){
          this.socket = socket;
          } // 线程该做的事
          @Override
          public void run() { BufferedReader br = null; // 读取客户端的数据
          try {
          br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String data;
          while ( ( data = br.readLine() ) != null ){ // 在这里:服务端就接收到了客户端的数据
          // 但是:要搞得事情不是把这个数据给打印出来看效果
          // 而是:在这里借服务端的手,把客户端传过来的数据 转发 给其他客户端
          // 可:问题又来了————服务端只是从客户端哪里接客了,但是接了哪些客,它不知道
          // 因此:需要一个东西来记录一下————服务端接了哪些客————集合(因为:具体多少个客户端不知道)
          // 所以:定义一个全局的集合
          // 然后:服务端接一个客户端,那就把这个客户端放到集合中去 // 最后需要搞一件事情涩————就是去集合中找除了自己这个客户端以外的其他客户端(即:另外的Socket通道)
          // 然后把接收过来的数据 转发 给其他客户端
          for (int i = 0; i < Server.socketList.size(); i++) { // 遍历这个集合
          Socket checkSocket = Server.socketList.get(i); // 看遍历出来的这个Socket是不是它自己本身————是的话就不转发了
          if ( this.socket == checkSocket ) continue; // 否则:就是其他的Socket通道嘛————即:其他的客户端————那就转发数据( 输出数据嘛 )
          new PrintWriter( checkSocket.getOutputStream() ).println(data); }
          }
          } catch (IOException e) {
          e.printStackTrace();
          }finally { if ( br != null ){ try {
          br.close();
          } catch (IOException e) {
          e.printStackTrace();
          }
          } }
          }
          }
        • package cn.xieGongZi.clientToClient;
          
          import java.io.BufferedWriter;
          import java.io.IOException;
          import java.io.OutputStreamWriter;
          import java.net.Socket;
          import java.util.Scanner; // 客服端
          public class Client { public static void main(String[] args) { try {
          Socket clientSocket = new Socket("127.0.0.1", 3030); // 这里问题又来了,实现客户端 与 客户端 聊天嘛。所以传输的东西肯定不能写死啊
          // 因此:再开线程
          new openClientThread(clientSocket).start(); } catch (IOException e) {
          e.printStackTrace();
          } }
          }


          // 开线程
          class openClientThread extends Thread{ private Socket socket; public openClientThread( Socket socket ){
          this.socket = socket;
          } @Override
          public void run() { // 线程该做的事
          System.out.println("聊天开始");
          Scanner input = new Scanner(System.in); // 进行数据传送
          while (true){ try {
          BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); String text = input.nextLine();
          bw.write(text);
          } catch (IOException e) {
          e.printStackTrace();
          }
          }
          }
  • 3、UDP协议编程———即:DatagramSocket编程

    • UDP编程————其实和TCP一样,玩法都一样,只是Socket变成了DatagramSocket而已

      • 不需要连接,但是需要知道对方的地址
      • 没有客户端 和 服务端的概念————可以互相发
      • 就像:发包裹一样————只需要知道地址就可以了
    • 直接上实例 

      • package AboutUDP.SendFiles;
        
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress; public class SendFile {
        public static void main(String[] args) throws Exception {
        //1、和传文件的对象建立链接--->
        // 这个socket和Receive里的socket是同一个:起到链接的作用
        DatagramSocket socket = new DatagramSocket(); //2、需要知道接收端的ip和端口号
        InetAddress ip = InetAddress.getByName("localhost");
        int port = 8888; //3、得有一个要发送的东西--->可以通过写程序让它去网上下东西,然后发过去
        //在这里 用自定义一个内容发过去测试
        String data= "你像个傻逼,还不晓得努力!"; //4、发什么内容,发的内容是从哪里开始---结束,发给什么Ip和端口
        DatagramPacket packet = new DatagramPacket(data.getBytes(),0,data.getBytes().length,ip,port);
        //data.getBytes()把要传送的数据包转为字节型数组:是因为电脑底层的传送实质是以字节来传送的 //5、发送文件
        socket.send(packet); //6、关闭链接
        socket.close();
        }
        }
      • package AboutUDP.SendFiles;
        
        import java.net.DatagramPacket;
        import java.net.DatagramSocket; public class ReceiveFile {
        public static void main(String[] args) throws Exception {
        //1、得有一个端口来让别人链接
        DatagramSocket socket = new DatagramSocket(8888); //2、接收包文件
        byte[] receiveFile = new byte[1024];//这个空的数据包是用来接收数据的:把接收的数据装在这里面
        //DatagramPacket这才是接收数据的命令
        DatagramPacket packet = new DatagramPacket(receiveFile,0,receiveFile.length); //3、接收 装好的包文件
        socket.receive(packet); //看一下效果
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        //4、关闭链接--->实质为关闭端口,防止端口占用
        socket.close();
        }
        }

  • 4、URL
    • 这个就不玩了,这个玩意儿就是定位网上的资源嘛( 怎么定位,就是输入的网址呗 ),因为:这个url就是一个对象,代表的就是url地址,也就是浏览器( 输入网址弹出来的不就是相应的页面内容吗 )
    • 这玩意儿在Java中怎么创建出来?

      • 万物皆对象嘛,这句话在博客开篇不是白说的,因此:new一下就出来了,至于具体怎么玩自行看源码摸索( 提示:这个东西可以搞小爬虫,获取网上资源 )

自此:Java相关的网络编程就整完了

javaSE高级篇3 — 网络编程 — 更新完毕的更多相关文章

  1. javaSE高级篇2 — 流技术 — 更新完毕

    1.先认识一个类----File类 前言:IO相关的一些常识 I / O----输入输出 I     输入     input 0    输出     output I / o 按数据的流动方向来分- ...

  2. python自动化开发-[第八天]-面向对象高级篇与网络编程

    今日概要: 一.面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) 2.__setattr__,__getattr__,__delattr__ 3.二 ...

  3. 4 - 基于ELK的ElasticSearch 7.8.x技术整理 - 高级篇( 续 ) - 更新完毕

    0.前言 这里面一些理论和前面的知识点挂钩的,所以:建议看一下另外3篇知识内容 基础篇:https://www.cnblogs.com/xiegongzi/p/15684307.html java操作 ...

  4. 《Java从入门到放弃》JavaSE入门篇:网络编程(入门版)

    要进行网络编程,首先要搞清楚目的是什么. 网络编程说简单点就是在网络上的计算机进行数据的交互. 既然要进行数据交互,那就需要有一个发送方和一个接受方. 按网络上的说法,就是一个攻一个受· 当然,现阶段 ...

  5. javaSE高级篇5 — java8新特性详解———更新完毕

    java8新特性 在前面已经见过一些东西了,但是:挖得有坑儿 1.lambda表达式 lambda表达式是jdk1.8引入的全新语法特性 它支持的是:只有单个抽象方法的函数式接口.什么意思? 就是说: ...

  6. Java入门 - 高级教程 - 05.网络编程

    原文地址:http://www.work100.net/training/java-networking.html 更多教程:光束云 - 免费课程 网络编程 序号 文内章节 视频 1 概述 2 Soc ...

  7. 大数据学习笔记——Java篇之网络编程基础

    Java网络编程学习笔记 1. 网络编程基础知识 1.1 网络分层图 网络分层分为两种模型:OSI模型以及TCP/IP网络模型,前者模型分为7层,是一个理论的,参考的模型:后者为实际应用的模型,具体对 ...

  8. Java之旅_高级教程_网络编程

    摘自:http://www.runoob.com/java/java-networking.html JAVA网络编程 网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来. j ...

  9. 01 语言基础+高级:1-9 网络编程_day11【网络编程】

    day11[网络编程] 主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类 ...

随机推荐

  1. Linux过来人帮你理清学习思路

    很多同学接触linux不多,对linux平台的开发更是一无所知. 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机it行业从业人员,="" 掌握linux是一种很重要的 ...

  2. word-break leetcoder C++

    Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...

  3. 通用 Makefile(及makefile中的notdir,wildcard和patsubst)

    notdir,wildcard和patsubst是makefile中几个有用的函数,以前没留意过makefile中函数的用法,今天稍微看看~ 1.makefile里的函数 makefile里的函数使用 ...

  4. PWN学习之栈溢出

    目录 PWN学习之栈溢出 前言 写bug bug.cpp源码 OD动态调试bug.exe OD调试观察溢出 栈溢出攻击之突破密码验证 x64位栈溢出 PWN学习之栈溢出 前言 我记得我在最开始学编程的 ...

  5. docker commit 制作自定义tomcat镜像

    官网下载的tomcat一般存在漏洞,在生产环境中一般是自己下载jdk和tomcat制作成一个新的镜像使用 1.将jdk和tomcat上传 2.生成 c3 容器 3.将jdk和tomcat拷贝到c3容器 ...

  6. istio基础详解

    1.Istio介绍? 官方文档:https://istio.io/docs/concepts/what-is-istio/ 中文官方文档:https://istio.io/zh/docs/concep ...

  7. 记录一个很傻的错误(C++)

    使用的vscode写代码,导入了vector,memory,然后忘了导入string.但是代码中能够提示std::string也就让我忘了导入string.然后就莫名其妙的报错了.找了很久的错.记录下 ...

  8. Cannot load module file xxx.iml的两种解决方法

    一. 一种是点击左上角File,然后点击Invalidate Caches / Restart...,弹出对话框再点击Invalidate and Restart等待工程重新加载,问题就解决了. 二. ...

  9. 03 | 变量的解构赋值 | es6

    变量的解构赋值 数组的解构赋值 基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 以前,为变量赋值,只能直接指定值. let a ...

  10. redis 内存划分

    1.数据:作为数据库,数据是最主要的部分,这部分占用的内存会被统计在used_memory中 2.进程内存:redis主进程本身运行需要占用的内存,这部分内存会被统计在used_memory_rss中 ...