• python----网络编程(TCP通讯)


    python----网络编程(TCP通讯)

    笔者在学习Python核心编程(第三版)这本书籍的时候

    在章节网络编程 2.4.1----TCP服务端和客户端里面

    尝试按照书籍编写TCP服务端和客户端的程序

    书籍例子如下

    TCP服务端

    #coding=utf-8
    #创建TCP服务器
    from socket import *
    from time import ctime
    
    HOST=''
    PORT=21567
    BUFSIZ=1024
    ADDR=(HOST,PORT)
    
    tcpSerSock=socket(AF_INET,SOCK_STREAM) #创服务器套接字
    tcpSerSock.bind(ADDR) #套接字与地址绑定
    tcpSerSock.listen(5)  #监听连接,传入连接请求的最大数
    
    while True:
        print('waiting for connection...')
        tcpCliSock,addr =tcpSerSock.accept()
        print('...connected from:',addr)
    
        while True:
            data =tcpCliSock.recv(BUFSIZ)
            #print('date=',data)
            if not data:
                break
            tcpCliSock.send(('[%s] %s' %(ctime(),data)))
    
        tcpCliSock.close()
    tcpSerSock.close()

    TCP客户端

    #coding=utf-8
    
    from socket import *
    
    HOST = 'localhost' #  or 'localhost'
    PORT = 21567
    BUFSIZ = 1024
    ADDR=(HOST,PORT)
    
    tcpCliSock = socket(AF_INET,SOCK_STREAM)
    tcpCliSock.connect(ADDR)
    
    while True:
        data = input('> ')
        print('data=',data);
        if not data:
            break
        tcpCliSock.send(data)
        data = tcpCliSock.recv(BUFSIZ)
        if not data:
            break
        print(data)
    
    tcpCliSock.close() 

    在启动服务端后,再启动客户端去连接服务器,输入信息,在服务器会返回报错:

    TypeError: a bytes-like object is required, not ‘str’ 

    笔者纠结了很久,在百度上搜索了相关的文章,看到了作者“MrYx”的一篇文章

    https://blog.csdn.net/yexiaohhjk/article/details/68066843

    里面有说道

    In python 3, bytes strings and unicode strings are now two different types. Since sockets are not aware of string encodings, they are using raw bytes strings, that have a slightly different interface from unicode strings.

    So, now, whenever you have a unicode string that you need to use as a byte string, you need to encode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.

    Unicode strings are quotes enclosed strings. Bytes strings are b”” enclosed strings

    When you use client_socket.send(data),replace it by client_socket.send(data.encode()). When you get datausing data = client_socket.recv(512), replace it by data =client_socket.recv(512).decode()


    这里大致的意思就是,Pyhon3之后,bytes strings 和 unicode strings 是两种不同的字符类型。如果想要将unicode strings变成bytes strings,我们需要用encode()这种方式去对其进行转码。反之,我们则需要用到decode()。而在书籍的例子里面,在关于变量data,并没有考虑到这点。我们从socket里面接受或者发送的数据,应该是bytes类型的,但是我们在程序里面编辑的时候,需要的字符类型是unicode的,因此,我们需要对书籍的例子作出修改。

    修改如下

    TCP服务端

    #!/usr/bin/python3
    #-*- coding -*-
    
    from socket import *
    from time import ctime
    
    HOST = ''
    PORT = 21571
    BUFSIZ = 1024
    ADDR = (HOST,PORT)
    
    tcpSerSock = socket(AF_INET,SOCK_STREAM)
    tcpSerSock.bind(ADDR)
    tcpSerSock.listen(5)
    
    while True:
        print ('waiting for connection')
        tcpCliSock ,addr = tcpSerSock.accept()
        print ('...connected from:',addr)
    
        while True:
            data = tcpCliSock.recv(BUFSIZ).decode()
            if not data:
                break
            tcpCliSock.send(('[%s] %s' %(ctime(),data)).encode())
    
        tcpCliSock.close()
    tcpCliSock.close()

    TCP客户端

    #!/usr/bin/python3
    #-*- coding -*-
    
    from  socket import *
    
    HOST = '127.0.0.1'
    PORT = 21571
    BUFSIZ = 1024
    ADDR = (HOST,PORT)
    
    tcpCliSock = socket(AF_INET, SOCK_STREAM)
    tcpCliSock.connect(ADDR)
    
    while True:
        data = input('> ')
        if not data:
            break
        tcpCliSock.send(data.encode())
        data = tcpCliSock.recv(BUFSIZ).decode()
        if not data:
            break
        print (data)
    
    tcpCliSock.close()

    twisted:

    服务端

    #!/usr/bin/python3
    #-*- coding -*-
    
    from twisted.internet import protocol,reactor
    from time import ctime
    
    PORT = 21500
    
    class TSServProtocol(protocol.Protocol):
        def connectionMade(self):
            clnt = self.clnt = self.transport.getPeer().host
            print('...connected from:',clnt)
        def dataReceived(self, data):
            self.transport.write(('[%s] %s'%(ctime(),data)).encode())
    
    factory = protocol.Factory()
    factory.protocol = TSServProtocol
    print('waiting for connection...')
    reactor.listenTCP(PORT,factory)
    reactor.run()

    客户端

    #!/usr/bin/python3
    #-*- coding -*-
    
    from twisted.internet import protocol,reactor
    
    HOST = 'localhost'
    PORT = 21500
    
    class TSClntProtocol(protocol.Protocol):
        def sendData(self):
            data = input('> ')
            if data:
                print('...sending %s...'% data)
                self.transport.write(data.encode())
            else:
                self.transport.loseConnection()
    
        def connectionMade(self):
            self.sendData()
    
        def dataReceived(self, data):
            self.sendData()
    
    class TSClntFactory(protocol.ClientFactory):
        protocol = TSClntProtocol
        clientConnectionLost = clientConnentionFailed = 
            lambda self,connector,reason:reactor.stop()
    
    reactor.connectTCP(HOST,PORT,TSClntFactory())
    reactor.run()

    本文参考

    https://blog.csdn.net/yexiaohhjk/article/details/68066843

  • 相关阅读:
    P2351 [SDOI2012]吊灯
    洛谷P1450 [HAOI2008]硬币购物 背包+容斥
    P5110 块速递推-光速幂、斐波那契数列通项
    AT2304 Cleaning
    CSP-S 2020
    CF487E Tourists
    P4334 [COI2007] Policija
    动态逆序对专练
    CF437D The Child and Zoo
    CF1032G Chattering
  • 原文地址:https://www.cnblogs.com/QicongLiang/p/10096969.html
Copyright © 2020-2023  润新知