VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • javaSE高级篇3 — 网络编程 — 更新完毕

网络编程基础知识

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

 

  • 网络编程中的几个要素
    • 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相关的网络编程就整完了

 



相关教程