-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path屎记.txt
More file actions
2214 lines (1505 loc) · 133 KB
/
Copy path屎记.txt
File metadata and controls
2214 lines (1505 loc) · 133 KB
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
cmd 1b
sn 3b
una 3b
标识
流
不可靠包 //无序 收到就处理 可以设置重试次数 超过丢弃
可靠包
先只实现流, 包模式 有序是多余的。与流功能本质上重叠的
tick 需要定时器 有没有数据都会调用 收发数据必定调用
#如果flag不够用的解决方法
分段。比如 第一个cmd 表示 有没有流和其他 和有没有下一个cmd
如果有 则继续读取 且 flag 意义换成另外的
#流
count 数据块数量
offset 第一个是 基准
len 2B(0表示1 最大65536)
data
offset 之后的是 相较于前一个的偏移(只能大于第一个)
len
data
#不可靠包
可跟 流数据 在一个包里。
不可靠包 丢了也不影响窗口滑动。窗口滑动是以 数据范围 计算的。
#基于数据范围了 una 不可靠了
因为sn不会复用。就不会重发。需要通知对方 接收偏移。
包头的una sn就没用了??。设计的乱七八糟的。丢包全靠 超时重发?
una sn还是有用的。可以确认 哪个数据包收到了。但是丢包的情况 怎么处理。una的更新问题。
当取出数据的时候,更新该包为una? 貌似可行。因为无论是重发的还是第一次发的 都是自增的sn虽然没法证明 payload集合 的顺序
#una 只能知道 连续的最早已接受的 需要额外的ack 才能实现fastack比如 ackmask
#ackmask
使用bitset实现
记录una 直到最大的sn 的接收情况。
#丢包问题
仅仅使用una 和检查包是否所有数据都被接收 去判断前面的seg 丢失的部分是否已接收是做不到的 做不到的 做不到的
必须使用ack
因为seg不会重发 所以单靠una 和 数据范围检查 做不到。必须有ack
#ackmask
不需要特别多,因为丢包率不是特别大 100bit应该就够
包头加 一个count(1b) 记录位数 最大255
之后跟着的是 byte[] 存下最低count位数(取8的倍数)
如果count0 说明 最大已知的包 已经处理完了 等待接收下一个包
#不使用ackmask的情况更新una
因为无法直到包前面的包传输的数据范围 是不是必然小于当前包
如果小于 可以直接滑动 但是无法判断,因为存在重传的,重传的也可能丢。不能直接假定接收了
但是,可以加入一个字段,指向前一个 有数据的sn
在数据传输完毕的时候,如果发现 没改变。则直接更新una即可
#目前想到的
cmd
sn 唯一标记包
una rcv_next_sn
rcv_offset 发送方的rcv_offset 用来滑动rcv用
preHavaDataSn 上一个有数据的sn(没数据传输的时候 可以直接更新una 不过不更新una也不影响传输 大杂烩 acksn也没实现)
貌似目前 preHavaDataSn 是多余的 但是确实有效。就像假定都接收了一样
preHavaDataSn 是否根据对方的反馈进行调整?互相滑动。而不是只根据上一个有数据的sn。可以避免回环。比如长时间不发数据最终就会回环。
# 分析una的作用 和不使用ACK时的替代
una 是发送方rcv_next_sn 表示下一个要接受的sn
可以知道 对方 第一个 为接收到的 sn。 比如 丢了的第一个包。可以实现重传功能。
但是 需要的场景是包不能直接重发。
但是 seg附带rcv_offset 也可以实现 等同于una的功能。 可知道 第一个未接收的数据范围(小于的 则表示已接收 可以进行滑动 )
una可以根据sn滑动 也可以根据 seg.rcv_offset
una和rcv_offset 功能重叠了 seg.una非必须
但是后续设计 快速重传 和ackmsk 有用 作为ackmask的起始
使用una和ackmask的话 基于rcv_offset 的滑动就多余了。
不使用的话,使用rcv_offset代替 una(分片传输协议中的una作用)
# 梳理 rcv_next_sn的滑动
目前是 rcv_next_sn=_maxint_(rcv_next_sn,segment.sn);
是偷懒的方式 只是直接接收了 sn 不考虑丢包。segment sn没有意义了 una 也没意义 只有rcv_offset有意义
1.无ack 基于超时重传 sn una都是多余的 只根据rcv_offset判断是否接受到
2.ackmas 基于fastack快速重传 rcv_offset是多余的
# 梳理 逻辑
## input
判断segment是否合法
-.接收数据(不可能出现超出缓冲区范围的情况,如果有 一定是意外)
1.将una之前的segment标记为已接收
2.对snd_ackmask进行标记 根据发来的ackmask
3.根据seg.rcv_offset 进行滑动
4.进行滑动处理。
根据ackmask 进行ack确认 跳过指定次数的,立即标记为需要重传, 并滑动
(因为每个包 不能原样重发 标记需要重发的范围 等待确认的这个包 就没用了 不需要存了,连续数据范围合并时 最大重传次数 取最大值 或者不合并,合并徒增复杂度,极小包情况下会零碎多而已)
可能的漏洞(如果中间人串改了数据段的数量缩小了,导致数据认为已经接收了,对方滑动了就不会重发了)
如果seg是next_sn 直接处理 不放入rcv_segments(并更新rcv_offset)
否则 放入
snd_next_sn(自己要发送的下一个sn序号)
maxSn(收到的最大的远方sn)
rcv_next_sn(要接收的下一个远方sn)
byte[] ackmask (从rcv_next_snk开始 每个bit 表示 之后第几个sn 是否接收到)
请根据这些,
//请使用java实现以下功能。 ,和。我需要你实现 基于byte[] 从对方 rcv_next_sn(第一个未接收到的sn) 到 对方接收到的最大的sn 这个范围。每个bit 表示 是否接收
ackmask 第一个bit必定位0 因为 开始是 rcv_next_sn 是没收到的sn
# 根据ackmask滑动
//snd_ackmask 只需要rcv_ackmask 发送到远方只需要远方处理完就丢了
rcv_ackmask
# 没数据的包 是否直接假定对方收到了?
如果附带snd_offset 没有数据发生 只要本地rcv_offset和远程snd_offset相同 可以直接更新una。但是意义不大好像。因为有数据传输的时候没用。使用fastack和ackmask即可
#rcv_next_sn(una)的更新?
接收 ackmask 也只能确认snd_里的哪些 没被接收 跟rcv_next_sn无关
rcv_next_sn是 下一个要接收的sn。***除非允许sn重发 或 发送方 使用一个bitarr 标记重发了的数据包。接收方 直接假定收到了.....不对啊。。。。交叉矛盾
啊。可以使用 seg.rcv_offset解决。如果发送方检查丢了的 seg 发现小于 远程rcv_offset 就认为已经接收了
小于远程 rcv_offset有几种情况 1.没丢收到了 2.丢了 但是收到了重发的数据填补了
不对。。。应该是seg.snd_offset 在接收时处理。。输错了。但是 只有在数据传输完毕的时候 才会同步rcv_next_sn
还有一种方法标记是否包含重发的。如果不包含重发的。如果rcv_offset 等于 当前包的最大值。则表示这个包前面的包 需要的数据都接收了。直接更新rcv_next_sn
不对。。重发的必然小于 新发的。不需要标记。 *******直接 判断rcv_offset>=当前包 最大的数据位置。 更新una为seg.sn+1
rcv_next_sn貌似 仅仅只在 ackmask 中使用?
#rcv_next_sn(una)的更新规则
1.如果seg.sn=rcv_next_sn 更新 有无数据都不影响
2.如果rcv_offset>=当前包 最大的数据位置 更新 主要应对 丢包重发的 没有数据的无法处理,必须配合上一条 共同完成 rcv_next_sn的更新
而rcv_next_sn 与维护ackmask 相关 与fastack相关
3.无数据时附带snd_offset 。 接收时如果 snd_offset=rcv_offset rcv_next_sn=seg.sn
在数据传输完毕后 不会更新了... 因为丢包 导致规则1 无效 而规则2 是有需要有数据 才生效。如何解决?在无数据的时候 附带 snd_offset?
规则3.无数据时附带snd_offset
???无数据时是不是ackmask也能省去了?
# snd_offset的更新
从头连续的 被确认的segment 取最大的 数据位置(payload.offset+payload.len)
# rcv_offset的更新
1.如果seg.sn=rcv_next_sn 更新 seg 最大数据位置
2.从 rcv_segments 取出连续的 取最大的 数据位置(payload.offset+payload.len)
#snd rcv segments 是多余的
数据可以从缓冲区取,数据范围 DataRange 管理着(只是标记了范围)
不对。。。。snd的不多余 因为
#梳理结构
cmd 1
sn 4
una 4
rcv_offset 4
ackmask count 0-1
ackmask 0-8
# 为什 l2.rcv_next_sn 42 但是lcp input的时候 认为35未收到 且命名只测试了丢包 没测试ackmask 不应该出现的快速重传字样 为什么出现了?
因为 rcv_offset在recv的时候才会更新。导致明明收到了的数据 以为没收到。
使用1.补正的时候 正常了。但是 存在新的问题(对方可以没有限制的不断发数据,无论recv 是否取出,如果没有取出会导致 溢出)
解决方法
1.补正 打包seg时 seg.rcv_offset+=rcvBuf.readableBytes();
缺点:无法实现流控 除非主动丢包,但是发送端无法知道 缓冲区满了。会不断重发
2.加入额外的包字段 像wnd字段一样告知 窗口大小。
3.修改ack机制。ack的时候 根据连续的最大值 判断真实的rcv_offset
方案3 改了半天不知道怎么弄 暂时方案1 如果rcvBuf writerIndex 超过缓冲区2倍就丢弃
错了1.补正 不能使用rcvBuf.readableBytes 因为 存在空缺。 要使用rcv_dr.canLeftShift(ACK) 得到最左边还没取出的数据长度
找到bug了。是una的问题
rcv_next_sn 在对方没有payload的包 比较对方的sn_offset 然后直接更新了una
应该不传输sn_offset而是 传输 最大位置
未开启ackmask不会触发快速重传。应该
但是为什么会触发?好像是在数据传输完毕的时候。传输的end_sn_offset 发现了跳过的sn。触发了快速重传,不是bug
应该是完成了。就差实现ackmask了
# 新问题
丢包后 莫名其妙触发快速重传。但是目前没开启ackmask
重传是根据rmt_rcv_offset 标记的(之前有丢过包应该 重发的已经被接收了 但是una无法更新(snd_offset只在传输停止的时候附带))
由于una未更新, 进入了一个地方(seg存在未接收的部分,但是实际上远程好像已经接收了,lcp标记重发的时候 lcp认为没被确认 而l2 已经接收)
测试发现与seg.snd_offset无关 因为 snd_offset只在数据传输完毕的时候 用来对比无条件同步una用。数据传输过程中没用
不清楚算不算bug和如何解决。目前是正常运行,只是没详细考虑到这个情况、逻辑貌似是正常的。数据也无误的重发了 lcp认为 未接收的部分
数据能正常传输,收到了重发的包,但是l2的una未更新。
解决方法,暂时忽略,加入ackmask 自然解决了。
但是不搞清楚原因,任意埋坑。
大致原因是l2的rcv_next_sn 138 与153 差距太多 为什么这样?是这些包 都在rcv_offset之后吗
另一个原因可能是
为什么rcv_next_sn 不能用real_offset 进行比较 而是rcv_offset比较?
为什么换成real_rcv_offset就进了offset 范围错误的异常了?
不清楚,乍一想以为是 超过了接收的缓冲区大小。后一想不对, 在lcp里异常 标记了 实际未接收的数据为已接收状态。不知道为什么会变成这样
伴随很多 忽略error 但是不应该连续忽略那么多。难道是una的问题 还有bug1也跟着刷
rcv_next_sn就是una 但是没想明白使用real_offset 应该不会导致sn 确认了未接收的数据吧
毕竟real_rcv_offset是实际接收了的
啊!难道是循环里写错了。real_rcv_offset和rcv_offset必然跟其他情况有关。差了一个包的偏移之类?相关的模糊的感觉
发现出现这个情况的时候 lcp没数据发送,缓冲区内数据都为确认,无法发送数据。此时携带的 snd_offset也无法帮上忙。因为是数据阻塞而不是数据传输完成。
最可能的原因,不能根据2进行判断。虽然 使用rcv_offset而不是real_rcv_offset看样子没问题(偶尔也出现了 不知道怎么回事)
很有可能,比如 缓冲区满了。现在已经发了1,2,3,4 。缓冲区即将满了,重发了1,2
包里只有1,2。以为sn之前的都收到了。实际上3,4没收到。
lcp以为收到了,进行markRange 但是调试判断发现 l2实际没收到 所以进入了 offset范围错误的问题
解决方法:彻底抛弃方案2,引入ackmask
或者lcp计算una发给l2 虽然滞后 但是还是准确的
引入ackmask 只能告诉 对方哪个收到了,加速 更新 rmt_rcv_offset。
并不会更新 l2的una。还是要lcp 发送
不对啊,如果不使用ackmask una不就不需要了。 snd自己判断,l2也不需要维护,只基与rcv_offset就行了。
因为现在,就算不更新rcv_next_sn 也不影响最终传输。
要想更新,只能 lcp进行反向更新
总结
rcv_next_sn 在只基于超时重传的时候 没用,需要ackmask 配合 作为 基础偏移序号用,需要远端进行反馈。
反馈方式
1.发送计算得到的rmt_una(受延迟影响较大,导致ackmask 滞后)
2.每个包进行标记, 表示这个包被完整确认的时候,更新到的una 但是需要考虑丢包 根据ackmask 计算una 也就是滑动
先使用方案1吧 方案2需要ackmask实现后 先暂时搁置
#梳理结构
cmd 1
sn 4
una 4
rcv_offset 4
end_offset 4(好像不需要了 这个是更新una的方案1 现在由updateUna 实现)
updateUna 4
ackmask count 0-1
ackmask 0-8
16+8+1+1=26
头有点臃肿了,再加上其他数据。感觉比kcp大。但是 支持 范围传输
范围传输单个片段 大致1 4 2 ,有数据的包最低 除了数据至少要33字节....
rcv_offset貌似是非必须的,如果使用了sn 和ackmask...确实....
简化版的协议 只有cmd rcv_offset
大致30多字节 是信息
如果没ackmask 就不打包 una 了,出现una基本也代表 可能丢包了
# 新问题
input不需要保留 seg
takeSend需要。 之前是 非连续的 确认收到就可以删了。
现在 una错误, 不能删,为了连续的滑动 增长una发给l2
导致发送端开销比较大。是个缺陷。
# 重发问题。。重发只能发1次。因为数据 转移到了新的数据包里。
原先的可以删除了,但是不是作为 确认sn 删除 而是直接删除。
#snd_buf_size 是没用的
因为目前是 不限制 send大小。
所以,只受远方 缓冲区大小 影响。
#缺陷
对fec支持不是很好
包大小固定,所以难以以包为分片。
如果以数据范围进行分片。比如 实际传输的是 fec编码后的数据。
每1000B 为单位,比如fec分片3+1模式。
可能片1,2的部分塞到一个包里。一旦丢失,2个分片都是不完整的。无法参与fec运算。
就是 分太小,多个片塞到一个包,都丢失或丢失部分。
分太大,一个包收不完,比如超大1M,mtu1400,窟窿一样,每个片随机缺失部分。也无法参与fec。
就算是均衡的情况,也总会有些许缺失。
除非,设计排序方法。尽量每个包,只放一个包或按丢包率重发次数 先后,进行排列,最大化减小 丢失时的影响。
# 可能的大小优化
没数据的时候 不需要携带 end_offset
undateuna 也可以考虑暂停。不增长发送
只需要1个cmd
新问题
l2发给lcp 极为缓慢 300多次循环 才接受了3000
原因不清楚,估计是太零碎了?和丢包率80的缘故?lcp的缓冲区没取出过。最多接收4096
# 积压ackmask
由于远方未recv 持续的交互 导致ack积压?
# 不对。。。发送逻辑存在问题。几百轮循环 远远超过rto 也经常发不到4096
检查发现。lcp的rnd_dr都是 连续的是末尾没有收到数据
。。。。找到原因了。 l2.takeSend(30)... 测试的时候 只注意了 lcp发给l2 所以每次只发了十几B最多。同步慢是正常的
# unpdateuna 可以改回 接收方自动更新,但是需要发送方 配合
之前不能根据 rcv_offset 滑动una是因为。可能包含重发的数据
比如 a1,b2,c3,d4
a1丢了,重发了a5 不能根据单个包的数据都被接收 来滑动una
因为 b2,c3可能还没接到。除非能确保 能确保 能确保 这个数据包里的数据,前面的数据都被接收了。
但是又复杂化了。。。算了 暂时使用 发送方更新接收方的una的方案吧
#seg.rcv_offset是非必须的。因为远方获取 真实rcv_offset 是根据 队列 最左边确认收到的包的数量 加上之前的snd_offset得到的
不需要 接收方 反馈rcv_offset。 可以删除rcv_offset 字段。
## 模式
1.超时重传 + 范围传输
传输时,头部只需要rcv_offset。丢包重传全靠发送方 超时重传
2.sn+发送方更新接收方una+超时重传+范围传输
会被前面的数据包丢失阻塞。影响性能
3.sn+ackmask(fastack) +发送方更新接收方una+超时重传+范围传输
只有模式1和3常用
1.只适合 在可能丢包的 安全信道传输。延迟无感,接收缓冲区大的情况。
2.范围传输的问题,包不允许直接原样重发(sn无法复用)。 方案2是方案3关掉ackmask的场景。适合几乎不丢包的情况,不然会阻塞,尤其是没有ack机制的情况。导致收到了的对方无法感知,会连着重发浪费。
3.ackmask 告知发送方 哪些包被接收了,重发已收到的问题。
总结,包头难以减少。。。。1,2没啥用 只有3能用。包结构头部大小难以减少。
#使用注意问题
初始化时
rmt_una 要等于 rcv_next_sn
测试sn从-10开始,增加到0 结果 int回绕的时候出问题了。重新测试 初始化把rmt_una改成rcv_next_sn 一样的初始值-10
正确执行了,sn增长到0到正数 正常运行。
高丢包率的情况,ackmask会无限增长。。。。包没有数据的也许不需要增长sn。这样就能将范围控制在 含有重发的数据包上。
## 梳理
#end_offset作用
在没有数据传输的更新una,引入updateUna后 多余了。
segment.end_offset = snd_offset + snd_buf.writerIndex();
#rcv_offset
告诉发送方自己当前接收了多少,有点多余。发送方可以计算出真实的rcv_offset。
但是要判断接收方能接收多少,就需要 rcv_offset而不是real_rcv_offset
real_rcv_offset是确认收到的数据末尾位置,包含接收方在缓冲区内未 调用recv()取出的。
如果根据real_rcv_offset发送,起不到计算 可接收 缓冲区大小的作用。
可发送的数据数量为int bufLimit = _itimediff(rmt_rcv_offset + rcv_buf_size, snd_offset);
#rmt_una
发送方计算得到的 接收方需要接收到的下一个sn
#updateUna
发送方 更新接收方的una
#rcv_next_sn(una)
接收方从发送方获取到的una。作为ackmask的起始。
与ackmask一同发给 发送方进行 确认哪些包收到了
#TODO
rto的计算更新
高丢包率的情况,只重发前面的。 百分之80丢包,ackmask居然90字节。跨越700个包。
## 不对 有bug
高丢包率的情况。发现 sn一直没变。
结果发现 接收方是 rcv_next_sn 152
发送方的对列 第一个是153。。。。没有152。152莫名其妙被删除了
不清楚是计算una的问题 还是 删除逻辑的问题
====测试发现 152没被加入snd_segments
152没有数据。所以每加入。
更新una的规则 应该加一条
滑动距离加上 snd_segments第一个sn 减去 rmt_una
rmt_una+= _itimediff(first.sn,rmt_una)
#加上了之后 还是卡在153 卡住的问题 不在una?而是需要的数据没收到所以滑动失败?
为什么没收到?是被提前删除了?永远不会发送了?
。。。。测试发现。153全部被接收了。但是并没有滑动。原因不明
。。。为什么l2的rcv_dr size是0 如果rcv_dr相关的是 正确的
发送方 为什么没有发?发送方计算的real_rcv_offset与 接收方的rcv_offset一致
发送方snd_segments 明明有很多携带了数据的 seg
为什么 接收方没有接收?
发现发送方的 snd_offset 小于接收方。落后了一个rcv_buf_size左右的大小。所以 接收方收不到 。
收到的都是过时的数据。
貌似需要根据 接收方的rcv_offset 不仅更新 real_rcv_offset(取最大值,在丢包时滑动snd_segments和snd_offset)
的功能并没有起作用
先检查这个功能为什么没效果,不行可能就需要增加一条 snd_offset的规则
滑动至 real_rcv_offset
segments 不用管,下次会删除
发现了一个其他bug
l2给lcp发数据。没数据发了之后,每次l2发送的updateUna 都没改变。差距超过int 一半的时候 会导致判断大小的结果 相反
发现lcp 以为的rmt_real_rcv_offset 并不是 l2真正的收到的位置。。。。
rmt_real_rcv_offset = _maxint_(rmt_real_rcv_offset, canDistance + snd_offset);
// rmt_real_rcv_offset = _maxint_(rmt_real_rcv_offset, segment.rcv_offset);
。。。。这一句我觉得 没用就注释了。 以为只靠数据范围的确认 滑动 就行了。
但是还没清楚为什么 发送方的 snd_dr前面的没有确认。
我应该是写了 如果包被确认,所有的数据都会标记为 ack
应该是能滑动的。难道ackSn 方法有问题。并没有对该确认的数据进行确认。
难道是确认的时候 范围计算错了?不清楚有什么影响。就算不修复
使用 rmt_real_rcv_offset = _maxint_(rmt_real_rcv_offset, segment.rcv_offset);
也能消除这个问题吧。尽管并没有解决原本的问题?
发现末尾压根没进过markRange。也是。。。还是input的 问题吧
。。。好像就是不能注释、、当时以为 不需要rcv_offset参数删了。后来发现需要就没加上。其他地方用了,这个地方以为不需要就没加
rmt_real_rcv_offset = _maxint_(rmt_real_rcv_offset, segment.rcv_offset);
real_rcv_offset的更新方式
1.加 滑动已确认的距离
2.根据 远程发来的rcv_offset 取最大值
修复后 再看看 会不会积压,刚才持续增长ackmask的尺寸。是因为rmt_real_rcv_offset计算错误。没有max(seg.rcv_offset,)
好像正常了,una会正常增长了。
ackmask没有很大。不会无限增长了。但是依旧有几十。大概十几 ,20多字节 左右。可以接受。
加入高丢包 高频发送 最左边的 应该会好些。
。。。。ackmask 最大达到30多。。。。达到66。看样子不会无限增长
80丢包情况基本也无法正常使用,不用担心ackmask的问题。
除非伪造了一个sn。非常大,加上机制确保不接受过大的sn。
有个问题。
应该不会遇见,每个包平均1000的话,每秒1w包。大概能达到100Mbps速度。(10MB/s)
发送丢包(正常情况不会跨度那么大吧,还跟缓冲区大小和延迟有关)。
先写成 不接收 超过rcv_next_una 1w的包吧。抛异常
如果延迟很高,缓冲区很小,速率就很低。不丢包的情况。比如 往返延迟1秒
缓冲区4096。代表最多1秒只能传4KB数据。
如果要高延迟,还能高的传输速率,需要增加 rcv_buf_size。
# ackmask的问题
只能确认少数。比如 8字节的话 只能确认 una 后面的 63个是否被接受
如果传输中未接收的包数量超过63 后面的 就无法被确认。导致后续的 认为超时了。但是实际并没有。
如果要计算rto,应只检测 una和后面共64个。
或者 额外设计动态ackmask。批量对后面的数据进行确认。
解决方法
1.增加ackmask 的发送限制,不限制为8字节。
缺点:10M传输 mtu1000左右的情况。延迟1秒 大约空中有 1w的数据包。极端情况,假设 头部丢包。会维持1w/8 字节 大概1K的ackmask
可能就没数据能填充了。
可以间隔一些包,发送完整的ackmask。和 如果takeSend 剩余比较大,能填多少ackmask 填多少。
# 之前的ackmask 前面一个字节是长度。 最多表示256 字节长度。
改成 varint。避免限制只能256字节。
。。。算了 直接2字节表示长度吧。多1字节的问题。
#梳理结构
cmd 1
sn 4
una 4
rcv_offset 4
updateUna 4
ackmasklen 0|2
ackmask >0
最短头17 才能封包。但是一直17附带不了其他数据。无法正常传输。
传输最低需要 2+maxAckMaskLen + [1+4+2](数据范围)和数据体
大致是2+1~max 加 7 加1 最低28 才能发送1字节。
实际最低 30~40多才能传输数据,考虑如果是在高丢包且 限制极小包大小。 ackmask因为丢包会扩充。挤占了几到十几左右的容量。
#如果canUse 还有余
可以 继续填充 还未超时的数据。
#思考延迟与丢包 重发
发送方 发送和重发的数据范围 只有rmt_rcv_offset 开始 rcv_buf_size 范围
如果丢包,比如头部丢包了,必须 被跳过才会重发。或等待超时。
fastack重发是最快的也需要 一个往返。
也就是丢包发生,如果计算rto 使用原先的sn 表示收到了。
其实是不合理的。比如sn1 重发为3
1是时间100发出去
网络往返延迟200
假设 接收方收到2的时候 立刻 发送给发送方
发送方发现1丢了 此时已经经过200毫秒。
发送方 重发了数据 序号为3
3正常接收,反馈给 发送方
这样 1虽然丢了,但是处理的时候 视为接收到了的话。也参与超时计算是不合理的。
因为1事实上没收到,收到的是3。正好是1重发的数据收完了。
滑动的时候 判断1的数据范围收到了。就进行 确认(不是ack确认 而是snd发现数据范围收到了的确认)
会错误的计算1的rtt是 200+200 也就是翻倍了。而3是正常的一个200。
也许 rtt的计算 只需要考虑 直接收到的数据包。
可以统计丢包率,和排除丢的包 后 得到的网络延迟。
避免丢包导致的rtt计算剧增。加速超时重传。
和还需要考虑,计算丢包率,进行多倍发包的逻辑。
比如 靠前的数据 多倍发送(下一个包里 重复发送数据范围),
但是没有数据传输的时候 不准确。基本 单个包的rtt是最短时间。
没有数据传输,ack是没作用的吧。
#突然发现数据传输完毕 之后的una没有更新。
加一条规则
如果end_offset=real_rmt_rcv_offset
takeSend时
rmt_una=segment.sn+1;
if(end_offset==rmt_real_rcv_offset){
rmt_una=segment.sn+1;
}
# 虽然修复了 但是还有一个小问题
如果 数据一直在缓冲区不取出。 una也不会更新。暂且不管
只要接收方正常取出数据,就能正常发送。如果接收方不取出数据。
可能是失联了。暂时没设计 握手和断开 超时 等 连接状态的管理。
只设计了数据的传输
测试了下乱序接受,没什么错误。
啊啊啊啊啊出bug了,之前遇见过以为是其他问题导致的已经修复了
结果还是出了。
rcvBufWrite方法
readerIndex: -234, writerIndex: 258 (expected: 0 <= readerIndex <= writerIndex <= capacity(512))
int diff = _itimediff(payload.offset + payload.length, rcv_offset);
结果为0 数据的末端 是 rcv_offset 说明接收过了(虽然连续但是没有重叠的部分 所以不需要写入)
下面一个判断记得之前是<=0 就忽略。当时以为这里有问题好像改过。但是跟这里没关系。这次概率一样刚好又碰到。发现这里应该改回去。。。吧
if (diff < 0) {//检查 是否在范围
System.out.println("忽略过时的" + payload.offset);
return;//
}
。。。又出现了。错误的在下面的代码。忘了什么意思了
还有一个相减。好像是负数了,疑似是测试乱序接受出现的。是之前就有bug。
当时写错了,应该是相减 计算 写到缓冲区的位置,但是 写反了,变成负数了。
int paylaodOffset = payload.offset - offset; 结果为负数
offset是上面计算得到的 payload.offset和rcv_offset 最大值。
应该最大值offset -最小值payload.offset 计算得到缓冲区偏移
写反了,在乱序测试的时候才发现问题。
needLen也错了,真马虎。计算了payload实际需要读取的开始位置Offset
needLen计算并没有 减去这个偏移
int paylaodOffset = _itimediff(offset,payload.offset);
int needLen = _itimediff(payload.offset + payload.length, offset);
int needLen = _itimediff(payload.offset + payload.length 加上(-paylaodOffset), offset);
应该没问题了。再测试n遍试试。
#TODO改进 之前想 数据传输完毕之后 不需要更新una。结果改来改去又加上了。sn一直增长,尽管很难。但是una不动 非常漫长的时间之后 会造成回绕,可能影响运行的bug。
而且 好像有一个主要问题
比如数据即将发送完成,比如高频率的takeSend的话。
延迟非常高的情况,后续本来就不会携带数据的包。可以被丢弃的包,仅仅是同步una作用。(其实是多余的吧。哪怕不发,不增长snd_next_sn)
会导致,头部数据阻塞,导致后面 高频率的空包 变成了必须确认的加入到了ackmask。
也许需要设计针对 数据传输完毕(表示前面没有数据) 的包。
没有自己的sn,或者sn是不变的,可以重发的。既不增长una,也不在前面有数据阻塞的时候,空包导致的ackmask增长。
同时允许携带ackmask。比如
cmd
updateUna
rcv_offset
ackmasklen
ackmask
......越加越接近原样。。一开始想了只加updateUna,觉得需要携带信息,不传数据最起码携带信息,然后又觉得rcv_offset也需要加,ackmask也需要加。una也需要加,结果真就只少了sn。。。。
干脆改。。。改进也可能是多余的。。。。徒增复杂度。
亦或者不使用同一套sn 数据传输的sn只在有数据的时候增长 无数据的 在前一个有数据的sn为基准开始增长或独立
#延迟波动率计算?
延迟(不包含丢包)
#ackmask也许可以 间隔时间,或包数量 满足一个条件 就发送。而不需要每次都携带,
#测试发现。input很耗时。。。几百毫秒
定位到slideSnd方法耗时
定位到
snd_buf.readerIndex(slideDistance);
snd_buf.discardReadBytes();
疑似是 700M的文件放到了snd_buf。调用discardReadBytes 废弃已被确认的数据时。的开销?
并且随着时间耗时降低了,应该是容量减小相关。
所以snd_buf不建议放入过大的数据。
或者 将数据绑定到 DataRange上。 范围split的时候 拆分为多个Buf
700M 废弃4K及一下 耗时 130~200毫秒
200M 约30多毫秒
100M 约15毫秒
#发现新问题,lcp发l2收
但是出现连续的标记4,调试看了一下发现只有一个payload 说明是连续的segment被确认。
一发一收 无丢包模式,应该一次确认一个。为什么导致了lcp snd的积压和确认
。。。发现 测试里 有个if忘了删 isNeedSend 忘了删。里面逻辑没写好 屏蔽了。只剩下一个 间隔时间判断。所以导致了积压
核心逻辑没出问题
性能测试大概ByteBuf discard 1M的情况大概1w5每秒
4096的情况 700w
4M 3k
byteBuf discardReadBytes 太耗时,使用接收时废弃已接受的 来滑动sndBuf 不合适
如果是切成一块块数据分别存储 就可以避免这个问题。
而且不是必须使用ByteBuf。(至少觉得可以自动扩容和废弃读过的比较方便)
一股脑把数据都写入ByteBuf 接收时废弃非常耗时行不通。耗时估计是内存拷贝时间。
就算接收时不立即滑动snd。snd的内容过大 下次滑动依旧会非常耗时。
DataRange 太耗时了。needRanges每次都构造List返回
之前怕写错 recv 用的DataRange 逻辑上应该是获取 rcv_buf可读字节
跑了一段时间发现没有出现不匹配的情况。
删掉了recv里的needRange 性能上去了一点
和屏蔽了一个takeSend中 检查是否真的被接收了用的 代码
40秒,循环里完成759M文件的 模拟发送接收 每秒。。只有18M
删掉了多个 测试范围检查的代码
32秒。
单纯读文件。不写出22秒
实际传输大概性能接近或2倍(udp开销。。。没测试)
马虎。忘了rcvBuf 存在空袭。
之前为了优化不使用DataRange。
然后忘了这一点,后续测试文件模拟传输 也是循环中没模拟丢包乱序。
今天又跑了一遍乱序和丢包 发现出现了问题。
找了半天才想起来。rcvBuf 的可读字节不等于 连续的数据。
导致错误的滑动距离。触发了其他地方的断点(还好断点多 一运行就发现了错误)
另外发现简单优化 ackmask 连续滑动的 方法逻辑(虽然没什么用)
滑动最小距离,后面是1就连续。计算需要的距离然后滑动。
计算错了。。。马虎 也修复了。
修复了recv方法的bug。性能下降了。因为DataRange
RingArr 也发现了bug。。。不能代替list
split(limit)非常耗时,需要优化
needOne 第一行 split是不需要的,删了。性能好了一些。
经过简单的测试,发现不能满足使用。
发送缓冲区 达到1M 性能开销大概6倍?相较于4K
但是 4K根本的传输速度太低。主要在 snd_buf 的discardReadBytes 和 rcv_buf
需要额外编写方法,减少 数据的拷贝。
比如 尽量不频繁discard 但是。。容量大了之后 调用一次依旧会卡顿。比如错误使用snd_buf直接填入了几百M的文件,滑动一次 需要1到200多毫秒。影响很大。
使用 Unpooled.wrappedBuffer 得到的CompositeByteBuf 可以动态的添加
在send方法里 每个4K进行扩容,然后写入。discardReadBytes 在snd_buf(多个buf组合的) 达到很大时 也不会非常耗时
性能好像更糟了,而且非常耗时在32M的时候每4K创建一个对象。
几十秒创建完毕。屏蔽掉之后 反而快。比如Unpooled.buffer()得到的Buf 快些
之前测试 缓冲区大小1M 1G大概5秒 32M 三十多秒
现在 依旧是5秒多
单独测试。。。CompositeByteBuf 的discard确实快。不知道是不是循环使用的,还是自动分段扩容的?
好像不是循环的,写超过初始化容量,依旧可以写,说明扩容了,而且初始化数组第一个也没见 写然后discard 再写 没见循环写。
不需要麻烦的又造屎山轮子了。 从Unpooled.buffer() 换成 CompositeByteBuf 解决了discardReadBytes 性能问题
就算直接往snd_buf 写入700M的文件。 也不影响性能。(性能主要是 discardReadBytes 耗时 居然换成CompositeByteBuf 好了)
突然发现测试方法写错了, 性能很好。。。
(一次性调用send 传入700M 不到一秒 接近6000次包,发送完成)
。。看错了 之前测试减少数据量/100了。。实际只有7M.。。。。。。
完美的内存溢出了。。。java.lang.OutOfMemoryError: Java heap space
性能约1000M 5秒 与缓冲区大小无关了
好像没法提升了,DataRange也不是主要瓶颈。。大概吧
感觉性能已经凑合了。能用的程度。可能跟java也有关,和水平问题,做不到更高性能。
发现时间统计错了,前面的读取文件忘了删。现在是内存测试。
大概3秒 1000M 每秒300M。
测试有误
加了 发送间隔(如果没有数据需要发送就不发送)
导致,没有及时的发送确认。传输阻塞了
解决:每收到多少包,就忽略。
ignoreCount 每次收到 +1
发送归零。在小于间隔的时候,如果ignoreCount<阈值 忽略。否则 无视间隔,发送
1000M 依旧是5秒
因为测试是收发一起。 可能传输性能1v1 超过100M每秒 (收发性能可能不均衡 至少是超过100M最高接近200M)
仅内存测试结果
改了下又出bug了
l2:空包 在间隔内忽略
lcp:空包 在间隔内忽略
l2:空包 在间隔内忽略
lcp:空包 在间隔内忽略
l2:空包 在间隔内忽略
lcp:空包 在间隔内忽略
想让在需要的时候才发送,比如 lcp单方面向l2发送。
如果收到16次 才反馈一次,或达到限制间隔。 窗口32M 16次 每次最多1376字节 达不到瓶颈。
但是测试发现数据发不动。。。在某个时间之后 lcp没数据发了,跟l2一起都在间隔等待。。。不对啊。
32M的缓冲区,16次1376也不至于没数据发了。哪里想错了
也许应该 收到数据时,需要立即确认?没有数据时 可以周期性发送。
或者交给 应用管理。不多设计这个功能了。
至于32M缓冲区应该没满,测试数据未发送完成 发现是 测试写错了。
如果snd_buf.writerIndex 小于4096 则置入1M数据
但是 加了忽略功能,所有 跨度超过4096导致的没数据可发
一顿瞎改 性能降低了。。
。。。。好像是播放器没关,导致的测试性能影响。关掉 还是5秒。多了一点点
时间间隔好多余感觉。感觉不适合这个协议内部实现。
而是上层管理,需要什么时候发,什么时候发。内部不用实现。算了暂时不删了。
udp测试,发现了更多问题。。一头雾水
DataRange 疑似有问题,但是是其他错误断点先触发,可能是传入了错误的参数。是其他问题也许不是dr的问题
难道是线程安全问题
加了锁好像好了。测试udp是额外写了个线程,并且 主线程循环间隔时间 也会写数据。可能冲突了。
udp测试写错了。 不知道为什么OutOfMemoryError
lcp逻辑又出问题了。。不知道动了哪
之前的测试跑不了了 好像是una计算问题
离奇,重新写了一下 接收和标记数据。
之前一直进标记4。乱序收发也正常,刚才发现代码有问题,之前怎么跑通的。
现在重新梳理 重写了 input和 ackSn,现在不报错了。奇怪,之前怎么跑通的。
为什么好了,为什么坏了,为什么好了,为什么坏了,
报错了 rcv_buf 一看容量0 设置writerIndex 超出0就报错了。
突然发现rcv_buf 取出数据并不需要discard 直接修改writerIndex 为0即可。性能好些应该
需要先修改readerIndex 不然 readerIndex>writerIndex 异常
报错好像是逻辑错了。。。不是rcv_buf问题。
应该是刚改的ackSn
..错误的地方是 接收。而不是snd_dr
继续分析
una的更新规则
接收时
1.如果是下一个,则+1
2.如果远方下发,则取最大值
3.根据rmt_real_rcv_offset 进行确认
可计算得到要更新对方的 una
4.发送时 数据末尾=rmt_real_rcv_offset 更新远方una (表示对方已经接收完毕)
规则4 不知道为什么加上 问题就出现了。 删掉就正常。
int end_offset = snd_offset + snd_buf.writerIndex();
if (end_offset == rmt_real_rcv_offset) {
rmt_una = segment.sn + 1;
}
好像没问题看着
加上去也正常。啊?我刚才改了什么把bug修了?
udp测试貌似也正常跑通了。但是ackmask 居然达到了600多字节
也许应该加入sack
有个地方总是进,可能是丢包重发了的,重复接收时触发的。
可能是没加最小rto限制,被跳过就标记为unsend 等待下次取出范围发送了。而且乱序情况下总是进。应该就这个原因。
似乎有bug?高速发送的时候 每秒大概几千包。逻辑有问题? 本地单机测试 好像丢了很多
导致收不到数据,缓冲区1M。
检查发现 并没有丢包。每秒发送100包。接收方发送1包。
出现了 忽略过时的125216
忽略过时的126592
忽略过时的127968
忽略过时的129344
好像不是这个问题。
好像会丢包,不知道跟断点暂停有没有关系。 发送数量 和 另一个udp的 接收数量对不上。统计好像没问题
测试发现会。
不会。。。。使用AtomicInteger 统计发现没丢
emmm会丢、。会丢。。会丢
netty 本机udp 收发 好像极限是6w/s..... 总觉得好低性能
基本在3w~6w 接收
找其他软件测试。发现单机127.0.0.1 收发 好像最大也就 几十M每秒 应该是正常情况
70M左右
。。。不对是复制的iperf测试参数问题。
好像单机大概 最大150MB/s (每秒1w9包(每个8K))
如果1400 只有27.....
iperf3 -c 127.0.0.1 -i 1 -t 300 -u -b 3000M -l 1400
貌似 udp每秒最大不超过2w包比较合适 超过容易丢包。不过下载的kcp-netty 里的测速。能达到6w每秒 (mtu1400)
iperf3 换成64位。每秒2w2
纠正单机的速度 跟 包大小有关。不过超过1400 的udp没有参考价值。虽然单机能传输几百MB每秒。但是网络上 mtu一般使用1400
性能又下降了,发现是rcv_buf 新写的如果容量小于 rcv_buf_size
就设定容量。但是比较耗时。不知道 clear或重置writerIndex 能不能代替discard
并且 不会修改容量
可以。recv 基本是全部取出。所以clear(修改writerIndex和readerIndex=0)
可以
奇怪还是慢。而且内存溢出了
好像是使用clear后 越来越大了。容量,莫名其妙一直在扩容
不对 discard 也这样。应该是其他地方导致的。
recBuf.writeBytes(rcv_buf, readLen);后扩容了。
莫名其妙,明明最大writerIndex 很小。每次write莫名其妙容量翻倍?
不是每次,是达到一半就扩容好像。不是无限扩容
看错了。不是rcv_buf 是recBuf.....是参数,正常。
好像只是内存爆了。测试1G 一个发送在snd_buf 一个在外面 取出存着。
内存爆了
性能差不多 clear 和discard 不需要特意替代(clear快一点点 因为只是改指针)
内存爆了好像跟 payloads 每个都创建了一个buf 并写入数据的问题。
相当于snd_buf一份 rcvBuf一份 snd_segments.paylaods里面一份 怪不得溢出了。
payload.data.release(); 太耗时 没法直接调用。置null 好像没什么效果,不会立即回收
难道之前recBuf 调用了discard?(注释掉了 )
难道之前没测试过 接收所有。
溢出是recBuf内存不够了。
payload.data.release()并不耗时,是刚才测试recBuf没clear。(随手注释掉了)
以为是release 加了又耗时了。实际上没什么影响
并且内存不会暴涨了。snd_segments 里的buf清理ok
编写检查方法。遍历rcv_dr。判断远方是否已发送。
遍历snd_segment。判断被确认的 范围 是否远方已接受
。。。。定位半天bug又回到了之前发现的问题
使用clear代替后。乱序情况下,只有头部一些字节可以取。所以clear不合适
使用discard。容量减小了。。。扩容性能又下降了
((CompositeByteBuf)buf).addComponent(Unpooled.wrappedBuffer(new byte[1024*1024]));
比buf.capacity( 容量)快
扩容时,尽量添加比 需要的多的。减少扩容次数
或者考虑其他办法。
discardReadComponents() 然后再加进去?
不行。。io.netty.util.IllegalReferenceCountException: refCnt: 0 异常。buf已被释放
addComponent性能也不好。。
性能好差啊。。之前测试错了。 一种是刚好取完。直接clear性能最好。测试一直是这个。
以为是discard
想办法避免使用discard
设计多个缓冲区?循环使用?
Unpooled.buffer()和 CompositeByteBuf 好像discard性能差不多
CompositeByteBuf 在大数据量时 性能好
使用循环数组 封装了一个 循环Buf。discard不会导致 资源释放。
性能很好,每秒2000w次大概。测试大概 每秒 8000MB(4096+2 每次读写都调用discard 只是移动偏移 没有资源释放)
循环使用多个buf,并支持扩容(释放方法没做)
单次使用4096读写。2千2百完次每秒。
替换rcv_buf后。 4.8秒左右,性能没有影响。
替换snd_buf后 4.2秒左右。
但是snd_buf 需要考虑释放,比如放入了几百M的文件。
之后不发送这么大的数据了,会一直占几百M用不到。
再写个方法,释放未使用的 ByteBuf
总结,改善了 rcv_buf 缓冲区较大的时候。discard的性能问题(snd_buf也是,比如700M 耗时200多毫秒,无法正常使用的程度)
修改后,不会进行拷贝仅仅进行偏移。使用额外封装的方式,替换ByteBuf。
主要解决的是,取出缓冲区的部分,并废弃。比如 snd_buf 头部的被确认了,被确认的部分 就可以删了。调用discard比较方便。
rcv_buf 如果取出的程度等于 writerIndex 直接clear性能最好。但是 乱序的情况,只能取出头部的部分,也需要调用discard。
如果使用偏移 来解决 写的乱七八糟的容易搞错。而且 buffer 还是要discard不然无限的增长下去了。或者也使用多个循环使用。但是写到核心代码里 太乱了。
还是额外造了个轮子。封装 循环使用的ByteBuf。使用环形数组,主要在头部和尾部进行增加删除,不会触发拷贝。也没有链表的节点包装对象。随机访问也快。
(但是容量扩容 可能导致的问题。。。没考虑是否有bug。。一般不需要很大容量,暂时搁置考虑,目前是能用,也用不到 int 一半的元素数量那么多,目前每次扩容*2 拷贝数组)
测试100M 1.1秒左右 200M 1.6秒左右 300M 2秒左右 500M 2.6秒左右
1000M 4.2秒 。。。。。。。测试方法有问题吗,不是均匀的
应该能满足使用。
之前模拟丢包和随机接收。效率很慢。
快速重传触发了的被再次跳过的时候就忽略的。加上了如果超过100毫秒就 不忽略,标记为可以立刻取出发送的状态
发现接收数据的效率上去了。之前是龟速 半小时300KB。(只是测试能不能接收)
发现原来问题是,包重发了也丢了,只能等rto了。但是当前默认3000。丢了只能等,所以很慢。
发现之前设计的ack问题。跳过数量的问题,找到最后一个标记为接收的snd seg
然后将之前的 非done的 跳过次数+1 和标记为 需要发送
但是,有时候丢包,比如只有一个包的情况。没收到,虽然后续的包收到了(空包无数据 不会加入snd_segments)
导致检测不到,无法快速重传。
换了个逻辑。记录最大的被确认的sn。所有小于sn的未done的 均 跳过次数+1 触发快速重传
测试方法每次循环sleep 200
快速重传,刚才写的100毫秒就。导致 一个周期内重复发送。改成200,发现不会周期内重复发送了。效率也上升了。
几乎每秒都在输出到文件。几百字节。(单次takeSend 1400)
。。。马虎
if(System.currentTimeMillis()-cur.ts>200){
System.out.println("重发超过100毫秒的");
cur.ts=System.currentTimeMillis();//刚才没有置新的ts 标记重发后又会一直标记重发
经常停滞,不知道什么时候突然又继续了。停止的时候一直再重发
而且偶尔能看见 ackmask 是一堆 86,太规律了。跟忽略数量有关吗
01 01 间隔
//如果 远程的real_rcv_offset=end_offset// 没有数据要发送的时候 也持续更新una
int end_offset = snd_offset + snd_buf.writerIndex();
if (end_offset == rmt_real_rcv_offset) {
rmt_una = segment.sn + 1;
}
难道是这句导致的 注释掉后 依旧 ackmask依旧是一串的 86
基于udp的测试 应该不至于丢包那么严重吧单机。逻辑有问题,不知道为什么放到udp测试显现了。
收到的数据包 存在跨度 有的缺失了 比如sn1不存在
发现确实打包了。但是莫名其妙没接收到 奇数的
奇怪 发送好像是没问题。序号是自增的
但是接收为什么序号重复接收了。反序列化出问题了?
udp发送的时候 有什么地方错了?
但是为什么只有一端有问题,另一端的接收没有出现跨度?
takeSend检查 确实有打包啊,打包也立刻调用trySend 传递发送了。
为什么错误了。
发现位置原因,udp收到的buf 是空的,内容是空的。
发现 收到数据后 直接使用的同一个buf 并且没有clear导致的 发送出去时 头部附带了其他干扰数据
正常了
udp跑通了。但是发现一个问题,增大每秒发送的数据量时(200ms间隔,每次100)
17秒收到10MB。
但是发现一个问题
刚开始 会 一直刷
error ackSn 970忽略949
false
error ackSn 971忽略949
false
error ackSn 972忽略949
false
error ackSn 973忽略949
false
疑似很多包会被跳过。
估计是una有问题。
难道是刚开始。尝试先 空数据启动,然后 再发数据试试。
问题消失了。疑似 第一发数据的时候错误的更新了una?
每秒大概450包发送,(200ms间隔 每次100可能是线程sleep 的问题误差 和莫名其妙的丢包(单机丢包,不知道为什么))
正常传输成功。
不对 又出现了 erro ackSn
ackSn 小于 rmt_una
重新梳理una的更新规则
发送时。如果对方real_rcv_offset= 发送方end_offset
更新对方una。//接收好像有问题 如果乱序接收 好像会提前更新?
不过逻辑是取最大值,应该没问题吧
rcv_next_sn。
貌似不发送数据 一切正常
发现是先刷了 处理ack
然后快速重传跳过次数
之后才会出现
收到ackmask14 seg.una1597 [-14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1]
=================处理ackmask
如果没开ackmask 进入这里可能有问题?? 跨sn也可能是丢包
false
error ackSn 1598忽略1609
为什么头部丢包了?
rmt_una=1599
也就是发送方认为 对方下一需要接收的是1599
1111 0010废弃2 还是有2个没收到
发现有包被多次重发
而且频繁刷 如果没开ackmask 进入这里可能有问题?? 跨sn也可能是丢包
难道只是丢包造成?写的udp测试单机。 丢包率很大
为什么KCP-netty 的测速 统计 每秒能6w包?
升级了netty 测试 也达不到。
之前的测试逻辑是
循环几w 然后sleep500毫秒 计算 收到的数量。
现在改成5秒。基本能收到大部分了。
难道是积压了,虽然是本地发送,但是积压了。
修改测试方法试试,连续测试,每次结束后 输出统计数量。然后减去 数量。
先测试了sleep 2000 大部分能收到
sleep 1000 大量的没收到。 积压居然会滞后1秒以上?
在网络上传输必然会增大延迟。
重新测试,最多每秒4w。可能测试方法有问题
ByteBuf byteBuf = byteBufAllocator.ioBuffer(buf.readableBytes());
// ByteBuf byteBuf = Unpooled.buffer(buf.readableBytes());
byteBuf.writeBytes(buf);
ioBuffer是做什么用的?换成这个貌似丢包率少了一些。好奇kcp用的什么buf找到 是使用的ioBuffer这个方法创建的
totalSend = 466762
totalRecv = 464799
totalSend = 467148