socket模拟通信实现ARQ停止等待协议
//服务端
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.security.Timestamp;
import java.util.*;
import java.util.prefs.BackingStoreException;
import javax.swing.*;
public class IServer extends JFrame {
private static long time1;
private static long time2;
private JPanel jp = new JPanel();
private JTextArea jta = new JTextArea();
private JScrollPane jsp = null;
private JButton jb = new JButton("发送");
private JTextField jtf = new JTextField(30);
private ServerSocket server;
private Socket socket;
DataOutputStream dos;
DataInputStream dis;
public IServer() throws IOException
{
Toolkit t = Toolkit.getDefaultToolkit();
Dimension Size =t.getScreenSize();
int width = Size.width;
int height = Size.height;
setLocationByPlatform(true);
jsp = new JScrollPane(jta);
this.setTitle("发送方");
this.setSize(600, 500);
this.setBounds((width - 600) / 2,
(height - 500) / 2, 600,500);
jp.add(jtf);
jp.add(jb);
this.add(jsp, BorderLayout.CENTER);
this.add(jp, BorderLayout.SOUTH);
jta.setCaretPosition(jta.getDocument().getLength());// 设置滚动条自动滚动
this.setVisible(true);
this.setAlwaysOnTop(true);
server = new ServerSocket(9000);
socket= server.accept();
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
dos = new DataOutputStream(socket.getOutputStream());
dis =new DataInputStream(socket.getInputStream());
jb.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
try {
Send();
} catch (InterruptedException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public static void main(String[] args) throws IOException, InterruptedException
{
new IServer();
}
public void Send() throws InterruptedException, IOException
{
String info = jtf.getText();
jtf.setText("");
char[] Msg = info.toCharArray();
dos.write(Msg.length);
for(int i=0;i<Msg.length;i++)
{
Random random=new java.util.Random(); //实现数据帧错传,以随机数的概率来实现
int result=random.nextInt(21);
if(result>=4)
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Sending...:" + Msg[i]);
} else {
jta.append("\r\nSending...:" + Msg[i]);
}
dos.writeChar(Msg[i]); //发送数据帧
time1 = System.currentTimeMillis(); //设置超时计时器
}
else
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Sending...:" + Msg[i]);
} else {
jta.append("\r\nSending...:" + Msg[i]);
}
dos.writeChar('η'); //发送数据帧
time1 = System.currentTimeMillis(); //设置超时计时器
}
int c = dis.readInt(); //接受客户端确认帧
time2 = System.currentTimeMillis();
long time = time2-time1;
//System.out.println("接收所用时间:"+time);
if(time<500) //确认帧未超时
{
if(c==i+2) //确认帧正确,传输成功,准备传输下一个帧
{
if(i<Msg.length-1)
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + c);
} else {
jta.append("\r\nReceive:" + c);
}
//System.out.println("接收方返回帧:"+c+" 第"+(i+1)+"号帧传输成功!");
}
else
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + (i+2)+"数据传输成功!");
} else {
jta.append("\r\nReceive:" + (i+2)+"数据传输成功!");
jta.setEnabled(false);
}
//System.out.println("第"+(i+1)+"号帧传输成功!");
//System.out.println("数据传输成功!");
server.close();
}
}
else if(c==-2) //确认帧出错,超时重传
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:数据帧出错,丢弃等待....."+
"确认帧接收超时,重新发送"+(i+1)+"帧");
} else {
jta.append("\r\nReceive:Receive:数据帧出错,丢弃等待....."
+"确认帧接收超时,重新发送"+(i+1)+"帧");
}
//System.out.println("数据帧出错,丢弃等待.....");
Thread.sleep(300);
//System.out.println("确认帧接收超时,重新发送"+(i+1)+"帧");
i=i-1;
}
}
else//超时,重传
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" +"确认帧接收超时,重新发送"+(i+1)+"帧");
} else {
jta.append("\r\nReceive:" + "确认帧接收超时,重新发送"+(i+1)+"帧");
}
//System.out.println("确认帧接收超时,重新发送"+(i+1)+"帧");
i=i-1;
}
}
}
}
//客户端
//客户端
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
public class IClient extends JFrame {
JPanel jp = new JPanel();
JTextArea jta = new JTextArea();
JScrollPane jsp = null;
public IClient()
{
Toolkit t = Toolkit.getDefaultToolkit();
Dimension Size =t.getScreenSize();
int width = Size.width;
int height = Size.height;
setLocationByPlatform(true);
this.setAlwaysOnTop(true);
jsp = new JScrollPane(jta);
this.setTitle("接收方");
this.add(jp);
this.setSize(500, 400);
this.setBounds((width - 500) / 2,
(height - 400) / 2, 600,500);
this.add(jsp, BorderLayout.CENTER);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
new IClient().Receive();
}
public void Receive() throws UnknownHostException, IOException, InterruptedException
{
Socket client = new Socket("localhost",9000);
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
DataInputStream dis =new DataInputStream(client.getInputStream());
int length = dis.read(); //读取接收数据帧的长度
//System.out.println(length); //输出要接受的数据的长度
for(int i=0;i<length;i++)
{
char c = dis.readChar(); //接收数据帧,判断是否正确
if(c!='η'){ //CRC数据帧校验正确
Random ran=new java.util.Random();
int re=ran.nextInt(13);
if(re>=4){ //数据帧帧数正确
if(i<length-1)
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + "成功接收"+(i+1)+"号帧,内容为:"+c);
} else {
jta.append("\r\nReceive:" + "成功接收"+(i+1)+"号帧,内容为:"+c);
}
//System.out.println("成功接收"+(i+1)+"号帧,内容为:"+c); //输出接受到的数据帧
dos.writeInt(i+2);
}
else
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + "成功接收"+(i+1)+"号帧,内容为:"+c);
} else {
jta.append("\r\nReceive:" + "成功接收"+(i+1)+"号帧,内容为:"+c);
}
//System.out.println("成功接收"+(i+1)+"号帧,内容为:"+c);
dos.writeInt(i+2); //向发送方返回确认帧
Thread.sleep(100);
}
}
else //数据帧内容错误
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + "不是所需要的帧,丢弃等待!");
} else {
jta.append("\r\nReceive:" + "不是所需要的帧,丢弃等待!");
}
Thread.sleep(600);
//System.out.println("不是所需要的帧,丢弃等待!");
dos.writeInt(-1);
i=i-1;
}
}
else if(c=='η') //CRC数据帧错误丢弃等待
{
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append("Receive:" + "数据帧错误!");
} else {
jta.append("\r\nReceive:" + "数据帧错误!");
}
//System.out.println("数据帧错误!");
i=i-1;
dos.writeInt(-2);
}
}
if (jta.getText() == null || "".equals(jta.getText())) {
jta.append( "接收信息成功!");
} else {
jta.append("\r\n" + "接收信息成功!");
}
jta.setEnabled(false);
//System.out.println("接收信息成功!");
client.close();
}
}
停止等待ARQ算法模拟
一、目的:
在两个程序通信的前提下,模拟实现停止等待ARQ协议。
要求模拟实现:
1. 正常数据帧的通信过程
2. 错误帧的通信过程
3. 数据帧的丢失的通信过程
二、实验内容与步骤
按照如下算法进行实现:
发方程序:
(1) 从主机取一个数据帧,送交发送缓存。
(2) V(S)←0。
(3) N(S)←V(S)。
(4) 将发送缓存中的数据帧发送出去。
(5) 设置超时计时器。
(6) 等待。
(7) 收到确认帧 ACKn,
若 n = 1 – V(s),则:
从主机取一个新的数据帧,放入发送缓存;
V(S)←[1 - V(S)],转到 (3)。
否则,丢弃这个确认帧,转到(6)。
(8) 若超时计时器时间到,则转到(4)。
收方:
(1) V(R)←0。
(2) 等待。
(3) 收到一个数据帧;
若 CRC校验无误
若 N(S) = V(R),则执行(4);
否则丢弃此数据帧,然后转到(6)。
否则丢弃此数据帧,然后转到(2)。
(4) 将收到的数据帧中的数据部分送交上层软件
(5) V(R)←[1 - V(R)]。
(6) n←V(R);
发送确认帧 ACKn,转到(2)。
socket模拟通信实现ARQ停止等待协议的更多相关文章
- TCP协议总结--停止等待协议,连续ARQ协议,滑动窗口协议
前言:在学习tcp三次握手的过程之中,由于一直无法解释tcpdump命令抓的包中seq和ack的含义,就将tcp协议往深入的了解了一下,了解到了几个协议,做一个小结. 先来看看我的问题: 这是用tcp ...
- 计算机网络之流量控制(停止-等待协议、滑动窗口、后退N帧协议GBN、选择重传协议SR)、滑动窗口、可靠传输机制
文章转自:https://blog.csdn.net/weixin_43914604/article/details/104908762 学习课程:<2019王道考研计算机网络> 学习目的 ...
- [knowledge] 停止等待协议
再读TCP/IP详解 说到流量控制, 可能便涉及了两方面 1. 停止等待协议. https://baike.baidu.com/item/%E5%81%9C%E6%AD%A2%E7%AD%89%E5% ...
- C#高性能大容量SOCKET并发(七):协议字符集
原文:C#高性能大容量SOCKET并发(七):协议字符集 UTF-8 UTF-8是UNICODE的一种变长字符编码又称万国码,由Ken Thompson于1992年创建.现在已经标准化为RFC 362 ...
- 网络编程----------SOCKET编程实现简单的TCP协议
首先我们须要大致了解TCP的几点知识: 1.TCP的特点:面向连接的可靠性传输 2.TCP的三次握手建立连接和四次挥手释放连接.但为什么TCP要三次握手建立连接呢? 答:由于两次握手无法保证可靠性.若 ...
- Python网络编程(socket模块、缓冲区、http协议)
网络的概念:主机 端口 IP 协议 服务器: localhost/127.0.0.1 客户端: 只是在本机启动客户端,用127.0.0.1访问 服务器: 0.0.0.0 客户端: ...
- Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver
今日内容:socket网络编程 1.OSI七层协议 2.基于tcp协议的套接字通信 3.模拟ssh远程执行命令 4.tcp的粘包问题及解决方案 5.基于udp协议的套接字 ...
- socket套接字编程 HTTP协议
socket套接字编程 套接字介绍 1. 套接字 : 实现网络编程进行数据传输的一种技术手段 2. Python实现套接字编程:import socket 3. 套接字分类 >流式套接 ...
- java基础知识回顾之java Socket学习(二)--TCP协议编程
TCP传输(传输控制协议):TCP协议是一种面向连接的,可靠的字节流服务.当客户端和服务器端彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能进行数据的传输.它将一台主机发出的字节流无差错的 ...
随机推荐
- contenteditable实现可编辑的HTML标签
最近工作中遇到了一个小问题,让我学到了新的标签属性--contenteditable. 我需要实现的是手机端界面,特别简单的一个页面,如下图: 在我脑海里第一时间想到的应该就是一个form表单然后里面 ...
- 偶遇event.target
今天在学习其他人代码的时候见到了event.target.nodeName,event.target.dataset.刚开始是一头雾水,便google一下.发现大多数给出的词条都是有关jQuery事件 ...
- ajax实现下载功能
ajax实现下载功能 适用场景:由于点击按钮下载excel响应时间过长,此时间段加入加载样式(灰色层.加载动画): 浏览器弹出下载框后,上面的加载样式去掉. 方 法 :使用jquery.fi ...
- MASM32使用教程
代码如果你在用汇编语言来开发windows下的程序的话,MASM32是很好的选择. (Masm32下载地址请用google搜索罢.) 工欲善其事,必先利其器. 本文主要针对masm32 v8来说明三点 ...
- 从源码解析LinkedList集合
上篇文章我们介绍了ArrayList类的基本的使用及其内部的一些方法的实现原理,但是这种集合类型虽然可以随机访问数据,但是如果需要删除中间的元素就需要移动一半的元素的位置,效率低下.并且它内 ...
- javascript小程序——用嵌套循环来输出乘法口诀表
在学习javascript过程中,一开始接触循环语句时一般拿乘法口诀表来练手,这里我将自己的练习贴在这里,希望能给和我一样的初学者些许帮助,也希望大神们能够不吝指教. 首先,来看一下乘法口诀表是什么样 ...
- Ant 警告:sun.misc.BASE64Decoder 是 Sun 的专用 API,可能会在未来版本中删除
如果你用Ant编译项目,而且在项目中用了SUN的专用API,你会得到警告信息,然后Ant会报告编译失败: 这当然是不合理的,javac只是警告而已,ant凭什么就直接报失败呢? 其实最好的解决办法是避 ...
- Android 反射-换一种方式编程
Android 反射-换一种方式编程 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/59109933 本文出自[赵彦军的博客] 上一 ...
- 2017-3-2 C#基础 集合
要使用集合必须先引用命名空间,using System.Collections; 集合与数组的不同: 数组:同一类型,固定长度集合:不同类型,不固定长度 集合主要分为六大类:普通集合,泛型集合,哈希表 ...
- EntityFrameworkCore使用Migrations自动更新数据库
EntityFrameworkCore使用Migrations自动更新数据库 系统环境:Win10 IDE:VS2017 RC4 .netcore版本:1.1 一.新建ASP.NET Core Web ...