zoukankan      html  css  js  c++  java
  • TCP与UDP协议的理解及小示例

    UDP协议

    定义:User Datagram Protocol,用户数据报协议.
    主要作用:将网络数据压缩成数据包的形式。
    数据包格式:一个二进制数据的传输单位
    工作机制:蛮干型。
    它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。因此,在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。

    优势:速度快,较安全。
    与TCP协议相比,UDP协议排除了信息可靠传递机制,也就是减少了TCP协议中提供数据包分组、组装和排序的过程需要的时间消耗。其次,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。

    劣势:可靠性差。
    UDP协议是一种无连接的传输协议,排除信息可靠传递机制带来速度优势的同时,显然降低了可靠性的需求,也就是UDP协议无法得知其是否安全、完整到达的。

    应用
    因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。
    在生活中音频、视频和普通数据都可以采用UDP协议来进行数据传输,比如腾讯QQ这些社交软件也多采用UDP。

    TCP协议

    TCP:Transmission Control Protocol 传输控制协议
    主要作用:把数据流分割成适当长度的报文段之后进行传输
    工作机制:紧小细微型。
    面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据包之前必须先建立一个TCP连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。在一个TCP连接中,仅有两方进行彼此通信。而UDP更像是发短信,将发送方所有的信息,将所有信息一股脑儿全扔到网络中。

    优势:可靠性好

    • 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。当TCP收到发自TCP连接另一端的数据,它将发送一个确认。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。
    • TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)
    • 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
    • TCP的接收端必须丢弃重复的数据
    • 量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

    劣势:速度慢,占用系统资源高,易被攻击
    TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间。
    由于在每台设备上都需要维护所有的传输连接,而每个连接都会占用系统的CPU、内存等硬件资源。
    此外,由于TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

    应用
    当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。
    在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输……

    原文:https://blog.csdn.net/Tong_jy/article/details/78477634

    简单的TCP示例

    TCP服务端

    /**
     * @CalssName TcpServer
     * @Description tcp服务端
     * @since JDK 1.8
     */
    public class TcpServer {
    
        private ServerSocket serverSocket;
        private int port = 8090;
    
        public TcpServer() throws IOException {
            this.serverSocket = new ServerSocket(port);
        }
    
        public void start() throws IOException {
            System.out.println("服务端启动....");
            try (
                    Socket socket = serverSocket.accept();
                    InputStream inputStream = socket.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                    BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
            ) {
                while (true) {
                    String msg = bufferedReader.readLine();
                    System.out.println("收到消息:" + msg);
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            TcpServer tcpServer = new TcpServer();
            tcpServer.start();
        }
    }
    

    TCP客户端

    /**
     * @CalssName TcpClient
     * @Description tcp客户端
     * @since JDK 1.8
     */
    public class TcpClient {
        private Socket socket;
        private String connectHost = "localhost";
        private int connectPort = 8090;
    
        public TcpClient() throws IOException {
            this.socket = new Socket(connectHost, connectPort);
        }
    
        public void send() throws IOException {
            System.out.println("客户端启动...");
            try (
                    Socket stk = this.socket;
                    OutputStream outputStream = stk.getOutputStream();
                    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8");
                    PrintWriter printWriter = new PrintWriter(outputStreamWriter, true)
            ) {
                Scanner sc = new Scanner(System.in);
                while (true) {
                    printWriter.println(sc.nextLine());
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            TcpClient tcpClient = new TcpClient();
            tcpClient.send();
        }
    }
    

    使用TCP的简易聊天室

    服务端

    /**
     * @CalssName TcpServer
     * @Description tcp服务端
     * @since JDK 1.8
     */
    public class TcpServer {
    
        private ServerSocket serverSocket;
        private int port = 8090;
    
        private List<PrintWriter> printWriters;
    
        public TcpServer() throws IOException {
            this.serverSocket = new ServerSocket(port);
            this.printWriters = Collections.synchronizedList(new ArrayList<>());
        }
    
        public void start() throws IOException {
            System.out.println("服务启动....");
            try (ServerSocket serSocket = this.serverSocket) {
                for (; ; ) {
                    Socket socket = serSocket.accept();
                    System.out.println("链接成功:" + socket);
                    new Thread(new ForwardingMsgRunnable(this.printWriters, socket)).start();
                }
            }
        }
    
        //转发消息到所有客户端线程
        class ForwardingMsgRunnable implements Runnable {
            private List<PrintWriter> printWriters;
            private Socket socket;
            private PrintWriter printWriter;
    
            public ForwardingMsgRunnable(List<PrintWriter> printWriters, Socket socket) throws IOException {
                this.printWriters = printWriters;
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(socket.getOutputStream(), "utf-8");
                this.printWriter = new PrintWriter(outputStreamWriter, true);
                this.printWriters.add(printWriter);
                this.socket = socket;
            }
    
            @Override
            public void run() {
                try (
                        Socket skt = this.socket;
                        InputStream inputStream = skt.getInputStream();
                        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                        BufferedReader br = new BufferedReader(inputStreamReader);
                ) {
                    String msg = "1";
                    while (msg != null) {
                        msg = br.readLine();
                        if (msg != null) {
                            //用索引遍历,别的线程remove没问题
                            for (int i = 0; i < this.printWriters.size(); i++) {
                                this.printWriters.get(i).println(msg);
                            }
                        } else {
                            this.printWriters.remove(this.printWriter);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            TcpServer tcpServer = new TcpServer();
            tcpServer.start();
        }
    }
    

    客户端

    /**
     * @CalssName TcpClient
     * @Description tcp客户端
     * @since JDK 1.8
     */
    public class TcpClient {
        private Socket socket;
        private String connectHost = "localhost";
        private int connectPort = 8090;
    
        public TcpClient() throws IOException {
            this.socket = new Socket(connectHost, connectPort);
        }
    
        public void send() throws IOException {
            System.out.println("客户端启动...");
            //给服务器发消息
            try (
                    Socket skt = this.socket;
                    OutputStream outputStream = skt.getOutputStream();
                    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8");
                    PrintWriter printWriter = new PrintWriter(outputStreamWriter, true);
                    Scanner sc = new Scanner(System.in);
            ) {
                System.out.print("用户名:");
                String username = sc.nextLine();
                //接收消息处理
                new Thread(new ShowMsgRunnable(this.socket)).start();
                while (!skt.isClosed()) {
                    String inStr = sc.nextLine();
                    if ("exit".equals(inStr)) break;
                    printWriter.println(username + ":" + inStr);
                }
                System.out.println("exiting...");
            }
        }
    
        //显示消息
        class ShowMsgRunnable implements Runnable {
    
            private Socket socket;
    
            public ShowMsgRunnable(Socket socket) {
                this.socket = socket;
            }
    
            @Override
            public void run() {
                try (
                        Socket skt = this.socket;
                        InputStreamReader inputStreamReader = new InputStreamReader(skt.getInputStream());
                        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                ) {
                    System.out.println("显示消息:");
    
                    while (!skt.isClosed()) {
                        String msg = bufferedReader.readLine();
                        System.out.println(msg);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) throws IOException {
            TcpClient tcpClient = new TcpClient();
            tcpClient.send();
        }
    }
    

    简单UDP示例

    服务端

    /**
     * @CalssName udpServer
     * @Description Udp服务端
     * @since JDK 1.8
     */
    public class UdpServer {
        private DatagramSocket server;
    
        public UdpServer() throws SocketException {
            this.server = new DatagramSocket(8060);
        }
    
        public void start() {
    
            System.out.println("服务端启动...");
            DatagramPacket datagramPacket = new DatagramPacket(new byte[32], 32);
    
            try (DatagramSocket datagramSocket = this.server) {
                datagramSocket.receive(datagramPacket);
                byte[] bytes = datagramPacket.getData();
                System.out.println("收到数据:" + new String(bytes, "utf-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws IOException {
            new UdpServer().start();
        }
    }
    

    客户端

    /**
     * @CalssName UdpClient
     * @Description Udp客户端
     * @since JDK 1.8
     */
    public class UdpClient {
    
        private DatagramSocket client;
    
        public UdpClient() throws SocketException {
            this.client = new DatagramSocket();
        }
    
        public void start() {
            try (
    
                    DatagramSocket datagramSocket = this.client;
            ) {
                String msg = "hello server,I am udp client...";
                DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes("utf-8"), msg.length(), InetAddress.getByName("localhost"), 8060);
                datagramSocket.send(datagramPacket);
            } catch (UnsupportedEncodingException | UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws SocketException {
            new UdpClient().start();
        }
    }
  • 相关阅读:
    LAMP环境搭建
    Httpd
    MySQL常用配置和性能压力测试:MySQL系列之十五
    MySQL的高可用实现:MySQL系列之十四
    MySQL的复制:MySQL系列之十三
    备份与恢复:MySQL系列之十二
    日志记录:MySQL系列之十一
    事务隔离实现并发控制:MySQL系列之十
    SpringMVC上传文件(图片)并保存到本地
    W10如何开启LinuxBash及安装Ubuntu
  • 原文地址:https://www.cnblogs.com/yhongyin/p/11117709.html
Copyright © 2011-2022 走看看