1、概述


  • 计算机之间通过传输介质、通信设施和网络通信协议互联,实现资源共享和数据传输。而我们的网络编程就是使用程序使互联网的两个(或多个)计算机之间进行数据传输。当然java语言,为了实现两个计算机之间的数据传输,提供了一系列的接口,使得开发人员可以方便的实现。

2、OSI与TCP/IP模型


模型对比

image-20200623105550900.png

  • TCP/IP支持跨层封装 ;但OSI不支持
  • TCP/IP仅仅支持IP网络协议 ;OSI支持多种网络层协议
  • TCP是面向连接的可靠的传输协议
  • UDP是非面向连接的不可靠的传输协议

TCP/IP模型中的协议剖析

image-20200623110038567.png

  • 该模型中几个主要的协议术语及其作用

    • TCP(传输控制协议):通过使用一个校验码检验数据是否发生错误,在接收和转发中都使用计算校验和,并同时对数据进行加密

    • UDP(用户数据报协议):UDP使用底层的互联网协议来传送报文,同IP一样提供不可靠的无连接数据包传输服务。它不提供报文到达确认、排序、及流量控制等功能

    • FTP(文件传输协议):让用户连接上一个远程计算机(这些计算机上运行着FTP服务器程序)察看远程计算机有哪些文件,然后把文件从远程计算机上拷到本地计算机,或把本地计算机的文件送到远程计算机去。

    • SMTP(邮件消息传输协议):SMTP是一种提供可靠且有效电子邮件传输的协议。它是建立在FTP文件传输服务上的一种邮件服务,主要用于传输系统之间的邮件信息并提供来信有关的通知。

      SMTP重要的特性之一是它能跨越网络传输邮件,也即“SMTP邮件中继”。使用SMTP,可实现相同网络上处理机之间的邮件传输,也可以通过中继器或网关实现某处理机与其它网络之间的邮件传输。具有域名服务系统(DNS)功能的邮件交换服务器还可以用来识别出传输邮件的下一跳IP地址。

3、IP


  • IP(网际协议) :提高网络可扩展性,为主机提供一种无连接的数据传输服务
  • 唯一定位一台网络上的计算机
  • 127.0.0.1为本机地址localhost

4、端口(port)


  • 端口表示计算机的一个程序的进程

    • 不同的进程有不同的端口号,并且端口号不能重复(单个协议下)

    • 端口号范围限制为 0 ~ 65535

    • 端口分类

      • 公有端口 0 ~ 1023

        • HTTP :80
        • HTTPS :443
        • FTP : 21
        • Telnet :23
      • 程序注册端口: 1024 ~ 49151 分配用户或程序

        • Tomcat :8080
        • MySQL :3306
        • Oracle :1521
      • 动态私有 49152 ~ 65535

         netstat -ano #查看所有端口
         netstat -ano|findstr "8080" # 查看指定端口
         tasklist|findstr "8696" # 查看指定端口的进程
         ctrl + shift +ESC # 调用任务管理器
        

