尝试TCP连接时,while()中的奇怪print()输出

时间:2016-03-20 14:16:46

标签: python python-3.x tcp

问题是:print() client()只输出一行,而我希望它打印几行,因为它所驻留的while循环显然运行了多次。

当我测试 Python网络编程基础,第3版 一书中给出的示例代码时,会出现问题。此示例代码基本上创建了一个简单的TCP服务器/客户端,用于处理/发送简单的文本大写请求。以下是代码:

#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter03/tcp_deadlock.py
# TCP client and server that leave too much data waiting
import argparse, socket, sys

def server(host, port, bytecount):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind((host, port))
    sock.listen(1)
    print('Listening at', sock.getsockname())
    while True:
        sc, sockname = sock.accept()
        print('Processing up to 1024 bytes at a time from', sockname)
        n = 0
        while True:
            data = sc.recv(1024)
            if not data:
                break
            output = data.decode('ascii').upper().encode('ascii')
            sc.sendall(output) # send it back uppercase
            n += len(data)
            print('\r %d bytes processed so far' % (n,), end=' ')
            sys.stdout.flush()
        print()
        sc.close()
        print('  Socket closed')

def client(host, port, bytecount):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    bytecount = (bytecount + 15) // 15 * 16 # round up to a multiple of 16
    message = b'CAP!' # 16-byte message to repeat over and over

    print('Sending', bytecount, 'bytes of data, in chunks of 16 bytes')
    sock.connect((host, port))
    sent = 0
    while sent < bytecount:
        sock.sendall(message)
        sent += len(message)
        # print('test')
        print('\r %d bytes sent' %(sent,), end=' ') # <-- THIS IS THE PROBLEMATIC PRINT()
        sys.stdout.flush()

    print()
    sock.shutdown(socket.SHUT_WR)

    print('Receiving all the data the server sends back')

    received = 0
    while True:
        data = sock.recv(42)
        if not received:
            print('  The first data received says', repr(data))
        if not data:
            break
        received += len(data)
        print('\r %d bytes received' %(received,), end=' ')

    print()
    sock.close()

if __name__ == '__main__':
    choices = {'client': client, 'server': server}
    parser = argparse.ArgumentParser(description='Get deadlocked over TCP')
    parser.add_argument('role', choices=choices, help='which role to play')
    parser.add_argument('host', help='interface the server listens at;'
                        ' host the client sends to')
    parser.add_argument('bytecount', type=int, nargs='?', default=16,
                        help='number of bytes for client to send (default 16)')
    parser.add_argument('-p', metavar='PORT', type=int, default=1060,
                        help='TCP port (default 1060)')
    args = parser.parse_args()
    function = choices[args.role]
    function(args.host, args.p, args.bytecount)

在我本地创建服务器之后,我用

启动了我的客户端
  

python listing3-2.py client 0.0.0.0

这是我得到的输出:

  

发送32个字节的数据,以16个字节的块为单位   发送了32个字节

     

接收服务器发回的所有数据收到的第一个数据   b&#39; CAP!CAP!CAP!CAP!CAP!CAP!CAP!CAP!&#39;收到32个字节

从此输出中我们知道while()循环已运行8次(因为8&#39; CAP!&#39; s)但print('\r %d bytes sent' %(sent,), end=' ')仅运行一次。对我来说更奇怪的是sys.stdout.flush()无法工作,尽管作者可能也注意到了这个问题。

当我在有问题的print('test')之前尝试添加一行print()时会发生更奇怪的事情,看看会发生什么?

  

python listing3-2.py client 0.0.0.0

     

发送32个字节的数据,以16字节的块为单位进行测试   4个字节发送测试   8个字节发送测试
  12个字节发送测试
  16个字节发送测试
  20个字节发送测试
  24字节发送测试   28个字节发送测试
  发送了32个字节   接收服务器发回的所有数据收到的第一个数据说   B&#39;!!!!!!!!CAP CAP CAP CAP CAP CAP CAP CAP&#39;收到32个字节

在之前有一个额外的print()print('\r %d bytes sent' %(sent,), end=' ')运行8次,尽管循环结构完全没有变化。我完全感到困惑的是,添加print()会带来这样的后果。而且,如果在这种情况下使用print()方法可能会有一些奇怪的特征,我也会感到困惑。

1 个答案:

答案 0 :(得分:1)

打印邮件中的\rend=' '相结合。这是一个没有换行的回车,所以所有的线都相互打印。额外的print添加换行符,它们会停止相互打印。将其更改为\n以进行修复,或更简单地说:

print(sent,'bytes sent')

P.S。还有一个数学错误:

bytecount = (bytecount + 15) // 15 * 16

应该是:

bytecount = (bytecount + 15) // 16 * 16