1
1
import os
2
2
import re
3
- import sys
4
3
import logging
5
4
from binascii import crc32
6
5
from collections import deque
14
13
from socket import socket , MSG_WAITALL , error as SocketError
15
14
from struct import pack , unpack
16
15
from threading import Event , Semaphore , Thread
17
- from typing import (Any , Deque , Dict , Generator , Iterable , List , NamedTuple ,
16
+ from typing import (Any , Deque , Dict , Generator , Iterable , List , NamedTuple , Set ,
18
17
Tuple , Union )
19
18
20
19
from rich .progress import (BarColumn , Progress , TaskID , TextColumn ,
21
20
TransferSpeedColumn )
22
21
23
22
24
23
SERVER_ADDR = ('127.0.0.1' , 7523 )
25
- CHUNK_SIZE = 8192 # 默认数据块大小 (单位: 字节)
24
+ CHUNK_SIZE = 1024 * 16 # 默认数据块大小 (单位: 字节)
26
25
TIMEOUT = 60 * 5 # 全局超时时间
27
26
LEN_HEAD = 7
28
27
MAX_SEQ = 0xffffffff
@@ -57,28 +56,6 @@ def contains(cls, member: object) -> bool:
57
56
return member in cls .__members__ .values ()
58
57
59
58
60
- class DictQueue (dict ):
61
- def __init__ (self , size = None ):
62
- super ().__init__ ()
63
- self .size = size or float ('inf' )
64
- self .cur_seq = 0
65
-
66
- def put (self , value ):
67
- while len (self ) >= self .size :
68
- self .pop ()
69
-
70
- self [self .cur_seq ] = value
71
- logging .debug (f'[DictQueue] put { self .cur_seq } to { value } into { id (self )} ' )
72
- self .cur_seq = (self .cur_seq + 1 ) & MAX_SEQ
73
-
74
- def pop (self , seq = None ):
75
- if seq is None :
76
- seq = min (self .keys ())
77
- value = super ().pop (seq )
78
- logging .debug (f'[DictQueue] pop { seq } as { value } from { id (self )} ' )
79
- return value
80
-
81
-
82
59
class Packet (NamedTuple ):
83
60
flag : Flag
84
61
body : bytes
@@ -251,53 +228,39 @@ def __init__(self, size=16):
251
228
self .send_q = Queue (self .size * 16 )
252
229
self .recv_q = Queue (self .size * 16 )
253
230
self .done = Event ()
254
- self .connections = {}
231
+ self .connections : Set [ socket ] = set ()
255
232
256
233
def send (self , packet : Packet ):
257
234
self .send_q .put (packet )
258
235
259
236
def recv (self , timeout = TIMEOUT ) -> Packet :
260
237
return self .recv_q .get (timeout )
261
238
262
- def _send (self , conn : socket , cache : DictQueue ):
239
+ def _send (self , conn : socket ):
263
240
conn_name = f'{ id (conn ):x} '
264
241
while not self .done .is_set ():
265
242
packet : Packet = self .send_q .get ()
266
243
try :
267
244
send_pkt (conn , packet )
268
245
except SocketError as e :
269
- logging .error (e )
270
- sys .exit (1 )
271
-
272
- logging .debug (f'[Send] conn-{ conn_name } /{ cache .cur_seq } : { packet } ' )
273
- cache .put (packet )
246
+ conn .close ()
247
+ logging .error (f'[Send] conn-{ conn_name } : { e } , conn exit.' )
248
+ return
274
249
275
- def _recv (self , conn : socket , cache : DictQueue ):
276
- n_recv = 0
250
+ def _recv (self , conn : socket ):
277
251
conn_name = f'{ id (conn ):x} '
278
252
while not self .done .is_set ():
279
253
try :
280
254
packet = recv_pkt (conn )
255
+ self .recv_q .put (packet )
256
+ logging .debug (f'[Recv] conn-{ conn_name } : { packet } ' )
281
257
except ConnectionResetError :
258
+ conn .close ()
259
+ return
260
+ except PacketError as e :
261
+ conn .close ()
262
+ logging .error (f'[Recv] conn-{ conn_name } : { e } , conn exit.' )
282
263
return
283
- except PacketError :
284
- resend_pkt = Packet .load (Flag .RESEND , n_recv )
285
- send_pkt (conn , resend_pkt )
286
- continue
287
-
288
- if packet .flag is Flag .RESEND :
289
- seq , = packet .unpack_body ()
290
- if seq not in cache :
291
- seqs = ',' .join (f'{ k } ' for k in cache .keys ())
292
- logging .error (f"{ seq } not in { seqs } " )
293
- sys .exit (1 )
294
- pkt = cache [seq ]
295
- print (f'get { seq } from { id (cache )} ' )
296
- self .send (pkt )
297
- else :
298
- logging .debug (f'[Recv] conn-{ conn_name } /{ cache .cur_seq } : { packet } ' )
299
- self .recv_q .put (packet )
300
- n_recv = (n_recv + 1 ) & MAX_SEQ
301
264
302
265
def add (self , conn : socket ):
303
266
'''添加一个连接'''
@@ -308,22 +271,31 @@ def add(self, conn: socket):
308
271
if conn in self .connections :
309
272
return True
310
273
311
- cache = DictQueue (256 )
312
- t_send = Thread (target = self ._send , args = (conn , cache ), daemon = True )
274
+ t_send = Thread (target = self ._send , args = (conn ,), daemon = True )
313
275
t_send .start ()
314
276
315
- t_recv = Thread (target = self ._recv , args = (conn , cache ), daemon = True )
277
+ t_recv = Thread (target = self ._recv , args = (conn ,), daemon = True )
316
278
t_recv .start ()
317
279
return True
318
280
281
+ def all_closed (self ):
282
+ for conn in self .connections :
283
+ if not conn .closed :
284
+ return False
285
+ return True
286
+
319
287
def stop (self ):
320
288
self .done .set ()
321
289
for conn in self .connections :
322
290
conn .close ()
323
291
324
292
def run (self ):
325
293
self .done .clear ()
326
- self .done .wait ()
294
+ while not self .done .wait (1 ):
295
+ if not self .connections :
296
+ continue
297
+ elif self .all_closed ():
298
+ break
327
299
self .stop ()
328
300
329
301
0 commit comments