TCP链接测试

这个部分非常顺利,可能是由于前面的部分代码写的没有问题,在更换至虚拟机之后一次就成功了,下面是运行测试成功的截图
![[0ddb6028c9158a2edf475e82409c5982_720.png]]

Ping结果分析思路

这个部分由于校园网太好了,我连续 ping 了四万个包都没有丢包,所以我委托我的朋友在他的服务器上面挂了一个ping的进程来获取这个文件。建议提供一个标准的分析文件,否则遇到南大校园网根本没有办法做

这里我写了一段python代码来分析整个ping的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import os
import re
import sys
from dataclasses import dataclass
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm

srcfile = "data_danny.txt"
test_line = "[1730994037.268124] 64 bytes from 171.67.215.200: icmp_seq=1 ttl=228 time=206 ms"
regex = r"\[(\d+\.\d+)\] 64 bytes from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}): icmp_seq=(\d+) ttl=(\d+) time=(\d+) ms"

@dataclass
class ResponseRecord:
seq:int = -1
ttl:int = -1
time:int = -1
timestamp:float = None

def prepare_response_list(src_path:str)->list[ResponseRecord]:
pattern = re.compile(regex)
response_records = []
with open(srcfile, 'r') as f:
data = f.read()
for lines in data.split("\n"):
match = pattern.match(lines)
if match:
timestamp = float(match.group(1))
seq = int(match.group(3))
ttl = int(match.group(4))
time = int(match.group(5))
response_record = ResponseRecord(seq,ttl,time,timestamp)
response_records.append(response_record)
response_records.sort(key=lambda x: x.seq)
return response_records

def analyze_overall_delivery_rate(responses:list[ResponseRecord])->float:
total_response = len(responses)
max_seq = responses[-1].seq
return total_response/max_seq

def analyze_longest_consecutive_string(responses:list[ResponseRecord])->int:
current_seq = 0
this_consecutive = 0
total_consecutive = 0
for response in responses:
this_consecutive += 1
if response.seq > current_seq:
total_consecutive = max(this_consecutive, total_consecutive)
this_consecutive = 0
current_seq = response.seq
current_seq += 1
total_consecutive = max(this_consecutive, total_consecutive)
return total_consecutive

def analyze_longest_burst_of_losses(responses:list[ResponseRecord])->int:
current_seq = 0
total_brust = 0
for response in responses:
if response.seq > current_seq:
this_brust = response.seq - current_seq - 1
total_brust = max(this_brust, total_brust)
current_seq = response.seq
current_seq += 1
return total_brust

def analyze_loss_event(responses:list[ResponseRecord])->tuple[float,float]:
receive_loss_event = 0
loss_loss_event = 0
receive_receive_event = 0
loss_receive_event = 0
for i in range(len(responses)):
first = responses[i]
second = responses[i+1] if i+1 < len(responses) else None
if second:
if second.seq != first.seq + 1:
receive_loss_event += 1
else:
receive_receive_event += 1

if second.seq != first.seq + 1:
# detected a loss event
loss_receive_event += 1
this_loss_loss_event = second.seq - first.seq - 2
if this_loss_loss_event > 0:
loss_loss_event += this_loss_loss_event
receive_loss_rate = receive_loss_event/(receive_loss_event + receive_receive_event)
loss_loss_rate = loss_loss_event/(loss_loss_event + loss_receive_event)
return receive_loss_rate, loss_loss_rate

def analyze_rtt(responses:list[ResponseRecord])->tuple[int,int]:
rtt_min = 1000000
rtt_max = -1
for response in responses:
rtt_min = min(rtt_min, response.time)
rtt_max = max(rtt_max, response.time)
return rtt_min, rtt_max

def plot_rtt_over_time(responses: list[ResponseRecord]):
if os.path.exists('rtt_over_time.png'):
return
times = [response.timestamp for response in responses]
rtts = [response.time for response in responses]

actual_times = [datetime.fromtimestamp(ts) for ts in times]

plt.figure(figsize=(10, 5))
plt.plot(actual_times, rtts, marker='o', linestyle='-')
plt.xlabel('Time of Day')
plt.ylabel('RTT (ms)')
plt.title('RTT over Time')
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('rtt_over_time.png')
plt.show()

def plot_rtt_distribution(responses: list[ResponseRecord]):
if os.path.exists('rtt_distribution.png') and os.path.exists('rtt_cdf.png'):
return
rtts = [response.time for response in responses]

