网络编程

一、网络编程概述

  1. 定义
    • 计算机网络
      • 是指将地理位置不同的具有独立功能的多台计算机以及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件以及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
    • 网络编程
      • 用来实现网络互连的不同计算机上运行的程序间,可以进行数据交换
  2. IP地址
    • 每个设备在网络中的唯一标识
    • 每台网络终端在网络中都有一个独立的地址,我们在网络中传输数据就是使用这个地址
    • ipconfig:查看本机IP
    • ping:测试连接
    • 本地回路地址:127.0.0.1
    • IPv4:4个字节组成,4个0-255。大概42亿个,30亿都在北美,亚洲4亿。2011年初已经用完
    • IPv6:8组,每组4个16进制数
  3. 端口号
    • 每个程序在设备上的唯一标识
    • 每个网络程序都需要绑定一个端口号,传输数据的时候除了确定发到哪台机器上,还要明确发到哪个程序
    • 端口号范围从0-65535
    • 编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以上的基本上都被系统程序占用了
  4. 协议
    • 为计算机网络中进行数据交换而建立的规则、标准、或约定的集合
    • UDP
      • 面向无连接,数据不安全,速度快。不区分客户端和服务端
    • TCP
      • 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端
      • 三次握手:客户端先向服务端发起请求,服务端响应请求,客户端发送确认信息

二、Socket通信

  1. 定义
    • 网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能够识别的标识符套接字
    • 通信的两端都有Socket
    • 网络的两端都有Socket
    • 网络通信其实就是Socket间的通信
    • 数据在两个Socket间通过IO流传输
    • Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port(端口)

三、UDP传输

  1. 发送Send

    • 创建DatagramSocket,指定端口号
    • 创建DatagramPacket,指定数据,长度,地址,端口
    • 使用DatagramSocket发送DatagramPacket
    • 关闭DatagramSocket
  2. 接收Receive

    • 创建DatagramSocket,指定端口号
    • 创建DatagramPacket,指定数据,长度
    • 使用DatagramSocket接收DatagramPacket
    • 关闭DatagramSocket
    • 从DatagramPacket中获取数据
  3. 接收方式获取ip和端口号

    • String ip = packet.getAddress().getHostAddress();
    • int port = packet.getPort();
  4. 演示

    • 发送端

      public static void main(String[] args) throws Exception {
         //确定要发送的内容
         String str = "你愿意跟我一起去吃麻辣烫吗?";
         //创建发送端Socket 可以ip ,会提供一个随机的
         DatagramSocket socket = new DatagramSocket();
         //创建装载数据的包  要指明IP地址,端口号, 
         DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, 
                 InetAddress.getByName("127.0.0.1"), 6666);
         //发送数据
         socket.send(packet);
         //关闭socket
         socket.close();
      }
      
    • 接收端

      public static void main(String[] args) throws Exception {
         //创建接收端Socket,必须指定端口,不然接收不到
         DatagramSocket socket = new DatagramSocket(6666);
         //创建装载数据的包
         DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
         //接收数据, 阻塞方法
         socket.receive(packet);
         //获取接收到的数据
         byte[] bs = packet.getData();
         //获取接收到的有效数据的长度
         int len = packet.getLength();
         System.out.println(new String(bs,0,len));
         //获取对方法的端口号
         System.out.println(packet.getPort());
         //获取对方的ip地址
         System.out.println(packet.getAddress());
         //关闭socket
         socket.close();
      }
      
  5. UDP传输优化

    public static void main(String[] args) throws Exception {
     //从键盘录入数据
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     
     //创建发送端Socket 
     DatagramSocket socket = new DatagramSocket();
     //循环接收数据
     while(true){
         String str = br.readLine();
         //创建装载数据的包  要指明IP地址,端口号, 
         DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, 
                 InetAddress.getByName("127.0.0.1"), 6666);
         
         //发送数据
         socket.send(packet);
         if("结束".equals(str)){
             break;
         }
     }
    
     //关闭socket
     socket.close();
    }
    

