@@ -495,21 +495,9 @@ def recv(
495
495
496
496
:return bytes: Data from the socket.
497
497
"""
498
- stamp = time .monotonic ()
499
- while not self ._available ():
500
- if self ._timeout and 0 < self ._timeout < time .monotonic () - stamp :
501
- break
502
- time .sleep (0.05 )
503
- bytes_on_socket = self ._available ()
504
- if not bytes_on_socket :
505
- return b""
506
- bytes_to_read = min (bytes_on_socket , bufsize )
507
- if self ._sock_type == SOCK_STREAM :
508
- bytes_read = _the_interface .socket_read (self ._socknum , bytes_to_read )[1 ]
509
- else :
510
- bytes_read = _the_interface .read_udp (self ._socknum , bytes_to_read )[1 ]
511
- gc .collect ()
512
- return bytes (bytes_read )
498
+ buf = bytearray (bufsize )
499
+ self .recv_into (buf , bufsize )
500
+ return bytes (buf )
513
501
514
502
def _embed_recv (
515
503
self , bufsize : int = 0 , flags : int = 0
@@ -568,12 +556,42 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int:
568
556
569
557
:return int: the number of bytes received
570
558
"""
571
- if nbytes == 0 :
572
- nbytes = len (buffer )
573
- bytes_received = self .recv (nbytes )
574
- nbytes = len (bytes_received )
575
- buffer [:nbytes ] = bytes_received
576
- return nbytes
559
+ if not 0 <= nbytes <= len (buffer ):
560
+ raise ValueError ("nbytes must be 0 to len(buffer)" )
561
+
562
+ last_read_time = time .monotonic ()
563
+ num_to_read = len (buffer ) if nbytes == 0 else nbytes
564
+ num_read = 0
565
+ while num_to_read > 0 :
566
+ # we might have read socket data into the self._buffer with:
567
+ # _readline
568
+ if len (self ._buffer ) > 0 :
569
+ bytes_to_read = min (num_to_read , len (self ._buffer ))
570
+ buffer [num_read : num_read + bytes_to_read ] = self ._buffer [:bytes_to_read ]
571
+ num_read += bytes_to_read
572
+ num_to_read -= bytes_to_read
573
+ self ._buffer = self ._buffer [bytes_to_read :]
574
+ # explicitly recheck num_to_read to avoid extra checks
575
+ continue
576
+
577
+ num_avail = self ._available ()
578
+ if num_avail > 0 :
579
+ last_read_time = time .monotonic ()
580
+ bytes_to_read = min (num_to_read , num_avail )
581
+ if self ._sock_type == SOCK_STREAM :
582
+ bytes_read = _the_interface .socket_read (self ._socknum , bytes_to_read )[1 ]
583
+ else :
584
+ bytes_read = _the_interface .read_udp (self ._socknum , bytes_to_read )[1 ]
585
+ buffer [num_read : num_read + len (bytes_read )] = bytes_read
586
+ num_read += len (bytes_read )
587
+ num_to_read -= len (bytes_read )
588
+ elif num_read > 0 :
589
+ # We got a message, but there are no more bytes to read, so we can stop.
590
+ break
591
+ # No bytes yet, or more bytes requested.
592
+ if self ._timeout > 0 and time .monotonic () - last_read_time > self ._timeout :
593
+ raise timeout ("timed out" )
594
+ return num_read
577
595
578
596
@_check_socket_closed
579
597
def recvfrom_into (
@@ -730,3 +748,11 @@ def type(self):
730
748
def proto (self ):
731
749
"""Socket protocol (always 0x00 in this implementation)."""
732
750
return 0
751
+
752
+
753
+ class timeout (TimeoutError ):
754
+ """TimeoutError class. An instance of this error will be raised by recv_into() if
755
+ the timeout has elapsed and we haven't received any data yet."""
756
+
757
+ def __init__ (self , msg ):
758
+ super ().__init__ (msg )
0 commit comments