• python2.0 s12 day7


    开发的第二阶段 网络编程阶段
    之所以叫网络编程,是因为,这里面就不是你在一台机器中玩了.多台机器,CS架构.即客户端和服务器端通过网络进行通信的编程了.
    首先想实现网络的通信,你得先学网络通信的一个基础,即两台机器之间是怎么打通的.有的同学说机器有IP地址,能互相ping通就连上了.
    7层网络协议,第三层:网络层,第四层,传输层(tcp/ip协议).tcp/ip协议保证了两台机器的通信的可靠的数据传输(tcp/ip协议通信的3次握手).什么叫可靠的. A给B发消息,A发了,A会知道发没发到.
    UDP不是可靠的数据传输协议,当A给B发消息,A发送出去了,A不知道B收没收到.A也不管.
    UDP依然在使用.因为它快.
    tcp/ip传输协议在发送数据前进行建立链接的3次握手.
    3次握手后,才进行真正发送数据.那么问题来了.是什么东西在负责发送数据,对方又是什么东西在进行数据接收呢.那就是socket.
    socket可以简单直白的认为它是一个管道,具体你在管道里传输什么socket不关心,如:mysql,http,这些对于socket来说就是一辆车.

    Socket 基础

    socket 通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求.
    socket起源于Unix,而Unix/Linux 基本哲学之一就是"一切皆文件",对于文件用[打开][读写][关闭]模式来操作.
    socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO打开关闭)
    socket和file的区别:
    file模块是针对某个指定文件进行[打开][读写][关闭]
    socket 模块是针对 服务器端 和 客户端socket 进行 [打开][读写][关闭]

    socket基础使用实例:
    socket_server.py
      import socket
            ip_port = ('127.0.0.1',9999)      
            sk = socket.socket()        #创建一个socket的句柄,如同open()一个文件
            sk.bind(ip_port)            #使用bind()方法,向系统内核注册一个ip,端口 作为这个socket的ip,port的属性,如果此端口没被占用,则
    返回含有ip和端口的句柄,如果被占用则报错退出程序 sk.listen(
    5)               #这个socket句柄处于监听状态。 while True:                #写一个死循环,用来接收客户端对socket的链接请求 print('server waiting ......') conn,addr = sk.accept()       
           #程序执行到accept()时,阻塞在这里,当客户端使用connect()方法,发送连接请求,accept()方法把客户端的ip也就是addr作为参数,传入sk这个socket实例设置了客户端的ip端口属性,然后把返回实例的内存地址,赋值给新的变量conn。语法就是conn,addr = 实例名.accept()。 client_data
    = conn.recv(1024)   #客户端和服务端的连接成功后,socket生成,紧接着在这里调用recv()方法,程序继续阻塞,直到客户端调用send方法,conn.recv(1024) 中的1024指的是一次最大接收1024个字节。 print(str(client_data,'utf8')) conn.send(bytes("不要回答,不要回答",'utf8')) #服务端发送即对socket套接字进行写操作。 conn.close()

    socket_clinet.py

      import socket
      ip_port = ('127.0.0.1',9999)
      sk = socket.socket()
      sk.connect(ip_port)
      
      sk.sendall(bytes("请求占领地球",'utf8'))

      server_reply = sk.recv(1024)
      print(str(server_reply,'utf8'))
      sk.close()

     基本的socket用法,很简单就实现了。那么我们深入一些:

    1.能不能让客户端和服务端进行通信呢?

    2.这是一个客户端,连接这个服务端。当多个客户端连接这个服务端会怎样?(这个测试下来,这种基本的socket是不能多个客户端访问的。)

    那么我们来尝试解决问题1.

    socket_server02.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting ......')
    
        conn,addr = sk.accept()
    
        client_data = conn.recv(1024)
        print(str(client_data,'utf8'))
        conn.send(bytes("不要回答,不要回答",'utf8'))
        while True:
            client_data = conn.recv(1024)
            print(str(client_data,'utf8'))
    
            server_response = input(">>>")
            conn.send(bytes(server_response,'utf8'))
        conn.close()

    socket_clinet02.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    sk.sendall(bytes("请求占领地球",'utf8'))
    
    server_reply = sk.recv(1024)
    print(str(server_reply,'utf8'))
    while True:
        user_input = input(">>>:").strip()
        sk.send(bytes(user_input,'utf8'))
        server_reply = sk.recv(1024)
        print(str(server_reply,'utf8'))
    sk.close()

    先执行socket_server02.py

    在执行socket_client02.py,执行结果如下:

    socket_client02.py
    不要回答,不要回答     #接到服务器的第一个响应
    >>>:dd          #客户端输入dd
    你大爷            #哟,服务端骂人
    >>>:龟孙            #骂回去
    日你先人          #服务器又骂回来一句
    >>>:
    
    socket_server02.py
    server waiting ......
    请求占领地球   #接到的第一个clinet send
    dd        #服务端收到dd
    >>>你大爷     #服务端回复,d d看不懂,就说了句“你大爷”
    龟孙        #乖乖,敢回嘴,我可是服务器
    >>>日你先人    #接着骂

     那么我这上面都是正常通信,输入的字符串都是正常的,假如客户端不输入了,直接退出。会怎样?

    这里就不赘述老师的试验过程了,最终结果,老师说当clinet客户端停掉,windows和Linux的服务端对这个异常处理的方式不一样

    但我自己在mac和Linux下尝试的结果一样,判断接收到clinet_data数据是否为空,为空就跳出循环。

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting ......')
    
        conn,addr = sk.accept()
    
        client_data = conn.recv(1024)
        print(str(client_data,'utf8'))
        conn.send(bytes("不要回答,不要回答",'utf8'))
        while True:
    
                client_data = conn.recv(1024)
                if not client_data:break   #判断当,对方传过来的值为空时,直接退出
                print('client_data',str(client_data,'utf8'))
    
                server_response = input(">>>")
                conn.send(bytes(server_response,'utf8'))
    
    
        conn.close()

    windows下,当客户端停掉,server端 conn.recv(1024)得到的数据不是空值,而是异常,异常发生后,程序就会退出,所以这里就要用到异常处理方法try语法,具体代码如下:这段代码如果用到Linux中,将无限循环下去,因为客户端停掉后,服务端会认为conn.recv(1024)得到空值,这样无限循环下去。

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)

    while True:
    print('server waiting ......')

    conn,addr = sk.accept()

    client_data = conn.recv(1024)
    print(str(client_data,'utf8'))
    conn.send(bytes("不要回答,不要回答",'utf8'))
    while True:
    try:
    client_data = conn.recv(1024)
    print('client_data',str(client_data,'utf8'))
    except Exception:
    print("clinet closed,break")
    break
    server_response = input(">>>")
    conn.send(bytes(server_response,'utf8'))

    conn.close()

     使用socket写一个远程的ssh工具:

    04socket_server.py代码如下:

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习,做成可以远程输入命令,客户端获得输出结果,如果你的命令输出结果很多,那么客户端得到的结
    '''
    import socket
    import subprocess
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting ......')
    
        conn,addr = sk.accept()
    
        # client_data = conn.recv(1024)
        # print(str(client_data,'utf8'))
        # conn.send(bytes("不要回答,不要回答",'utf8'))
        while True:
                print("客户端{}已经连接,等待客户端传输命令... ...".format(conn.getpeername()))
                client_cmd_re = conn.recv(1024)
                if not client_cmd_re:break   # 判断当,对方传过来的值为空时,直接退出(在客户端我已经判断用户输入不能为空,所以这里为空,只有一种可能,就是客户端关闭程序了.如果没有这句的break,会导致客户端一旦关闭,服务端也跟着关闭.
                # 因为当客户端关闭后,传过来的不知道是什么东西)
                print("用户传来了命令:%s"%client_cmd_re)   # 打印输出用户传来的命令
                cmd_re_str = str(client_cmd_re,'utf8') # 将用户传来的命令转换成str
    
                # 将命令执行,并获得执行结果
                cmd_exec_result = subprocess.Popen(cmd_re_str,shell=True,stdout=subprocess.PIPE).stdout.read()
                # print(cmd_exec_result)    # 打印执行的结果
                # print(len(cmd_exec_result)) # 打印结果的长度
                if  len(cmd_exec_result) == 0 :    #   判断结果是不是为空,为空说明用户传过来的命令,本服务器无法执行.
                    cmd_exec_result = bytes("命令 '{}' 后没有返回执行结果,请检查命令是否正确...".format(cmd_re_str),'utf8')    #  提示命令不对
                #将执行结果发送给客户端
                conn.send(cmd_exec_result)
        conn.close()

    04socket_client.py代码如下:

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    # sk.sendall(bytes("请求占领地球",'utf8'))
    #
    # server_reply = sk.recv(1024)
    # print(str(server_reply,'utf8'))
    while True:
        input_cmd = input("cmd:").strip()               # 用户输入命令
        if input_cmd == 'q':break                       # 用户如果输入的是q,退出输入命令的循环
        if not input_cmd:continue                       # 用户如果直接按了回车,既为空,则进行下次循环
        print(input_cmd)                                 # 打印此次用户输入的命令
        sk.send(bytes(input_cmd,'utf8'))                 # 将用户的命令通过socket发送给服务器端
        cmd_exec_data = sk.recv(1024)                    # 接收服务器执行命令后返回的结果
        print(str(cmd_exec_data,'utf8'))
    sk.close()

     上面的代码已经实现了,client连接到server后,进行基本的简单的命令。却不能进行实时的交互,比如top,cd 这种执行后没法返回的命令。具体如何时间,第七天的课程暂不说明。

    那么问题来了,client端在接收设置中用到了sk.recv(1024),设置了每次最大收1024个字节,当你执行一个ifconfig命令,字节将大于1024,客户端就会一次收不完,这些数据,会怎样。这些数据已经被服务端通过socket发送过来了。你再次调用sk.recv(1024)时,继续接收余下的数据。那么怎样才能继续接收呢?目前的代码是循环到下次输入命令时会接收ifconfig命令结果的后续。那它这次的命令就又要排队到后面了。

    那么如何进行循环接收呢?当然是在本次执行命令中,在sk.recv(1024)代码前加while 循环。

    问题又来了。默认是死循环,while True,那么本次命令循环接收sk.recv(1024)结束条件怎么设置呢。

    先说明:这里处理方法只有一种,就是在服务端传给客户端字符串前,先把传输的字节数告诉客户端。客户端循环接收字节,并把接收到的字节数累加统计,然后拿接收到的字节总数和服务端发来的做比较。如果小于继续循环。

    但是: 老师给我们理清了思路,尝试了3种测试的方法,通过这3次尝试,让我们渐渐的了解socket传输的内部原理。

    尝试方案1:

      客户端在接收调用sk.recv(1024)方法,我们可以尝试调大这个数值,看看结果。是可以,每次多收一些,但是,如果你一个字符串有100*1024bytes,你不能把接收数值调整到100M吧,那内存还不爆掉。并且socket官方建议最大不能超过8192,所以此方案不可行。并且一般设置500即可。

    尝试方案2:

       我们在接收哪里直接while True,一直接收,直到接收不到数据时就退出break

      06socket_server.py 不需要改动

      06socket_client.py 代码如下:

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    当服务端发送过来的字符串字节数过大,一次接收不完,客户端通过判断服务器端是不是发送完,来作为循环接收的依据。
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    # sk.sendall(bytes("请求占领地球",'utf8'))
    #
    # server_reply = sk.recv(1024)
    # print(str(server_reply,'utf8'))
    while True:
        input_cmd = input("cmd:").strip()               # 用户输入命令
        if input_cmd == 'q':break                       # 用户如果输入的是q,退出输入命令的循环
        if not input_cmd:continue                       # 用户如果直接按了回车,既为空,则进行下次循环
        print(input_cmd)                                 # 打印此次用户输入的命令
        sk.send(bytes(input_cmd,'utf8'))                 # 将用户的命令通过socket发送给服务器端
    
        res = bytes('','utf8')
        while True:
            cmd_exec_data = sk.recv(500)                    # 接收服务器执行命令后返回的结果
            res += cmd_exec_data
            if not cmd_exec_data :            #这里判断,当接收不到数据时,就退出循环
                break
        print(str(res,'utf8'))
    sk.close()

    ps:此方式不可行。原因是cmd_exec_data = sk.recv(500) 这里在接收完本次命令执行的所有结果后,会一直阻塞在这里。不会退出循环,此时客户端就卡死了。

    总结:sk.recv()和sk.send()都会阻塞

    尝试方案3:

      在客户端判断服务端的数据是不是传完了,如果没传完,则继续循环接收。

      05scoket_server.py 不需要改动

      05socket_client.py 代码如下:

      

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    当服务端发送过来的字符串字节数过大,一次接收不完,客户端通过判断服务器端是不是发送完,来作为循环接收的依据.
    如何判断服务器端是不是发送完成?
    我们认为,客户端每次接收的最大值500字节.那么如果最后一次传过来的数据长度没有500字节,那么我们是不是就可以说这次就是最后一次传输来.
    所以while 循环中判断接收到的数据长度小于500,就退出循环接收.
    代码如下:
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    # sk.sendall(bytes("请求占领地球",'utf8'))
    #
    # server_reply = sk.recv(1024)
    # print(str(server_reply,'utf8'))
    while True:
        input_cmd = input("cmd:").strip()               # 用户输入命令
        if input_cmd == 'q':break                       # 用户如果输入的是q,退出输入命令的循环
        if not input_cmd:continue                       # 用户如果直接按了回车,既为空,则进行下次循环
        print(input_cmd)                                 # 打印此次用户输入的命令
        sk.send(bytes(input_cmd,'utf8'))                 # 将用户的命令通过socket发送给服务器端
    
        res = bytes('','utf8')
        while True:
            cmd_exec_data = sk.recv(500)                    # 接收服务器执行命令后返回的结果
            res += cmd_exec_data
            if len(cmd_exec_data) < 500:            #当接收到的字节小于500就判断已经接收完了。
                break
        print(str(res,'utf8'))
    sk.close()

    这里我们执行命令,得到一些数据量还没有那么大的字符串时没有问题,担当字符串相当大时,就出现之前的那种错误了,原因是我们最初认为的客户端每次都是按最大500字节接收(这个观点错了)。两个因素导致单次接收可能没有500字节。

      因素1,服务端发送会因为网络状态发送数据。如果网络不稳定,传个10几个bytes也是可能的。

      因素2,客户端接收也可能因为网络或者性能,导致这次接收延迟了几百毫秒(内部缓冲机制时间限制也许只有100毫秒)。从而导致本次接收不到500字节。

    总结:客户端不是每次接收都是按照最大限额的字节接收的。这样我们的代码:

        while True:
            cmd_exec_data = sk.recv(500)                    # 接收服务器执行命令后返回的结果
            res += cmd_exec_data
            if len(cmd_exec_data) < 500:        #这里就会在没接收完时,就退出了本次命令执行结果接收呢。
                break

    最终答案来了,代码如下:

    07socket_server.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习,做成可以远程输入命令,客户端获得输出结果,如果你的命令输出结果很多,那么客户端得到的结
    '''
    import socket
    import subprocess
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting ......')
    
        conn,addr = sk.accept()
    
        # client_data = conn.recv(1024)
        # print(str(client_data,'utf8'))
        # conn.send(bytes("不要回答,不要回答",'utf8'))
        while True:
                print("客户端{}已经连接,等待客户端传输命令... ...".format(conn.getpeername()))
                client_cmd_re = conn.recv(1024)
                if not client_cmd_re:break   # 判断当,对方传过来的值为空时,直接退出(在客户端我已经判断用户输入不能为空,所以这里为空,只有一种可能,就是客户端关闭程序了.如果没有这句的break,会导致客户端一旦关闭,服务端也跟着关闭.
                # 因为当客户端关闭后,传过来的不知道是什么东西)
                print("用户传来了命令:%s"%client_cmd_re)   # 打印输出用户传来的命令
                cmd_re_str = str(client_cmd_re,'utf8') # 将用户传来的命令转换成str
    
                # 将命令执行,并获得执行结果
                cmd_exec_result = subprocess.Popen(cmd_re_str,shell=True,stdout=subprocess.PIPE).stdout.read()
                if  len(cmd_exec_result) == 0 :    #   判断结果是不是为空,为空说明用户传过来的命令,本服务器无法执行.
                    cmd_exec_result = bytes("命令 '{}' 后没有返回执行结果,请检查命令是否正确...".format(cmd_re_str),'utf8')    #  提示命令不对
                
                
                result_size = len(cmd_exec_result) # 计算本次获得到结果是多少字节
                conn.send(bytes("CMD_RESULT_SIZE|{}".format(result_size),'utf8')) # 首先将本次将要发送的字符串的大小告诉客户端.
    
                conn.send(cmd_exec_result)   #紧接着把执行结果发过去
        conn.close()

    07socket_client.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    当服务端发送过来的字符串字节数过大,一次接收不完,客户端通过判断服务器端是不是发送完,来作为循环接收的依据.
    如何判断服务器端是不是发送完成?
    根据服务器端发来的大小,判断是否接收完成.
    代码如下:
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    # sk.sendall(bytes("请求占领地球",'utf8'))
    #
    # server_reply = sk.recv(1024)
    # print(str(server_reply,'utf8'))
    while True:
        input_cmd = input("cmd:").strip()               # 用户输入命令
        if input_cmd == 'q':break                       # 用户如果输入的是q,退出输入命令的循环
        if not input_cmd:continue                       # 用户如果直接按了回车,既为空,则进行下次循环
        print(input_cmd)                                 # 打印此次用户输入的命令
        sk.send(bytes(input_cmd,'utf8'))                 # 将用户的命令通过socket发送给服务器端
    
        server_ack_msg = sk.recv(100)
        cmd_res_msg = str(server_ack_msg,'utf8').split('|')
        # "CMD_RESULT_SIZE|{}".format(result_size),'utf8')
        # print(cmd_res_msg)
    
        if cmd_res_msg[0] == "CMD_RESULT_SIZE": # 判断你发来的这个是不是文件大小的标示
            cmd_res_size = int(cmd_res_msg[1])  #如果是,把大小付给cmd_res_size变量
    
        res = bytes('','utf8')
        recevied_size = 0                   # 初始化字符串大小为0
        while recevied_size < cmd_res_size: # 如果已接收的字符串大小小于服务器传过来的大小,则循环接收
            data = sk.recv(50)              # 接收数据
            recevied_size += len(data)      # 将数据累加
            res += data                     # 累加统计已接收的数据
        print(str(res,'utf8'))              # 打印最终结果
    sk.close()

    到此为止,我们认为,socket接收大数据的功能已经实现。大功告成~~~,no,还有错误,当数据量大时,会出现 “socket编程中最大的一个坑 粘包 ”

    我们看07socket_server.py中最后发送的代码

                conn.send(bytes("CMD_RESULT_SIZE|{}".format(result_size),'utf8')) # 首先将本次将要发送的字符串的大小告诉客户端. 
                                
                conn.send(cmd_exec_result)

    我们看到一连两次发送。这就会出现“socket编程中最大的一个坑 粘包 ”,原因是缓冲区的问题,你两次发送,缓冲区会把两次要发送的内容放到一起发送。

    那么怎么解决呢?

    两个方案:

      1.在两次发送之间sleep(1) 间隔1秒,这样缓冲区就失效。但是这种方式low,如果并发大就会很慢。

      2.发送完文件大小后,使用conn.recv(100)这个能阻塞的方法,获取客户端返回来已经接收到文件大小信息的确认信息。(当然客户端也要加返回给服务端的确认信息。)

    最终代码如下:

    08socket_server.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    socket学习,做成可以远程输入命令,客户端获得输出结果,如果你的命令输出结果很多,那么客户端得到的结
    '''
    import socket
    import subprocess
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.bind(ip_port)
    sk.listen(5)
    
    while True:
        print('server waiting ......')
    
        conn,addr = sk.accept()
    
        # client_data = conn.recv(1024)
        # print(str(client_data,'utf8'))
        # conn.send(bytes("不要回答,不要回答",'utf8'))
        while True:
                print("客户端{}已经连接,等待客户端传输命令... ...".format(conn.getpeername()))
                client_cmd_re = conn.recv(1024)
                if not client_cmd_re:break   # 判断当,对方传过来的值为空时,直接退出(在客户端我已经判断用户输入不能为空,所以这里为空,只有一种可能,就是客户端关闭程序了.如果没有这句的break,会导致客户端一旦关闭,服务端也跟着关闭.
                # 因为当客户端关闭后,传过来的不知道是什么东西)
                print("用户传来了命令:%s"%client_cmd_re)   # 打印输出用户传来的命令
                cmd_re_str = str(client_cmd_re,'utf8') # 将用户传来的命令转换成str
    
                # 将命令执行,并获得执行结果
                cmd_exec_result = subprocess.Popen(cmd_re_str,shell=True,stdout=subprocess.PIPE).stdout.read()
                if  len(cmd_exec_result) == 0 :    #   判断结果是不是为空,为空说明用户传过来的命令,本服务器无法执行.
                    cmd_exec_result = bytes("命令 '{}' 后没有返回执行结果,请检查命令是否正确...".format(cmd_re_str),'utf8')    #  提示命令不对
    
    
                result_size = len(cmd_exec_result) # 计算本次获得到结果是多少字节
                conn.send(bytes("CMD_RESULT_SIZE|{}".format(result_size),'utf8')) # 首先将本次将要发送的字符串的大小告诉客户端.
                client_ack = conn.recv(50)
                if str(client_ack,'utf8') == "CLIENT_READY_TO_RECV":
                    conn.send(cmd_exec_result)
        conn.close()

    08socket_client.py

    #!/usr/bin/env python3.5
    #__author__:'ted.zhou'
    '''
    当服务端发送过来的字符串字节数过大,一次接收不完,客户端通过判断服务器端是不是发送完,来作为循环接收的依据.
    如何判断服务器端是不是发送完成?
    根据服务器端发来的大小,判断是否接收完成.
    代码如下:
    '''
    import socket
    ip_port = ('127.0.0.1',9999)
    sk = socket.socket()
    sk.connect(ip_port)
    
    # sk.sendall(bytes("请求占领地球",'utf8'))
    #
    # server_reply = sk.recv(1024)
    # print(str(server_reply,'utf8'))
    while True:
        input_cmd = input("cmd:").strip()               # 用户输入命令
        if input_cmd == 'q':break                       # 用户如果输入的是q,退出输入命令的循环
        if not input_cmd:continue                       # 用户如果直接按了回车,既为空,则进行下次循环
        print(input_cmd)                                 # 打印此次用户输入的命令
        sk.send(bytes(input_cmd,'utf8'))                 # 将用户的命令通过socket发送给服务器端
    
        server_ack_msg = sk.recv(100)
        cmd_res_msg = str(server_ack_msg,'utf8').split('|')
        # "CMD_RESULT_SIZE|{}".format(result_size),'utf8')
        # print(cmd_res_msg)
    
        if cmd_res_msg[0] == "CMD_RESULT_SIZE": # 判断你发来的这个是不是文件大小的标示
            cmd_res_size = int(cmd_res_msg[1])  #如果是,把大小付给cmd_res_size变量
            sk.send(b"CLIENT_READY_TO_RECV")
    
        res = bytes('','utf8')
        recevied_size = 0                   # 初始化字符串大小为0
        while recevied_size < cmd_res_size: # 如果已接收的字符串大小小于服务器传过来的大小,则循环接收
            data = sk.recv(50)              # 接收数据
            recevied_size += len(data)      # 将数据累加
            res += data                     # 累加统计已接收的数据
        print(str(res,'utf8'))              # 打印最终结果
    sk.close()
  • 相关阅读:
    Windows SDK编程(Delphi版) 之 应用基础,楔子
    一个小问题引发的论证思考
    Delphi 组件开发教程指南(7)继续模拟动画显示控件
    用PyInstaller将python转成可执行文件exe笔记
    使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践)
    Microsof Office SharePoint 2007 工作流开发环境搭建
    How to monitor Web server performance by using counter logs in System Monitor in IIS
    LINQ之Order By
    window 性能监视器
    内存泄露检测工具
  • 原文地址:https://www.cnblogs.com/zhming26/p/5527202.html
Copyright © 2020-2023  润新知