四、UDP传输之多线程

  1. 定义

    • 使用多线程同时启动接收端和发送端
  2. 演示

    • 发送端

      class Send extends Thread {
         public void run() {
             DatagramSocket socket = null;
             BufferedReader br = null;
             try {
                 
                 socket = new DatagramSocket();      //创建socket相当于创建码头
                 br = new BufferedReader(new InputStreamReader(System.in));
                 
                 while(true) {
                     String str = br.readLine();
                     if("quit".equals(str))
                         break;
                     DatagramPacket packet =     //创建packet相当于创建集装箱
                             new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
                     socket.send(packet);            //发货
                 }
                 socket.close();
             }  catch (IOException e) {
                 e.printStackTrace();
             }finally {
                 try {
                     socket.close();
                     br.close();
                 } catch (Exception e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
         }
      }
      
    • 接收端

      class Receive1 extends Thread {
         public void run() {
             DatagramSocket socket = null;
             DatagramPacket packet = null;
             try {
                 socket = new DatagramSocket(6666);  //创建socket相当于创建码头
                 packet = new DatagramPacket(new byte[1024], 1024);//创建packet相当于创建集装箱
                 
                 while(true) {
                     socket.receive(packet);                                             //接收货物
                     byte[] arr = packet.getData();
                     int len = packet.getLength();
                     String ip = packet.getAddress().getHostAddress();
                     System.out.println(ip + ":" + new String(arr,0,len));
                 }
             } catch (IOException e) {
                 
                 e.printStackTrace();
             }finally {
                 socket.close();
             }
         }
      }
      
    • 启动

      public static void main(String[] args) {
         new Receive1().start();
         new Send1().start();
      }
      

五、TCP协议

  1. 定义

    • 客户端和服务器间的交流,客户端发送信息,服务器接收到并返回信息
    • 长连接
  2. 使用步骤

    客户端

    • 创建Socket连接服务器(指定ip地址,端口号)通过ip地址找对应的服务器
    • 调用Socket的getInputStream()和getOutputStream()方法获取和服务器相连的IO流
    • 客户端输入流可以读取服务器端输出流写出的数据
    • 客户端输出流可以写出数据到服务端的输入流

    服务端

    • 创建ServerSocket(需要指定接口号)
    • 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
    • 调用Socket的getInputStream()和getOutputSream()方法获取和客户端相连的IO流
    • 服务端输入流可以读取客户端输出流写出的数据
    • 服务器输出流可以写出数据到客户端的输入流
  3. 演示

    • 客户端

      public static void main(String[] args) throws Exception {
         Socket socket = new Socket("127.0.0.1", 6666);
         
         //发送信息
         OutputStream stream = socket.getOutputStream();
         
         String str = "我很中意你呀";
         stream.write(str.getBytes());
         
         //接收返回的信息
         InputStream is = socket.getInputStream();
         byte[] bs = new byte[1024];
         int len ;
         len=is.read(bs);
         System.out.println(new String(bs,0,len));
         
         socket.close();
      }
      
    • 服务端

      public static void main(String[] args) throws Exception {
         ServerSocket server = new ServerSocket(6666);
         
         Socket socket = server.accept();
         
         //接收信息
         InputStream is = socket.getInputStream();
         byte[] bs = new byte[1024];
         int len ;
         len = is.read(bs);
         System.out.println(new String(bs,0,len));
         
         //返回信息
         OutputStream stream = socket.getOutputStream();
         
         String str = "哎呀, 知道了";
         stream.write(str.getBytes());
      
         socket.close();
      }
      
  4. TCP传输优化

    • 客户端

      public static void main(String[] args) throws Exception {
         Socket socket = new Socket("127.0.0.1", 6666);
         
         //接收信息
         InputStream is = socket.getInputStream();
         BufferedReader br = new BufferedReader(new InputStreamReader(is));
         
         //发送信息
         OutputStream stream = socket.getOutputStream();
         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(stream));
         
         BufferedReader sca = new BufferedReader(new InputStreamReader(System.in));
         String str;
         while(true){
             str = sca.readLine();
             if ("结束".equals(str)) {
                 break;
             }
             bw.write(str);
             bw.newLine();
             bw.flush();
             //接收返回的信息
             str = br.readLine();
             System.out.println(str);
         }
         
         socket.close();
      }
      
    • 服务端

      public static void main(String[] args) throws Exception {
         ServerSocket server = new ServerSocket(6666);
         
         Socket socket = server.accept();
         
         //接收信息
         InputStream is = socket.getInputStream();
         BufferedReader br = new BufferedReader(new InputStreamReader(is));
         
         //发送信息
         OutputStream stream = socket.getOutputStream();
         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(stream));
         
         BufferedReader sca = new BufferedReader(new InputStreamReader(System.in));
         
         String str ;
         while(true){
             str = br.readLine();
             System.out.println(str);
             str = sca.readLine();
             if("结束".equals(str))
                 break;
             bw.write(str);
             bw.newLine();
             bw.flush();
         }
         socket.close();
      }
      

