利用udp模擬arq停止等待協(xié)議

停止等待arq協(xié)議:
停止等待協(xié)議(stop-and-wait)是最簡單但也是最基礎(chǔ)的數(shù)據(jù)鏈路層協(xié)議黄伊。很多有關(guān)協(xié)議的基本概念都可以從這個協(xié)議中學(xué)習(xí)到还最。“停止等待”就是每發(fā)送完一個分組就停止發(fā)送扶叉,等待對方的確認(rèn)枣氧。在收到確認(rèn)后再發(fā)送下一個分組。

由于這里我們采用的是端對端的傳輸酪劫,所以我們并沒有采用tcp進(jìn)行流式套接字的傳輸,而是采用udp搪桂,進(jìn)行的數(shù)據(jù)報的傳輸。

UDP 是User Datagram Protocol的簡稱魄藕, 中文名是用戶數(shù)據(jù)報協(xié)議,是OSI(Open System Interconnection寝姿,開放式系統(tǒng)互聯(lián)) 參考模型中一種無連接的傳輸層協(xié)議埃篓,提供面向事務(wù)的簡單不可靠信息傳送服務(wù)架专,IETF RFC 768是UDP的正式規(guī)范部脚。UDP在IP報文的協(xié)議號是17

UDP協(xié)議全稱是用戶數(shù)據(jù)報協(xié)議[1] ,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包钱雷,是一種無連接的協(xié)議。在OSI模型中灿椅,在第四層——傳輸層操刀,處于IP協(xié)議的上一層。UDP有不提供數(shù)據(jù)包分組欢唾、組裝和不能對數(shù)據(jù)包進(jìn)行排序的缺點,也就是說杏头,當(dāng)報文發(fā)送之后醇王,是無法得知其是否安全完整到達(dá)的。UDP用來支持那些需要在計算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用滥朱。包括網(wǎng)絡(luò)視頻會議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用UDP協(xié)議根暑。UDP協(xié)議從問世至今已經(jīng)被使用了很多年,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋徙邻,但是即使是在今天UDP仍然不失為一項非常實用和可行的網(wǎng)絡(luò)傳輸層協(xié)議排嫌。

與所熟知的TCP(傳輸控制協(xié)議)協(xié)議一樣,UDP協(xié)議直接位于IP(網(wǎng)際協(xié)議)協(xié)議的頂層缰犁。根據(jù)OSI(開放系統(tǒng)互連)參考模型淳地,UDP和TCP都屬于傳輸層協(xié)議。UDP協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)包的形式帅容。一個典型的數(shù)據(jù)包就是一個二進(jìn)制數(shù)據(jù)的傳輸單位蕴茴。每一個數(shù)據(jù)包的前8個字節(jié)用來包含報頭信息,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)辫狼。

再解釋說明一下真椿,由于系統(tǒng)層面的原因锋八,會有自動校驗的措施胸竞,而且因為我做的是本機(jī)的測試腺占,出錯率也會很低尽爆,所以我們需要模擬出錯的情況募强。我們利用隨機(jī)數(shù)的算法,做了一個模擬的隨機(jī)數(shù)算法:



package UDP;

/**
 * Created by linSir on 16/10/5.用來模擬傳輸過程(udp)
 */
public class ImitateTransfer {

    /**
     * 用來模擬傳輸過程中的各種情況
     * 1.無差錯情況(60%) 狀態(tài)碼:100
     * 2.出現(xiàn)差錯
     * ①.接收到了玄括,做校驗時發(fā)現(xiàn)有錯(20%) 狀態(tài)碼:101
     * ②.傳輸過程中丟失數(shù)據(jù)(20%) 狀態(tài)碼:102
     * 3.確認(rèn)丟失和確認(rèn)遲到
     * ①.確認(rèn)丟失(20%)狀態(tài)碼:103
     * ②.確認(rèn)遲到(20%)狀態(tài)碼:104
     */