5、TCP实现聊天


  • 客户端(Client)

    1. 获取服务端的地址与端口号

    2. 连接服务器端口,建立socket连接

    3. 发送信息(IO流)

    4. 关闭资源

      Socket socket = null;
      OutputStream os = null;
              try {
      
                  //首先要知道服务端的地址和端口号
                  InetAddress serverIp = InetAddress.getByName("127.0.0.1");
                  int port = 9999;
      
                  //建立socket连接
                  socket = new Socket(serverIp,9999);
      
                  //发送信息
                  os = socket.getOutputStream();
                  os.write("我们已经成为好友,可以开始聊天".getBytes());
              } catch (Exception 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();
                      }
                  }
      
              }
      
  • 服务端(Server)

    1. 建立socket服务器端口

    2. 调用端口的accept方法,等待用户端连接

    3. 读取用户信息(IO流)的inputStream

    4. 建立管道流,把数据从字节流转换为字符流

    5. 关闭资源

          ServerSocket serverSocket = null;
           Socket socket = null;
            InputStream is = null;
              ByteArrayOutputStream baos = null;
              try {
                  //给一个服务端的地址
                   serverSocket = new ServerSocket(9999);
                  //等待客户端接入
                   socket = serverSocket.accept();
                  //读取客户端信息
                   is = socket.getInputStream();
      
                  //管道流
                   baos = new ByteArrayOutputStream();
                  byte[] buffer = new byte[1024];
                  int len;
                  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 (socket != null){
                      try {
                          socket.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
                  if (serverSocket != null){
                      try {
                          serverSocket.close();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              }
      

6、TCP实现文件上传


  • 服务端(Server)

     public static void main(String[] args) throws Exception {
             //创建服务
             ServerSocket serverSocket = new ServerSocket(9000);
             //监听客户端连接
             Socket socket = serverSocket.accept();
             //获取输入流
             InputStream is = socket.getInputStream();
             //此处写文件路径最好使用绝对路径,否则会报错
             File file = new File("G://IDEA_Project/FIST/src/receive.jpg");
             //文件输出
             FileOutputStream fos = new FileOutputStream(file);
             byte[] buffer = new byte[1024];
             int len;
             while ((len = is.read(buffer))!=-1){
                 fos.write(buffer,0,len);
             }
    
             //通知客户端接收完毕
             OutputStream os = socket.getOutputStream();
             os.write("服务端接收完毕,你可以断开连接".getBytes());
    
             //关闭资源 (后创建先关闭原则)
             fos.close();
             is.close();
             socket.close();
             serverSocket.close();
         }
    
  • 客户端(client)

     public static void main(String[] args) throws Exception {
             //创建一个socket连接
             Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
             //建立一个输出流
             OutputStream os = socket.getOutputStream();
             //此处写文件路径最好使用绝对路径,否则会报错
             File file = new File("G://IDEA_Project/FIST/src/lld.jpg");
             //读取文件
             FileInputStream fis = new FileInputStream(file);
             //写入文件
             byte[] buffer = new byte[1024];
             int len;
             while ((len= fis.read(buffer)) !=-1){
                 os.write(buffer,0,len);
             }
             //通知服务器,我已经结束啦
             socket.shutdownOutput();
    
             //确认服务端接收完毕,才断开连接
             InputStream is = socket.getInputStream();
    
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
             byte[] buffer2 =new byte[1024];
             int len2;
             while ((len2 = is.read(buffer2)) != -1){
                 baos.write(buffer2,0,len2);
             }
             System.out.println(baos.toString());
             //关闭资源 (后创建先关闭原则)
             baos.close();
             is.close();
             fis.close();
             os.close();
             socket.close();
         }
    

7、UDP实现消息的发送


  • 客户端

     public static void main(String[] args) throws Exception {
             //建立一个socket
             DatagramSocket socket = new DatagramSocket();
             //建立数据包
             String msg = "Hello,Server!";
             //发送目的地
             InetAddress localhost = InetAddress.getByName("localhost");
             int port =9090;
             //数据,数据长度的起始,目的地信息
             DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
             //发送包
             socket.send(packet);
             //关闭流
             socket.close();
    
         }
    
  • 服务端

     public static void main(String[] args) throws Exception {
             //开放端口
             DatagramSocket socket = new DatagramSocket(9090);
             //接收数据包
             byte[] buffer = new byte[1024];
             DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
             //接收包
             socket.receive(packet);
             //打印输出目的端地址及数据内容
             System.out.println(packet.getAddress().getHostName());
             System.out.println(new String(packet.getData(), 0, packet.getLength()));
             //关闭流
             socket.close();
         }
    

8、UDP实现循环发送


  • Sender端

    ```java
    public static void main(String[] args) throws Exception {

         //建立端口
         DatagramSocket socket = new DatagramSocket(8888);
    
         //数据,通过控制台输入数据
         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
       while (true){
           String data =  reader.readLine();
           byte[] datas = data.getBytes();

           DatagramPacket packet = new DatagramPacket(datas,0,datas.length,new InetSocketAddress("localhost",6666));

           socket.send(packet);

           if (data.equals("bye")){
               break;
           }
       }

       socket.close();
   }



+ **Receive端**

   ```java
   public static void main(String[] args) throws Exception {
           DatagramSocket socket = new DatagramSocket(6666);
           while (true){

               byte[] container = new byte[1024];
               DatagramPacket packet = new DatagramPacket(container, 0, container.length);
               //阻塞式接收
               socket.receive(packet);

               byte[] data = packet.getData();
               String receiveData = new String(data, 0, data.length);
               System.out.println(receiveData);

               if (receiveData.equals("bye")){
                   break;
               }

           }
           //关闭流
           socket.close();
       }
  • 实际示例:
    • 在线咨询:通信双方既是发送方,也是接收方

请我喝[茶]~( ̄▽ ̄)~*

Peter Pan 微信支付

微信支付

Peter Pan 支付宝

支付宝