Java通讯协议之TCP与UDP协议

TCP与UDP协议

1、UDP

	UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP
协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,
由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
1.1 、UDP程序交互的流程
*发送端
   1、创建DatagramSocket对象
   2、创建DatagramPacket对象,并封装数据
   3、发送数据
   4、释放流资源
*接收端
   1、创建DatagramSocket对象
   2、创建DatagramPacket对象
   3、接收数据存储到DatagramPacket对象中
   4、获取DatagramPacket对象的内容
   5、释放流资源

1.2、简单示例

package com.protocol;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
* @author Guku
* @version 1.0
* @date 2021/8/30 13:35
* @describe
*/
public class UdpProtocol {
  //发送
  public static void main(String[] args) {
      byte[] bytes = "suhua nice".getBytes(); // 发送内容
      int port = 10086;   // 发送port
      int length = bytes.length; // 发送内容长度
      String host = "127.0.0.1"; // 发送host
      try {
          SendUdpProtocol(bytes , length , port , host);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }
  /**
   * UPD协议发送 / 发送端的构造方法要接收存放了发送数据的字节数组,还需要指定发送端IP地址和端口号
   * @param buf : string.getBytes()
   * @param length : buf.length
   *        InetAddress.getByName(host)
   * @param port : port
   * @throws Exception
   */
  public static void SendUdpProtocol(byte buf[] , int length, int port , String host) throws Exception {
      //1、创建udp服务,通过DategramSocket对象;
      DatagramSocket datagramSocket = new DatagramSocket();

      //2、确定数据,并封装数据到数据包.DatagramPacket(byte[] buf, int length, InetAddress address, int port)
      DatagramPacket datagramPacket = new DatagramPacket(buf, length, InetAddress.getByName(host),port);

      //3、通过socket服务,将已有的数据报发送出去,通过send方法。
      datagramSocket.send(datagramPacket);

      //4、关闭资源
      datagramSocket.close();
  }


  //接收
  static class ReceiveUdp{
      /**
       * 接收
       * @param args
       */
      public static void main(String[] args) {
          byte[] bytes = new byte[1024];
          int port = 10086;
          int length = bytes.length;
          try {
              ReceiveUdpProtocol(bytes  ,length , port);
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
      /**
       * UPD协议接收 / 接收端的构造方法只需要接收一个字节数组来存放接收到的数据
       * @param buf : string.getBytes()
       */
      public static void ReceiveUdpProtocol(byte buf[] ,int length , int port) throws Exception{
          //1、创建DatagramSocket对象,并指定端口号
          DatagramSocket datagramSocket=new DatagramSocket(port);
          //2、创建DatagramPacket对象, 创建一个空的仓库 buf[] --> byte[] bytes = new byte[1024];
          DatagramPacket datagramPacket=new DatagramPacket(buf, length);
          //3、接收数据存储到DatagramPacket对象中
          datagramSocket.receive(datagramPacket);
          //4、获取DatagramPacket对象的内容
          //InetAddress address = datagramPacket.getAddress(); //谁发来的数据  getAddress() 本质获取IP
          String ip=datagramPacket.getAddress().getHostAddress(); // IP地址
          String data=new String(datagramPacket.getData(),0,datagramPacket.getLength()); //发送过来的数据
          int count = datagramPacket.getLength(); //发来了多少数据 getLength() / 包括空格符号长度

          System.out.println("IP地址:"+ip
                  +"\n发来了多少数据:"+count
                  +"\n发送过来的数据:"+data);
          //5、释放流资源
          datagramSocket.close();
      }
  }
}

2、TCP

TCP协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,
然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
每次连接的创建都需要经过“三次握手”。
 *第一次握手,客户端向服务器端发出连接请求,等待服务器确认,
 *第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求,
 *第三次握手,客户端再次向服务器端发送确认信息,确认连接。
2.1、TCP程序交互的流程
*客户端
   1、创建客户端的Socket对象
   2、获取Socket的输出流对象
   3、写数据给服务器
   4、获取Socket的输入流对象
   5、使用输入流,读反馈信息
   6、关闭流资源
*服务端
   1、创建服务器端ServerSocket对象,指定服务器端端口号
   2、开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
   3、通过客户端的Socket对象,获取客户端的输入流,为了实现获取客户端发来的数据
   4、通过客户端的输入流,获取流中的数据
   5、通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
   6、通过客户端的输出流,写数据到流中
   7、关闭流资源
2.2、简单示例
package com.protocol;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author Guku
 * @version 1.0
 * @date 2021/8/30 14:20
 * @describe
 */
public class TcpProtocol {
    //服务端 / 发送
    public static void main(String[] args) throws IOException {
        int port = 10086;
        SendTcpProtocol(port);
    }
    private static void SendTcpProtocol(int port) throws IOException{
        //1、创建服务器ServerSocket对象(指定服务器端口号)
        ServerSocket serverSocket = new ServerSocket(port);
        //2、开启服务器了,等待客户端的连接,当客户端连接后,可以获取到连接服务器的客户端Socket对象
        Socket socket = serverSocket.accept();
        //3、给客户端反馈信息
        /*
         * a、获取客户端的输出流
         * b、在服务端端,通过客户端的输出流写数据给客户端
         */
        //a、获取客户端的输出流
        OutputStream outputStream = socket.getOutputStream();
        //b、在服务端端,通过客户端的输出流写数据给客户端
        outputStream.write("我就是通过TCP协议发送的数据,我叼不叼!".getBytes());
        //4、关闭流资源
        outputStream.close();
        socket.close();
        //ss.close();  服务器流 通常都是不关闭的
    }
    //客户端 / 接收
    static class ReceiveTcp {
        public static void main(String[] args) throws IOException{
            String host = "127.0.0.1";
            int port = 10086;
            ReceiveTcpProtocol(host , port);
        }
        private static void ReceiveTcpProtocol(String host , int port) throws IOException{
            //1、创建客户端Socket对象,(指定要连接的服务器地址与端口号)
            Socket socket = new Socket(host, port);
            //2、获取服务器端的反馈回来的信息
            InputStream inputStream = socket.getInputStream();
            //获取获取流中的数据
            byte[] buffer = new byte[1024];
            //把流中的数据存储到数组中,并记录读取字节的个数
            int length = inputStream.read(buffer);
            //显示数据
            System.out.println("数据:"+new String(buffer, 0 , length) );
            //3、关闭流资源
            inputStream.close();
            socket.close();
        }
    }



    //模拟文件发送 / 服务端 / 发送
    static class TcpFileSend{
        public static void main(String[] args) throws IOException{
            String fileUrl = "E:\\用于输入字节的JPG(空).jpg";
            int port = 10086;
            fileSend(fileUrl , port);
        }
        private static void fileSend(String fileUrl , int port) throws IOException {
            //1、创建服务器,等待客户端连接
            ServerSocket serverSocket = new ServerSocket(port);
            Socket clientSocket = serverSocket.accept();
            //显示哪个客户端Socket连接上了服务器
            InetAddress ipObject = clientSocket.getInetAddress();//得到IP地址对象
            String ip = ipObject.getHostAddress(); //得到IP地址字符串
            System.out.println("我是服务端IP地址:" + ip);

            //2、获取Socket的输入流
            InputStream inputStream = clientSocket.getInputStream();
            //3、创建目的地的字节输出流   E:\img\黑色使者-亚索.jpg
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileUrl));
            //4、把Socket输入流中的数据,写入目的地的字节输出流中
            byte[] bytes = new byte[1024];
            int length = -1;
            while((length = inputStream.read(bytes)) != -1){
                //5、写入目的地的字节输出流中
                bufferedOutputStream.write(bytes, 0, length);
            }

            //-----------------反馈信息---------------------
            //6、获取Socket的输出流, 作用:写反馈信息给客户端
            OutputStream out = clientSocket.getOutputStream();
            //7、反馈信息给客户端
            out.write("图片上传成功".getBytes());

            //8、关闭资源
            out.close();
            bufferedOutputStream.close();
            inputStream.close();
            clientSocket.close();
            //serverSocket.close();
        }
    }
    //模拟文件接收 / 客户端 / 接收
    static class TcpFileReceive{
        public static void main(String[] args) throws IOException {
            String host = "127.0.0.1";
            int port = 10086;
            //用于输出字节的JPG
            String fileUrl = "E:\\img\\黑色使者-亚索.jpg";
            fileReceive(host , port , fileUrl);
        }
        private static void fileReceive(String host , int port , String fileUrl) throws IOException{
            //1、创建客户端Socket,连接服务器
            Socket socket = new Socket(host, port);
            //2、获取Socket流中的输出流,功能:用来把数据写到服务器
            OutputStream outputStream = socket.getOutputStream();
            //3、创建字节输入流,功能:用来读取数据源(图片)的字节
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(fileUrl));
            //4、把图片数据写到Socket的输出流中(把数据传给服务器)
            byte[] bytes = new byte[1024];
            int length = -1;
            while ((length = bufferedInputStream.read(bytes)) != -1){
                //把数据写到Socket的输出流中
                outputStream.write(bytes, 0, length);
            }
            //5、客户端发送数据完毕,结束Socket输出流的写入操作,告知服务器端
            socket.shutdownOutput();

            //-----------------反馈信息---------------------
            //6、获取Socket的输入流  作用: 读反馈信息
            InputStream inputStream = socket.getInputStream();
            //7、读反馈信息
            byte[] info = new byte[1024];
            //8、把反馈信息存储到info数组中,并记录字节个数
            int count = inputStream.read(info);
            //显示反馈结果
            System.out.println(new String(info, 0, count) );

            //9、关闭流
            inputStream.close();
            bufferedInputStream.close();
            outputStream.close();
            socket.close();
        }

        //实现服务器端可以同时接收多个客户端上传的文件
        private static void filesReceive(String host , int port , String fileUrl) throws IOException{
            //1、创建服务器,等待客户端连接
            ServerSocket serverSocket = new ServerSocket(port);
            //实现多个客户端连接服务器的操作
            while(true){
                final Socket clientSocket = serverSocket.accept();
                //启动线程,完成与当前客户端的数据交互过程
                new Thread(){
                    public void run() {
                        try{
                            //显示哪个客户端Socket连接上了服务器
                            InetAddress inetAddress = clientSocket.getInetAddress();//得到IP地址对象
                            String ip = inetAddress.getHostAddress(); //得到IP地址字符串
                            System.out.println("我是服务端IP:" + ip);

                            //2/获取Socket的输入流
                            InputStream inputStream = clientSocket.getInputStream();
                            //3、创建目的地的字节输出流   "E:\\img\\黑色使者-亚索.jpg"
                            BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\"+ip+"("+System.currentTimeMillis()+").jpg"));
                            //4、把Socket输入流中的数据,写入目的地的字节输出流中
                            byte[] bytes = new byte[1024];
                            int len = -1;
                            while((len = inputStream.read(bytes)) != -1){
                                //写入目的地的字节输出流中
                                fileOut.write(bytes, 0, len);
                            }

                            //-----------------反馈信息---------------------
                            ///5、获取Socket的输出流, 作用:写反馈信息给客户端
                            OutputStream out = clientSocket.getOutputStream();
                            ///6、写反馈信息给客户端
                            out.write("图片上传成功".getBytes());

                            out.close();
                            fileOut.close();
                            inputStream.close();
                            clientSocket.close();
                        } catch(IOException e){
                            e.printStackTrace();
                        }
                    };
                }.start();
            }
            //serverSocket.close();
        }
    }
}

更详细请看原文作者(点我)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值