    public static String transfer_send() {//發(fā)送數(shù)據(jù)的三種情況

        int x = (int) (Math.random() * 10);//0-9
        switch (x) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                return "100";
            case 6:
            case 7:
                return "101";
            case 8:
            case 9:
                return "102";
        }
        return "100";
    }


    public static String transfer_confirm() {//發(fā)送確認(rèn)命令的三種情況

        int x = (int) (Math.random() * 10);//0-9
        switch (x) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                return "100";
            case 6:
            case 7:
                return "103";
            case 8:
            case 9:
                return "104";
        }
        return "100";
    }
}



這樣我們就做完了堡僻,模擬出錯的情況壤躲。下面我們看一下代碼客税,再解釋:

客戶端A(負(fù)責(zé)發(fā)送):



package UDP;


import 實驗二.ImitateTransfer;

import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.border.BevelBorder;

import java.net.*;
import java.util.Timer;

class Window extends JFrame {
    private static JTextArea showArea;
    private JTextField inputField;
    private static String IPadress;
    public static String[] datas = new String[1000];
    public static Timer timer = new Timer();
    public static int m = 0;

    public static void sentData(String Message) {
        byte[] dataarr = new byte[100010];
        dataarr = Message.getBytes();

        try {
            Thread.currentThread().sleep(500);//毫秒
        } catch (Exception e) {
        }


        try {
            InetAddress sentIP = InetAddress.getByName(IPadress);
            DatagramSocket dsset = new DatagramSocket(62000);
            DatagramPacket dprec = new DatagramPacket(dataarr, dataarr.length, sentIP, 64650);
            System.out.println(sentIP);
            // 從己方62000 端口發(fā)送到客戶端64650端口
            dsset.send(dprec);
            dsset.close();
            timer1(1);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void recieveData() {
        byte[] dataarr = new byte[100010];
        try {
            DatagramSocket dsset = new DatagramSocket(63300);
            // 監(jiān)聽己方63300端口收到的消息
            DatagramPacket dprec = new DatagramPacket(dataarr, dataarr.length);
            dsset.receive(dprec);
            dsset.close();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            showArea.append(format.format(new Date()) + "\n" + "新消息: " + new String(dataarr).trim() + "\n");

            String content2 = new String(dataarr).trim().split("\\(")[1].split("\\)")[0];
            System.out.println(content2);
            switch (content2) {
                case "成功接受":
                    timer1(0);
                    m++;
                    String type = "";
                    type = ImitateTransfer.transfer_send();
                    switch (type) {
                        case "100":
                            type = "成功發(fā)送";
                            break;

                        case "101":
                            type = "做校驗時出錯";
                            break;

                        case "102":
                            type = "傳送時丟失";
                            break;
                    }
                    sentData("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (正常發(fā)送)");
                    showArea.append("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (正常發(fā)送)" + "\n");
                    break;

                case "確認(rèn)丟失":

                    break;


                case "確認(rèn)超時":

                    break;

            }


        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startChat() {

        for (int i = 0; i < datas.length; i++) {
            datas[i] = String.valueOf(i);
        }

        JLabel displyjLabel = new JLabel("客戶端A");
        displyjLabel.setBounds(150, 10, 100, 15);
        JPanel myJPanel = new JPanel();
        myJPanel.setLayout(null);
        this.setContentPane(myJPanel);
        myJPanel.add(displyjLabel);
        showArea = new JTextArea();
        showArea.setLineWrap(true);
        JScrollPane scrollpane = new JScrollPane(showArea);
        scrollpane.setBounds(20, 30, 350, 350);
        scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.CYAN, Color.BLUE, null, null));
        scrollpane.setVisible(true);
        inputField = new JTextField();
        inputField.setBounds(20, 410, 280, 25);
        inputField.setVisible(true);
        myJPanel.add(scrollpane);
        JButton mybutton = new JButton("發(fā)送");
        mybutton.setBounds(310, 410, 60, 25);
        myJPanel.add(mybutton);
        myJPanel.add(inputField);
        myJPanel.setVisible(true);
        JButton quitjButton = new JButton("退出");
        quitjButton.setBounds(250, 450, 100, 30);
        myJPanel.add(quitjButton);
        quitjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                System.exit(0);
            }
        });
        JButton returnjButton = new JButton("返回主界面");
        returnjButton.setBounds(20, 450, 100, 30);
        myJPanel.add(returnjButton);
        returnjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                initWindow();
            }
        });
        this.setVisible(true);
        inputField.requestFocus();
        inputField.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                if (e.getKeyChar() == '\n') {

                    String type = "";
                    type = ImitateTransfer.transfer_send();
                    switch (type) {
                        case "100":
                            type = "成功發(fā)送";
                            break;

                        case "101":
                            type = "做校驗時出錯";
                            break;

                        case "102":
                            type = "傳送時丟失";
                            break;


                    }

                    //A發(fā)送:  數(shù)據(jù)為:1  類型為:成功發(fā)送;  (開始發(fā)送)
                    sentData("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (開始發(fā)送)");
                    inputField.setText("");
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    showArea.append("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (開始發(fā)送)" + "\n");
                    //sendMessage("A(發(fā)送)-" + datas[m] + "-" + 實驗二.ImitateTransfer.transfer_send() + "---開始發(fā)送");
                }
            }
        });
        mybutton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                // 當(dāng)發(fā)送鍵被按下
                String type = "";
                type = ImitateTransfer.transfer_send();
                switch (type) {
                    case "100":
                        type = "成功發(fā)送";
                        break;

                    case "101":
                        type = "做校驗時出錯";
                        break;

                    case "102":
                        type = "傳送時丟失";
                        break;


                }

                //A發(fā)送:  數(shù)據(jù)為:1  類型為:成功發(fā)送;  (開始發(fā)送)
                sentData("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (開始發(fā)送)");
                inputField.setText("");
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                showArea.append("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (開始發(fā)送)" + "\n");
                //sendMessage("A(發(fā)送)-" + datas[m] + "-" + 實驗二.ImitateTransfer.transfer_send() + "---開始發(fā)送");

            }
        });
    }

    public void initWindow() {
        JPanel myjPanel = new JPanel();
        myjPanel.setLayout(null);
        this.setContentPane(myjPanel);
        JLabel myjLabel = new JLabel("歡迎使用本聊天程序");
        myjLabel.setBounds(50, 100, 300, 40);
        myjLabel.setForeground(Color.cyan);
        myjLabel.setFont(new Font("HirakakuProN-W6", Font.BOLD, 30));
        JLabel tishiJLabel = new JLabel("請輸入對方的IP地址:");
        tishiJLabel.setBounds(15, 300, 150, 20);
        final JTextField ipJTextField = new JTextField("127.128.0.1");
        ipJTextField.setBounds(150, 300, 115, 20);
        JButton okJButton = new JButton("確定");
        okJButton.setBounds(280, 300, 70, 20);
        ipJTextField.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                if (e.getKeyChar() == '\n') {
                    startChat();
                }
            }
        });
        okJButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                IPadress = ipJTextField.getText();
                startChat();
            }
        });
        myjPanel.add(tishiJLabel);
        myjPanel.add(myjLabel);
        myjPanel.add(ipJTextField);
        myjPanel.add(okJButton);
        JButton quitjButton = new JButton("退出");
        quitjButton.setBounds(150, 350, 100, 30);
        myjPanel.add(quitjButton);
        quitjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                System.exit(0);
            }
        });
        this.setVisible(true);

    }

    public Window() {
        this.setBounds(420, 100, 400, 550);
        this.setLayout(null);
        this.setTitle("客戶端A");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initWindow();
        while (true) {
            recieveData();
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Window();
    }

    public static void timer1(int q) {

        if (q == 1) {
            timer = new Timer();
            timer.schedule(new TimerTask() {
                public void run() {
                    String type = "";
                    type = ImitateTransfer.transfer_send();
                    switch (type) {
                        case "100":
                            type = "成功發(fā)送";
                            break;

                        case "101":
                            type = "做校驗時出錯";
                            break;

                        case "102":
                            type = "傳送時丟失";
                            break;
                    }
                    sentData("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (超時重發(fā))");
                    showArea.append("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (超時重發(fā))" + "\n");

                }
            }, 2000);
        }

        if (q == 0) {
            timer.cancel();
        }
    }


}