plt.figure(figsize=(10, 5))
plt.hist(rtts, bins=50, alpha=0.75, edgecolor='black')
plt.xlabel('RTT (ms)')
plt.ylabel('Frequency')
plt.title('RTT Distribution')
plt.grid(True)
plt.savefig('rtt_distribution.png')
plt.show()

plt.figure(figsize=(10, 5))
sorted_rtts = np.sort(rtts)
cdf = np.arange(len(sorted_rtts)) / float(len(sorted_rtts))
plt.plot(sorted_rtts, cdf, marker='.', linestyle='none')
plt.xlabel('RTT (ms)')
plt.ylabel('CDF')
plt.title('Cumulative Distribution Function of RTT')
plt.grid(True)
plt.savefig('rtt_cdf.png')
plt.show()

def plot_rtt_correlation(responses: list[ResponseRecord]):
if os.path.exists('rtt_correlation.png'):
return
rtts = [response.time for response in responses]

if len(rtts) < 2:
print("Not enough data points to plot RTT correlation.")
return

rtt_n = rtts[:-1]
rtt_n_plus_1 = rtts[1:]
plt.figure()
hist, xedges, yedges, image = plt.hist2d(rtt_n, rtt_n_plus_1, bins=30, cmap='viridis', norm=LogNorm())
plt.colorbar(image, label="Frequency")
plt.xlabel("RTT_N")
plt.ylabel("RTT_N+1")
plt.title("Heatmap of RTT_N vs RTT_N+1")
plt.savefig('rtt_correlation_heatmap.png')
plt.close()

plt.figure(figsize=(10, 5))
plt.scatter(rtt_n, rtt_n_plus_1, alpha=0.5)
plt.xlabel('RTT of ping #N (ms)')
plt.ylabel('RTT of ping #N+1 (ms)')
plt.title('Correlation between RTT of ping #N and RTT of ping #N+1')
plt.grid(True)
plt.savefig('rtt_correlation.png')
plt.show()

if __name__ == "__main__":
responses = prepare_response_list(srcfile)
delivery_rate = analyze_overall_delivery_rate(responses)
print(f"Delivery rate: {delivery_rate*100:.5f}%")
longest_consecutive = analyze_longest_consecutive_string(responses)
print(f"Longest consecutive string: {longest_consecutive}")
longest_brust = analyze_longest_burst_of_losses(responses)
print(f"Longest burst of losses: {longest_brust}")
receive_loss_rate, loss_loss_rate = analyze_loss_event(responses)
print(f"Receive_receive rate: {(1 - receive_loss_rate)*100:.5f}%")
print(f"Loss_receive rate: {(1 - loss_loss_rate)*100:.5f}%")
rtt_min, rtt_max = analyze_rtt(responses)
print(f"RTT min: {rtt_min} ms")
print(f"RTT max: {rtt_max} ms")
plot_rtt_over_time(responses)
plot_rtt_distribution(responses)
plot_rtt_correlation(responses)

这里我选择用正则表达式先把整个文件解析出来,存放到这个 responses 里面,然后后续都读取这个list来解析

下面是这个程序的输出:

1
2
3
4
5
6
7
Delivery rate: 98.10246%
Longest consecutive string: 1508
Longest burst of losses: 2
Receive_receive rate: 98.13828%
Loss_receive rate: 96.24838%
RTT min: 193 ms
RTT max: 1145 ms

ping结果

Overall Delivery Rate

总共的送达率为 98.10236%

最长的连续送达串

最长的没有丢包的字符串长度为 1508

最长丢包数量

最长的丢包数量为 2

丢包情况分析

第 N 号包收到而第 N + 1号包也被接受

这个概率是 98.13828%

N 号丢失到而第 N + 1号包被接受

该概率为 96.24838%

分析

分析上面两个数据可以发现,在前一个包被接受的情况下,后一个包被接受的概率比总体的送达率要高,这说明此时的网络状况较好,所以更不容易丢包,而如果前一个包丢失了,下一个包成功送达的概率较低,这表明这个时候网络出现波动,所有连续丢包的可能性比较高

最小最大RTT

最小的RTT是 193 ms 而最大 RTT是 1145ms

RTT-Time图

该图如下:
![[Pasted image 20241112163403.png]]

Histogram and CDF

这两个图如下:
![[Pasted image 20241112163502.png]]

![[Pasted image 20241112163523.png]]

Correlation of N and N+1

这个的heatmap如下:
![[Pasted image 20241112163620.png]]

分析

整个数据说明,这个网络还是比较稳定的,某些时间段会出现网络波动,而这种波动会影响相邻的几个包,这非常符合我的预期