利用udp模拟arq停止等待协议

停止等待arq协议:
停止等待协议(stop-and-wait)是最简单但也是最基础的数据链路层协议。很多有关协议的基本概念都可以从这个协议中学习到。“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。

由于这里我们采用的是端对端的传输,所以我们并没有采用tcp进行流式套接字的传输,而是采用udp,进行的数据报的传输。

UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17

UDP协议全称是用户数据报协议[1] ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。

与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

再解释说明一下,由于系统层面的原因,会有自动校验的措施,而且因为我做的是本机的测试,出错率也会很低,所以我们需要模拟出错的情况。我们利用随机数的算法,做了一个模拟的随机数算法:



package UDP;

/**
 * Created by linSir on 16/10/5.用来模拟传输过程(udp)
 */
public class ImitateTransfer {

    /**
     * 用来模拟传输过程中的各种情况
     * 1.无差错情况(60%) 状态码:100
     * 2.出现差错
     * ①.接收到了,做校验时发现有错(20%) 状态码:101
     * ②.传输过程中丢失数据(20%) 状态码:102
     * 3.确认丢失和确认迟到
     * ①.确认丢失(20%)状态码:103
     * ②.确认迟到(20%)状态码:104
     */

    public static String transfer_send() {//发送数据的三种情况

        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() {//发送确认命令的三种情况

        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(负责发送):



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 端口发送到客户端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);
            // 监听己方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 = "成功发送";
                            break;

                        case "101":
                            type = "做校验时出错";
                            break;

                        case "102":
                            type = "传送时丢失";
                            break;
                    }
                    sentData("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (正常发送)");
                    showArea.append("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (正常发送)" + "\n");
                    break;

                case "确认丢失":

                    break;


                case "确认超时":

                    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("发送");
        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 = "成功发送";
                            break;

                        case "101":
                            type = "做校验时出错";
                            break;

                        case "102":
                            type = "传送时丢失";
                            break;


                    }

                    //A发送:  数据为:1  类型为:成功发送;  (开始发送)
                    sentData("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (开始发送)");
                    inputField.setText("");
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    showArea.append("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (开始发送)" + "\n");
                    //sendMessage("A(发送)-" + datas[m] + "-" + 实验二.ImitateTransfer.transfer_send() + "---开始发送");
                }
            }
        });
        mybutton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                // 当发送键被按下
                String type = "";
                type = ImitateTransfer.transfer_send();
                switch (type) {
                    case "100":
                        type = "成功发送";
                        break;

                    case "101":
                        type = "做校验时出错";
                        break;

                    case "102":
                        type = "传送时丢失";
                        break;


                }

                //A发送:  数据为:1  类型为:成功发送;  (开始发送)
                sentData("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (开始发送)");
                inputField.setText("");
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                showArea.append("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (开始发送)" + "\n");
                //sendMessage("A(发送)-" + datas[m] + "-" + 实验二.ImitateTransfer.transfer_send() + "---开始发送");

            }
        });
    }

    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 = "成功发送";
                            break;

                        case "101":
                            type = "做校验时出错";
                            break;

                        case "102":
                            type = "传送时丢失";
                            break;
                    }
                    sentData("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (超时重发)");
                    showArea.append("A发送:  数据为:" + datas[m] + "类型为:" + type + ";  (超时重发)" + "\n");

                }
            }, 2000);
        }

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


}




客户端B(负责接收):



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端口发送到对方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发送:  数据为:" + datas[m] + "类型为:" + type + ";  (开始发送)");
            String type = "";
            type = ImitateTransfer.transfer_confirm();
            switch (type) {
                case "100":
                    type = "成功接受";
                    break;

                case "103":
                    type = "确认丢失";
                    break;

                case "104":
                    type = "确认超时";
                    break;
            }

            switch (a_type) {


                case "成功发送":
                    sentData("B发送:" + "收到的数据为:" + 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("发送");
        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" + "我发送: " + Message + "\n");
                }
            }
        });
        mybutton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                // 当发送键被按下
                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" + "我发送: " + 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();

    }

}


相信,有很多人,已经看懂了,这个程序了,先声明一下,本程序是我在上网找的,只是修改了一点点。

这个程序说的就是,一个java的可视化界面+一个发送数据的函数+一个接收数据的函数,无论发送还是接收,我都做了500毫秒的延迟,用来模拟在路上的时间,也都需要指定ip和端口号,就可以从这个端口发送到对方的端口了,对方只需要监视自己的端口就可以了。

然后,在发送数据的过程中,加了一个利用随机数产生的。
发送的类型,有三种,分别是:1.成功数据发送 2.发送的数据做校验会出错 3.发送的数据超时 。
接收的类型也有三种,分别是:1.发送确认成功 2.发送确认超时
3.发送确认丢失

当A向B发送数据时,B会判断,如果是出错或者超时,B不会做任何处理,这个时候便会触发A的超时计时器,重传。

当B向A发送确认时,如果确认超时,或者确认丢失,A都会重新向B发送正确的数据。

如果A接收到B的一次成功接收的指令,就会将数据向下滚动一位,传一下数据。

超时定时器(函数timer1)也很好理解,只是让它两秒的等待,然后去重新发送数据,如果在两秒内,收到了确认了,成功接收的指令,就会关闭这个超时定时器。并且再向B发送一个数据,同时再打开超时计时器就可以了。

当然,操作也非常简单,只需要在,客户端A的输入窗口,敲一下回车,或者点击一下发送就行,内容是自动填充的,不用手动输入。

效果图:

效果图1
效果图2
效果图3

大概这个模拟的过程就是这个样子,当然其中肯定有很多,代码规范,代码格式,代码复用做的很不好的地方~ 欢迎大家提意见,我都会改正的~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,639评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,093评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,079评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,329评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,343评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,047评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,645评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,565评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,201评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,338评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,014评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,701评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,194评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,685评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,345评论 2 358

推荐阅读更多精彩内容

  • 个人认为,Goodboy1881先生的TCP /IP 协议详解学习博客系列博客是一部非常精彩的学习笔记,这虽然只是...
    贰零壹柒_fc10阅读 5,058评论 0 8
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 13,071评论 6 174
  • 本章讨论TCP/IP体系中运输层最重要的两种协议:UDP和TCP。必须弄清TCP的各种机制(如面向连接的可靠服务、...
    dmmy大印阅读 939评论 0 0
  • 1 运输层协议概述 1.1 进程之间的通信 网络层是为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑...
    Mr希灵阅读 8,103评论 0 34
  • 注:本文的图片均来源于谢希仁《计算机网络》第六版的课件PPT 1.重点内容 (1)运输层为相互通信的应用进程提供逻...
    zuyuxia阅读 1,102评论 0 1