客戶端B(負(fù)責(zé)接收):



package UDP;


import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.border.BevelBorder;

import java.net.*;

class Window2 extends JFrame {
    private JTextArea showArea;
    private JTextField inputField;
    private String IPadress;

    public void sentData(String Message) {
        byte[] dataarr = new byte[100010];

        try {
            Thread.currentThread().sleep(500);//毫秒
        } catch (Exception e) {
        }


        dataarr = Message.getBytes();
        try {
            InetAddress sentIP = InetAddress.getByName(IPadress);
            DatagramSocket dsset = new DatagramSocket(60010);
            DatagramPacket dprec = new DatagramPacket(dataarr, dataarr.length, sentIP, 63300);
            // 從己方60010端口發(fā)送到對方63300端口
            dsset.send(dprec);
            dsset.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void recieveData() {
        byte[] dataarr = new byte[100010];
        try {
            DatagramSocket dsset = new DatagramSocket(64650);
            DatagramPacket dprec = new DatagramPacket(dataarr, dataarr.length);
            dsset.receive(dprec);
            dsset.close();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            showArea.append(format.format(new Date()) + "\n" + "新消息: " + new String(dataarr).trim() + "\n");

            String a_type = new String(dataarr).trim().split(":")[3].split(";")[0];
            String content = new String(dataarr).trim().split(":")[2].split("類")[0];
            //sentData("A發(fā)送:  數(shù)據(jù)為:" + datas[m] + "類型為:" + type + ";  (開始發(fā)送)");
            String type = "";
            type = ImitateTransfer.transfer_confirm();
            switch (type) {
                case "100":
                    type = "成功接受";
                    break;

                case "103":
                    type = "確認(rèn)丟失";
                    break;

                case "104":
                    type = "確認(rèn)超時";
                    break;
            }

            switch (a_type) {


                case "成功發(fā)送":
                    sentData("B發(fā)送:" + "收到的數(shù)據(jù)為:" + content + "   類型(" + type + ") ");
                    break;

                case "做校驗時出錯":
                    break;

                case "傳送時丟失":
                    break;


            }


        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startChat() {
        JLabel displyjLabel = new JLabel("客戶端B");
        displyjLabel.setBounds(150, 10, 100, 15);
        JPanel myJPanel = new JPanel();
        myJPanel.setLayout(null);
        this.setContentPane(myJPanel);
        myJPanel.add(displyjLabel);
        showArea = new JTextArea();
        showArea.setLineWrap(true);
        JScrollPane scrollpane = new JScrollPane(showArea);
        scrollpane.setBounds(20, 30, 350, 350);
        scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED, Color.CYAN, Color.BLUE, null, null));
        scrollpane.setVisible(true);
        inputField = new JTextField();
        inputField.setBounds(20, 410, 280, 25);

        inputField.setVisible(true);
        myJPanel.add(scrollpane);
        JButton mybutton = new JButton("發(fā)送");
        mybutton.setBounds(310, 410, 60, 25);
        myJPanel.add(mybutton);
        myJPanel.add(inputField);
        myJPanel.setVisible(true);
        JButton quitjButton = new JButton("退出");
        quitjButton.setBounds(250, 450, 100, 30);
        myJPanel.add(quitjButton);
        quitjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                System.exit(0);
            }
        });
        JButton returnjButton = new JButton("返回主界面");
        returnjButton.setBounds(20, 450, 100, 30);
        myJPanel.add(returnjButton);
        returnjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                initWindow();
            }
        });
        this.setVisible(true);
        inputField.requestFocus();
        inputField.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                if (e.getKeyChar() == '\n') {
                    String Message = inputField.getText().trim();
                    sentData(Message);
                    inputField.setText("");
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    showArea.append(format.format(new Date()) + "\n" + "我發(fā)送: " + Message + "\n");
                }
            }
        });
        mybutton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                // 當(dāng)發(fā)送鍵被按下
                String Message = inputField.getText().trim();
                sentData(Message);
                inputField.setText("");
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                showArea.append(format.format(new Date()) + "\n" + "我發(fā)送: " + Message + "\n");

            }
        });
    }

    public void initWindow() {


        JPanel myjPanel = new JPanel();
        myjPanel.setLayout(null);
        this.setContentPane(myjPanel);
        JLabel myjLabel = new JLabel("歡迎使用本聊天程序");
        myjLabel.setBounds(50, 100, 300, 40);
        myjLabel.setForeground(Color.cyan);
        myjLabel.setFont(new Font("HirakakuProN-W6", Font.BOLD, 30));
        JLabel tishiJLabel = new JLabel("請輸入對方的IP地址:");
        tishiJLabel.setBounds(15, 300, 150, 20);
        final JTextField ipJTextField = new JTextField("127.128.0.1");
        ipJTextField.setBounds(150, 300, 115, 20);
        JButton okJButton = new JButton("確定");
        okJButton.setBounds(280, 300, 70, 20);
        ipJTextField.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub
                if (e.getKeyChar() == '\n') {
                    startChat();
                }
            }
        });
        okJButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                IPadress = ipJTextField.getText();
                startChat();
            }
        });
        myjPanel.add(tishiJLabel);
        myjPanel.add(myjLabel);
        myjPanel.add(ipJTextField);
        myjPanel.add(okJButton);
        JButton quitjButton = new JButton("退出");
        quitjButton.setBounds(150, 350, 100, 30);
        myjPanel.add(quitjButton);
        quitjButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                System.exit(0);
            }
        });
        this.setVisible(true);

    }

    public Window2() {
        this.setBounds(420, 100, 400, 550);
        this.setLayout(null);
        this.setTitle("客戶端B");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        initWindow();
        while (true) {
            recieveData();
            System.out.println("-----");
        }
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Window2();

    }

}


