Code
1 //主类:模拟滑动窗口协议
2
3 using System;
4 using System.Collections;
5 using System.Net.Sockets;
6 using System.Net;
7 using System.Threading;
8 using System.Text;
9 using seal.common;
10
11
12 namespace scutnetTalkClient
13 {
14 /// <summary>
15 /// UDPSlidingWindow udp滑动窗口类。
16 /// </summary>
17 public class UDPSlidingWindow
18 {
19 public static byte MSG_COMPLETE=0x01;//队列数据发送完毕
20 public static byte MSG_SLICE_SENDED=0x03;//片发送状态
21 public static byte MSG_SLICE_COMPLETE=0x04;//片完毕应答
22 public static long MAX_WAIT_TIME=3000;//窗口最大等待时间
23 public static int MAX_RETRY_TIME=5;//窗口最大重发次数
24 private byte ret;
25 private int retryTime=0;
26 private SlidingWindow sendWindow=new SlidingWindow(5);
27 private Hashtable sendList=new Hashtable();
28 private Hashtable state=new Hashtable();
29 public static UdpClient sendClient=new UdpClient(8211);
30 public string msg;
31 public System.Net.IPEndPoint target;
32
33 public UDPSlidingWindow()
34 {
35 //
36 // TODO: 在此处添加构造函数逻辑
37 //
38 }
39
40 public void sendThread(object o)
41 {
42 byte[] sendBuffer=System.Text.ASCIIEncoding.UTF8.GetBytes(msg);
43 Console.WriteLine("发送开始时间:"+DateTime.Now);
44 Console.WriteLine("待发数据长度:"+sendBuffer.Length/1024+"K Byte】");
45
46 sendList=MsgSlice.splitMsg(sendBuffer);
47 //Console.WriteLine("准备发送数据:"+sendList.Count+"片");
48 while(ret!=UDPSlidingWindow.MSG_COMPLETE)
49 {
50 if(((DateTime.Now)>sendWindow.lastActiveTime.AddMilliseconds(UDPSlidingWindow.MAX_WAIT_TIME)))
51 {//窗口停留超时,则重发落在窗口内未标志为“已接收”的所有包
52 if(retryTime>=UDPSlidingWindow.MAX_RETRY_TIME)
53 {//重发次数超过设定值,退出。
54 Console.WriteLine("重发次数超过"+UDPSlidingWindow.MAX_RETRY_TIME+",发送数据失败!请检查网络是否正常连接。");
55 return;
56 }
57 Console.WriteLine((DateTime.Now).ToString()+"===>"+sendWindow.lastActiveTime.AddMilliseconds(UDPSlidingWindow.MAX_WAIT_TIME));
58 for(long i=sendWindow.getWindowHead()-sendWindow.getUsedSize();i<sendWindow.getWindowHead();i++)
59 {
60 MsgSlice tmpMs=(MsgSlice)sendList[i];
61 if(tmpMs!=null&&(state[i]==null||(byte)state[i]!=UDPSlidingWindow.MSG_SLICE_COMPLETE))
62 {
63 Console.WriteLine("重新发送数据:"+i);
64 byte[] tmpBt=FormatterHelper.Serialize(tmpMs);
65 sendClient.Send(tmpBt,tmpBt.Length,target);
66 state.Remove(i);
67 state.Add(i,UDPSlidingWindow.MSG_SLICE_SENDED);//将窗口内新发送包加入到等待回应队列
68 }
69 }
70 retryTime++;
71 sendWindow.lastActiveTime=DateTime.Now;
72 }
73 while((state[(long)(sendWindow.getWindowHead()-sendWindow.getUsedSize())]!=null&&(byte)state[(long)(sendWindow.getWindowHead()-sendWindow.getUsedSize())]==MSG_SLICE_COMPLETE||sendWindow.getUsedSize()<sendWindow.getMaxSize())&&sendWindow.getWindowHead()<sendList.Count)
74 {//滑动窗口下标数据已经完成且数据未发完,则发送下一个包,并且窗口前移。
75 retryTime=0;
76 MsgSlice tmpMs=(MsgSlice)sendList[(long)sendWindow.getWindowHead()];
77 //Console.WriteLine("准备发送:"+sendWindow.getWindowHead()+":"+tmpMs.isEndSlice());
78 byte[] tmpBt=FormatterHelper.Serialize(tmpMs);
79 sendClient.Send(tmpBt,tmpBt.Length,target);
80 sendWindow.moveAhead();
81 state.Add(sendWindow.getWindowHead(),UDPSlidingWindow.MSG_SLICE_SENDED);//将窗口内新发送包加入到等待回应队列
82 }
83 //Thread.Sleep(50);
84 }
85 }
86
87
88 public void recieveThread(object o)
89 {
90 while(true)
91 {
92 IPEndPoint remoteIp=new IPEndPoint(IPAddress.Any,0);
93 byte[] act=sendClient.Receive(ref remoteIp);
94 if(act[0]==UDPSlidingWindow.MSG_SLICE_COMPLETE)
95 {//接收到片完成信息
96 long index=BitConverter.ToInt64(act,1);
97 state.Remove(index);
98 state.Add(index,UDPSlidingWindow.MSG_SLICE_COMPLETE);
99 //Console.WriteLine("接收到数据包完成信息:"+index);
100 }
101 else if(act[0]==UDPSlidingWindow.MSG_COMPLETE)
102 {//接收到“数据接收完毕”信息
103 ret=UDPSlidingWindow.MSG_COMPLETE;
104 Console.WriteLine("全部数据成功发送完毕,收工");
105 Console.WriteLine("发送结束时间:"+DateTime.Now);
106 return;
107 }
108 }
109 }
110 //*
111 [STAThread]
112 static void Main(string[] args)
113 {
114 string ip="192.168.0.244";
115 string msg="0--begin--0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪--end---0";
116 msg+=msg;
117 msg+=msg;
118 msg+=msg;
119 msg+=msg;
120 msg+=msg;
121 msg+=msg;
122 msg+=msg;
123 msg+=msg;
124 msg+=msg;
125 msg+=msg;
126 msg+=msg;
127 msg="[begin]"+msg+"[end]";
128
129 Console.WriteLine("请输入发送目的IP:");
130 ip=Console.ReadLine();
131 ip=ip==""?"192.168.0.244":ip;
132 IPEndPoint target=new IPEndPoint(IPAddress.Parse(ip),8080);
133 while(true)
134 {
135 Console.WriteLine("是否再发送?");
136 if(Console.ReadLine().ToLower()=="y")
137 {
138 UDPSlidingWindow usw=new UDPSlidingWindow();
139 usw.target=target;
140 usw.msg=msg;
141 System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(usw.recieveThread));
142 System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(usw.sendThread));
143 }
144 }
145 }
146 //*/
147 }
148
149 public class SlidingWindow
150 {
151 private int maxSize;
152 private int usedSize=0;
153 private int windowHead=0;
154 public DateTime beginTime;
155 public DateTime lastActiveTime;
156
157 public SlidingWindow()
158 {
159 beginTime=DateTime.Now;
160 lastActiveTime=beginTime;
161 this.maxSize=5;
162 }
163
164 public SlidingWindow(int m)
165 {
166 beginTime=DateTime.Now;
167 lastActiveTime=beginTime;
168 this.maxSize=m;
169 }
170
171 //窗口向前移动
172 public void moveAhead()
173 {
174 this.windowHead++;
175 if(this.usedSize<this.maxSize)
176 {
177 this.usedSize++;
178 }
179 this.lastActiveTime=DateTime.Now;
180 }
181
182 //发送完毕后窗口回到原位
183 public void resetWindowHead()
184 {
185 this.windowHead=0;
186 }
187
188 public void takeOne()
189 {
190 if(this.usedSize>0)
191 {
192 this.usedSize--;
193 }
194 this.lastActiveTime=DateTime.Now;
195 }
196
197 public int getMaxSize()
198 {
199 return this.maxSize;
200 }
201
202 public int getUsedSize()
203 {
204 return this.usedSize;
205 }
206
207 public int getWindowHead()
208 {
209 return this.windowHead;
210 }
211 }
212 }
213
214
215
216
1 //主类:模拟滑动窗口协议
2
3 using System;
4 using System.Collections;
5 using System.Net.Sockets;
6 using System.Net;
7 using System.Threading;
8 using System.Text;
9 using seal.common;
10
11
12 namespace scutnetTalkClient
13 {
14 /// <summary>
15 /// UDPSlidingWindow udp滑动窗口类。
16 /// </summary>
17 public class UDPSlidingWindow
18 {
19 public static byte MSG_COMPLETE=0x01;//队列数据发送完毕
20 public static byte MSG_SLICE_SENDED=0x03;//片发送状态
21 public static byte MSG_SLICE_COMPLETE=0x04;//片完毕应答
22 public static long MAX_WAIT_TIME=3000;//窗口最大等待时间
23 public static int MAX_RETRY_TIME=5;//窗口最大重发次数
24 private byte ret;
25 private int retryTime=0;
26 private SlidingWindow sendWindow=new SlidingWindow(5);
27 private Hashtable sendList=new Hashtable();
28 private Hashtable state=new Hashtable();
29 public static UdpClient sendClient=new UdpClient(8211);
30 public string msg;
31 public System.Net.IPEndPoint target;
32
33 public UDPSlidingWindow()
34 {
35 //
36 // TODO: 在此处添加构造函数逻辑
37 //
38 }
39
40 public void sendThread(object o)
41 {
42 byte[] sendBuffer=System.Text.ASCIIEncoding.UTF8.GetBytes(msg);
43 Console.WriteLine("发送开始时间:"+DateTime.Now);
44 Console.WriteLine("待发数据长度:"+sendBuffer.Length/1024+"K Byte】");
45
46 sendList=MsgSlice.splitMsg(sendBuffer);
47 //Console.WriteLine("准备发送数据:"+sendList.Count+"片");
48 while(ret!=UDPSlidingWindow.MSG_COMPLETE)
49 {
50 if(((DateTime.Now)>sendWindow.lastActiveTime.AddMilliseconds(UDPSlidingWindow.MAX_WAIT_TIME)))
51 {//窗口停留超时,则重发落在窗口内未标志为“已接收”的所有包
52 if(retryTime>=UDPSlidingWindow.MAX_RETRY_TIME)
53 {//重发次数超过设定值,退出。
54 Console.WriteLine("重发次数超过"+UDPSlidingWindow.MAX_RETRY_TIME+",发送数据失败!请检查网络是否正常连接。");
55 return;
56 }
57 Console.WriteLine((DateTime.Now).ToString()+"===>"+sendWindow.lastActiveTime.AddMilliseconds(UDPSlidingWindow.MAX_WAIT_TIME));
58 for(long i=sendWindow.getWindowHead()-sendWindow.getUsedSize();i<sendWindow.getWindowHead();i++)
59 {
60 MsgSlice tmpMs=(MsgSlice)sendList[i];
61 if(tmpMs!=null&&(state[i]==null||(byte)state[i]!=UDPSlidingWindow.MSG_SLICE_COMPLETE))
62 {
63 Console.WriteLine("重新发送数据:"+i);
64 byte[] tmpBt=FormatterHelper.Serialize(tmpMs);
65 sendClient.Send(tmpBt,tmpBt.Length,target);
66 state.Remove(i);
67 state.Add(i,UDPSlidingWindow.MSG_SLICE_SENDED);//将窗口内新发送包加入到等待回应队列
68 }
69 }
70 retryTime++;
71 sendWindow.lastActiveTime=DateTime.Now;
72 }
73 while((state[(long)(sendWindow.getWindowHead()-sendWindow.getUsedSize())]!=null&&(byte)state[(long)(sendWindow.getWindowHead()-sendWindow.getUsedSize())]==MSG_SLICE_COMPLETE||sendWindow.getUsedSize()<sendWindow.getMaxSize())&&sendWindow.getWindowHead()<sendList.Count)
74 {//滑动窗口下标数据已经完成且数据未发完,则发送下一个包,并且窗口前移。
75 retryTime=0;
76 MsgSlice tmpMs=(MsgSlice)sendList[(long)sendWindow.getWindowHead()];
77 //Console.WriteLine("准备发送:"+sendWindow.getWindowHead()+":"+tmpMs.isEndSlice());
78 byte[] tmpBt=FormatterHelper.Serialize(tmpMs);
79 sendClient.Send(tmpBt,tmpBt.Length,target);
80 sendWindow.moveAhead();
81 state.Add(sendWindow.getWindowHead(),UDPSlidingWindow.MSG_SLICE_SENDED);//将窗口内新发送包加入到等待回应队列
82 }
83 //Thread.Sleep(50);
84 }
85 }
86
87
88 public void recieveThread(object o)
89 {
90 while(true)
91 {
92 IPEndPoint remoteIp=new IPEndPoint(IPAddress.Any,0);
93 byte[] act=sendClient.Receive(ref remoteIp);
94 if(act[0]==UDPSlidingWindow.MSG_SLICE_COMPLETE)
95 {//接收到片完成信息
96 long index=BitConverter.ToInt64(act,1);
97 state.Remove(index);
98 state.Add(index,UDPSlidingWindow.MSG_SLICE_COMPLETE);
99 //Console.WriteLine("接收到数据包完成信息:"+index);
100 }
101 else if(act[0]==UDPSlidingWindow.MSG_COMPLETE)
102 {//接收到“数据接收完毕”信息
103 ret=UDPSlidingWindow.MSG_COMPLETE;
104 Console.WriteLine("全部数据成功发送完毕,收工");
105 Console.WriteLine("发送结束时间:"+DateTime.Now);
106 return;
107 }
108 }
109 }
110 //*
111 [STAThread]
112 static void Main(string[] args)
113 {
114 string ip="192.168.0.244";
115 string msg="0--begin--0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪----0123456789我-的-地-盘-我-作-猪--end---0";
116 msg+=msg;
117 msg+=msg;
118 msg+=msg;
119 msg+=msg;
120 msg+=msg;
121 msg+=msg;
122 msg+=msg;
123 msg+=msg;
124 msg+=msg;
125 msg+=msg;
126 msg+=msg;
127 msg="[begin]"+msg+"[end]";
128
129 Console.WriteLine("请输入发送目的IP:");
130 ip=Console.ReadLine();
131 ip=ip==""?"192.168.0.244":ip;
132 IPEndPoint target=new IPEndPoint(IPAddress.Parse(ip),8080);
133 while(true)
134 {
135 Console.WriteLine("是否再发送?");
136 if(Console.ReadLine().ToLower()=="y")
137 {
138 UDPSlidingWindow usw=new UDPSlidingWindow();
139 usw.target=target;
140 usw.msg=msg;
141 System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(usw.recieveThread));
142 System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(usw.sendThread));
143 }
144 }
145 }
146 //*/
147 }
148
149 public class SlidingWindow
150 {
151 private int maxSize;
152 private int usedSize=0;
153 private int windowHead=0;
154 public DateTime beginTime;
155 public DateTime lastActiveTime;
156
157 public SlidingWindow()
158 {
159 beginTime=DateTime.Now;
160 lastActiveTime=beginTime;
161 this.maxSize=5;
162 }
163
164 public SlidingWindow(int m)
165 {
166 beginTime=DateTime.Now;
167 lastActiveTime=beginTime;
168 this.maxSize=m;
169 }
170
171 //窗口向前移动
172 public void moveAhead()
173 {
174 this.windowHead++;
175 if(this.usedSize<this.maxSize)
176 {
177 this.usedSize++;
178 }
179 this.lastActiveTime=DateTime.Now;
180 }
181
182 //发送完毕后窗口回到原位
183 public void resetWindowHead()
184 {
185 this.windowHead=0;
186 }
187
188 public void takeOne()
189 {
190 if(this.usedSize>0)
191 {
192 this.usedSize--;
193 }
194 this.lastActiveTime=DateTime.Now;
195 }
196
197 public int getMaxSize()
198 {
199 return this.maxSize;
200 }
201
202 public int getUsedSize()
203 {
204 return this.usedSize;
205 }
206
207 public int getWindowHead()
208 {
209 return this.windowHead;
210 }
211 }
212 }
213
214
215
216