六、多线程服务器

  1. 定义

    • 每当一个请求过来,服务器就会产生一个Socket连接,为了避免前面的socket阻碍后面的socket运行,我们必须创建一个新的线程来发送请求
  2. 演示

    public static void main(String[] args) throws Exception {
     ServerSocket server = new ServerSocket(9999);   //创建服务器
     while(true) {
         Socket socket = server.accept();        //接受客户端的请求
         //创建一个线程来处理请求
         new Thread() {
             public void run() {
                 try {
                     BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                     PrintStream ps = new PrintStream(socket.getOutputStream());
                     ps.println("欢迎咨询千锋互联");
                     System.out.println(br.readLine());
                     ps.println("报满了,请报下一期吧");
                     System.out.println(br.readLine());
                     socket.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }.start();
     }
    }
    

七、文件上传

  1. 定义

    • 其实就是通过流从本地文件中读取数据,通过网络传输到服务器
    • 服务器在接收到数据之后再存储到本地
  2. 演示

    • 客户端

      public static void main(String[] args) throws Exception {
      
         //1.和服务器建立连接
         Socket socket = new Socket("127.0.0.1", 9999);
         
         //2.获取输出流,往服务器写数据
         //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
         OutputStream os = socket.getOutputStream();
         
         //3.获取输入流,获取服务器发送过来的数据
         BufferedReader br = new BufferedReader(new InputStreamReader( socket.getInputStream()));
         
         FileInputStream fis = new FileInputStream("d:\\骑在银龙的背上.mp3");
         
         
         byte[] bs = new byte[1024];
         int len ;
         while ((len=fis.read(bs))!=-1) {
             os.write(bs, 0, len);
         }
         socket.shutdownOutputStream();
         
         String str = br.readLine();
         if("200".equals(str))
             System.out.println("文件上传成功");
         else
             System.out.println("文件上传失败");
         
         socket.close();
      }
      
    • 服务端

      public static void main(String[] args) throws Exception {
      
         //服务端必须先启动
         ServerSocket serverSocket = new ServerSocket(9999);
         
         //1.和客户端建立连接(被动)
         Socket socket = serverSocket.accept();
         
         //2.获取输入流,获取从客户端发送过来的数据
         InputStream is = socket.getInputStream();
         
         //3.获取输出流,往客户端写数据
         BufferedWriter bw = new BufferedWriter(new          OutputStreamWriter(socket.getOutputStream()));
         
         
         FileOutputStream fos = new FileOutputStream("d:\\音乐.mp3");
         
         byte[] bs = new byte[1024];
         int i ;
         
         while((i=is.read(bs))!=-1){
             fos.write(bs,0,i);
         }
         //写一个200回去表示成功
         bw.write("200");
         bw.newLine();
         bw.flush();
        
         fos.close();
         socket.close();
                 
      }
      

总结

  1. 网络传输的概述
    • ip:通过ip可以找到找到网络中的一台机器
    • port:通过端口号可以找到电脑中某个程序
    • ip+port:一个套接字
    • UDP:快,不安全,面向无连接
    • TCP:慢,安全,面向有连接
  2. UDP编码
    • DatagramSocket
    • DatagramPacket
    • DatagramPacket包裹着ip地址,端口号,数据
    • DatagramSocket发送包裹
    • 接收端和发送端是平等的
  3. TCP编码
    • Socket
    • ServerSocket
    • ServerSocket可以接收多个Socket,每接收一个客户端连接,就会创建一个Socket与客户端通信
    • TCP的最大优点:两端是由一个通道连接,可以随意传输数据,不会受到数据量大小的限制
    • 服务端一般与多线程配合使用
    • 查阅资料:思考TCP传输的缺点和解决办法?

作业

  1. 编程模拟文件的下载
  2. 从键盘录入地址,通过网络传输复制文件

你可能感兴趣的:(网络编程)