相信,有很多人贬养,已經(jīng)看懂了误算,這個程序了,先聲明一下咖杂,本程序是我在上網(wǎng)找的蚊夫,只是修改了一點點知纷。

這個程序說的就是琅轧,一個java的可視化界面+一個發(fā)送數(shù)據(jù)的函數(shù)+一個接收數(shù)據(jù)的函數(shù)乍桂,無論發(fā)送還是接收权谁,我都做了500毫秒的延遲闯传,用來模擬在路上的時間字币,也都需要指定ip和端口號洗出,就可以從這個端口發(fā)送到對方的端口了图谷,對方只需要監(jiān)視自己的端口就可以了翩活。

然后便贵,在發(fā)送數(shù)據(jù)的過程中,加了一個利用隨機(jī)數(shù)產(chǎn)生的承璃。
發(fā)送的類型,有三種盔粹,分別是:1.成功數(shù)據(jù)發(fā)送 2.發(fā)送的數(shù)據(jù)做校驗會出錯 3.發(fā)送的數(shù)據(jù)超時 隘梨。
接收的類型也有三種舷嗡,分別是:1.發(fā)送確認(rèn)成功 2.發(fā)送確認(rèn)超時
3.發(fā)送確認(rèn)丟失

當(dāng)A向B發(fā)送數(shù)據(jù)時进萄,B會判斷,如果是出錯或者超時兜蠕,B不會做任何處理扰肌,這個時候便會觸發(fā)A的超時計時器,重傳晶府。

當(dāng)B向A發(fā)送確認(rèn)時桂躏,如果確認(rèn)超時,或者確認(rèn)丟失川陆,A都會重新向B發(fā)送正確的數(shù)據(jù)剂习。

如果A接收到B的一次成功接收的指令,就會將數(shù)據(jù)向下滾動一位,傳一下數(shù)據(jù)鳞绕。

超時定時器(函數(shù)timer1)也很好理解失仁,只是讓它兩秒的等待,然后去重新發(fā)送數(shù)據(jù)们何,如果在兩秒內(nèi)萄焦,收到了確認(rèn)了,成功接收的指令冤竹,就會關(guān)閉這個超時定時器拂封。并且再向B發(fā)送一個數(shù)據(jù),同時再打開超時計時器就可以了鹦蠕。

當(dāng)然冒签,操作也非常簡單,只需要在钟病,客戶端A的輸入窗口萧恕,敲一下回車,或者點擊一下發(fā)送就行档悠,內(nèi)容是自動填充的廊鸥,不用手動輸入望浩。

效果圖:

效果圖1
效果圖2
效果圖3

大概這個模擬的過程就是這個樣子辖所,當(dāng)然其中肯定有很多,代碼規(guī)范磨德,代碼格式缘回,代碼復(fù)用做的很不好的地方~ 歡迎大家提意見,我都會改正的~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末典挑,一起剝皮案震驚了整個濱河市酥宴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌您觉,老刑警劉巖拙寡,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異琳水,居然都是意外死亡肆糕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門在孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诚啃,“玉大人,你說我怎么就攤上這事私沮∈际辏” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長造垛。 經(jīng)常有香客問我魔招,道長,這世上最難降的妖魔是什么五辽? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任仆百,我火速辦了婚禮,結(jié)果婚禮上奔脐,老公的妹妹穿的比我還像新娘俄周。我一直安慰自己,他們只是感情好髓迎,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布峦朗。 她就那樣靜靜地躺著,像睡著了一般排龄。 火紅的嫁衣襯著肌膚如雪波势。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天橄维,我揣著相機(jī)與錄音尺铣,去河邊找鬼。 笑死争舞,一個胖子當(dāng)著我的面吹牛凛忿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竞川,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼店溢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了委乌?” 一聲冷哼從身側(cè)響起床牧,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遭贸,沒想到半個月后戈咳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡壕吹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年著蛙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片算利。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡册踩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出效拭,到底是詐尸還是另有隱情暂吉,我是刑警寧澤胖秒,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站慕的,受9級特大地震影響阎肝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肮街,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一风题、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嫉父,春花似錦沛硅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仪际,卻和暖如春围小,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背树碱。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工肯适, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人成榜。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓框舔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伦连。 傳聞我的和親對象是個殘疾皇子雨饺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 個人認(rèn)為钳垮,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記惑淳,這雖然只是...
    貳零壹柒_fc10閱讀 5,054評論 0 8
  • 1.這篇文章不是本人原創(chuàng)的,只是個人為了對這部分知識做一個整理和系統(tǒng)的輸出而編輯成的饺窿,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,068評論 6 174
  • 本章討論TCP/IP體系中運輸層最重要的兩種協(xié)議:UDP和TCP歧焦。必須弄清TCP的各種機(jī)制(如面向連接的可靠服務(wù)、...
    dmmy大印閱讀 936評論 0 0
  • 1 運輸層協(xié)議概述 1.1 進(jìn)程之間的通信 網(wǎng)絡(luò)層是為主機(jī)之間提供邏輯通信肚医,而運輸層為應(yīng)用進(jìn)程之間提供端到端的邏輯...
    Mr希靈閱讀 8,086評論 0 34
  • 注:本文的圖片均來源于謝希仁《計算機(jī)網(wǎng)絡(luò)》第六版的課件PPT 1.重點內(nèi)容 (1)運輸層為相互通信的應(yīng)用進(jìn)程提供邏...
    zuyuxia閱讀 1,101評論 0 1