Python 3.4,TypeError用于套接字问题

时间:2015-08-12 09:54:19

标签: python sockets python-3.x

我不太了解python中的编码/解码。 我已经尝试了很多,并在这里寻找类似但我找不到一些。 这是有问题的代码:

import sys
import socket
import threading
import time

QUIT = False


class ClientThread(threading.Thread):  # Class that implements the client threads in this server
    def __init__(self, client_sock):  # Initialize the object, save the socket that this thread will use.
        threading.Thread.__init__(self)
        self.client = client_sock

    def run(self):  # Thread's main loop. Once this function returns, the thread is finished and dies.
        global QUIT  # Need to declare QUIT as global, since the method can change it
        done = False
        cmd = self.readline()  # Read data from the socket and process it
        while not done:
            if b'quit' == cmd:
                self.writeline('Ok, bye')
                QUIT = True
                done = True
            elif b'bye' == cmd:
                self.writeline('Ok, bye')
                done = True
            else:
                self.writeline(self.name).encode('utf-8')
                cmd = self.readline()

            self.client.close()  # Make sure socket is closed when we're done with it
            return

    def readline(self):  # Helper function, read up to 1024 chars from the socket, and returns them as a string
        result = self.client.recv(1024)
        if None != result:  # All letters in lower case and without and end of line markers
            result = result.strip().lower()
        return result

    def writeline(self, text):  # Helper func, writes the given string to the socket with and end of line marker at end
        self.client.send(bytes(text.strip() + '\n'))

在这种情况下,我得到:

TypeError: string argument without an enconding.

这就行了:

self.writeline('ok bye')

还有一行:

self.client.send(bytes(text.strip() + '\n'))  

删除字节部分会给我另一个错误:

TypeError: 'str' does not support the buffer interface  

并且还引用了上面的两行。 我在没有任何帮助的情况下尝试了encode(utf-8)的组合 我想我在这里误解了什么是错误的。我知道需要发送bytes,但是当我这样做时,它会产生连锁错误。被困在一个恶劣的循环中 非常感谢任何澄清,谢谢!

这是完整的代码,其中包含了迄今为止社区帮助中添加的内容:

import sys
import socket
import threading
import time

QUIT = False


class ClientThread(threading.Thread):  # Class that implements the client threads in this server
    def __init__(self, client_sock):  # Initialize the object, save the socket that this thread will use.
        threading.Thread.__init__(self)
        self.client = client_sock

    def run(self):  # Thread's main loop. Once this function returns, the thread is finished and dies.
        global QUIT  # Need to declare QUIT as global, since the method can change it
        done = False
        cmd = self.readline()  # Read data from the socket and process it
        while not done:
            if b'quit' == cmd:
                self.writeline('Ok, bye'.encode('utf-8'))
                QUIT = True
                done = True
            elif b'bye' == cmd:
                self.writeline('Ok, bye')
                done = True
            else:
                self.writeline(str(self.name).encode('utf-8'))
                cmd = self.readline()

            self.client.close()  # Make sure socket is closed when we're done with it
            return

    def readline(self):  # Helper function, read up to 1024 chars from the socket, and returns them as a string
        result = self.client.recv(1024)
        if None != result:  # All letters in lower case and without and end of line markers
            result = result.strip().lower()
        return result

    def writeline(self, text):  # Helper func, writes the given string to the socket with and end of line marker at end
        self.client.send((text.strip() + '\n').encode("utf-8"))


class Server:  # Server class. Opens up a socket and listens for incoming connections.
    def __init__(self):  # Every time a new connection arrives, new thread object is created and
        self.sock = None  # defers the processing of the connection to it
        self.thread_list = []

    def run(self):  # Server main loop: Creates the server (incoming) socket, listens > creates thread to handle it
        all_good = False
        try_count = 0  # Attempt to open the socket
        while not all_good:
            if 3 < try_count:  # Tried more than 3 times without success, maybe post is in use by another program
                sys.exit(1)
            try:
                self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # Create the socket
                port = 80
                self.sock.bind(('127.0.0.1', port))  # Bind to the interface and port we want to listen on
                self.sock.listen(5)
                all_good = True
                break
            except socket.error:
                print('Socket connection error... Waiting 10 seconds to retry.')
                del self.sock
                time.sleep(10)
                try_count += 1

        print('Server is listening for incoming connections.')
        print('Try to connect through the command line with:')
        print('telnet localhost 80')
        print('and then type whatever you want.')
        print()
        print("typing 'bye' finishes the thread. but not the server",)
        print("eg. you can quit telnet, run it again and get a different ",)
        print("thread name")
        print("typing 'quit' finishes the server")

        try:
            while not QUIT:
                try:
                    self.sock.settimeout(0.500)
                    client = self.sock.accept()[0]
                except socket.timeout:
                    time.sleep(1)
                    if QUIT:
                        print('Received quit command. Shutting down...')
                        break
                    continue
                new_thread = ClientThread(client)
                print('Incoming Connection. Started thread ',)
                print(new_thread.getName())
                self.thread_list.append(new_thread)
                new_thread.start()
                for thread in self.thread_list:
                    if not thread.isAlive():
                        self.thread_list.remove(thread)
                        thread.join()
        except KeyboardInterrupt:
            print('Ctrl+C pressed... Shutting Down')
        except Exception as err:
            print('Exception caught: %s\nClosing...' % err)
        for thread in self.thread_list:
            thread.join(1.0)
            self.sock.close()

if "__main__" == __name__:
    server = Server()
    server.run()

print('Terminated')

在追溯中,我得到了这个:

Exception in Thread-1:
Traceback (most recent call last):
File: "C:\Python34\liv\threading.py", line 920, in _bootstrap_inner
         self.run()
File: "C:/Users/Savag/PycharmProjects/lds_system/Socketthread2.py", line 20 in run
         self.writeline('Ok, bye'.encode("utf-8"))
File: "C:/Users/Savag/PycharmProjects/lds_system/Socketthread2.py", Line 40, in writeline
self.client.send((text.strip() + '\n').encode("utf-8"))

1 个答案:

答案 0 :(得分:2)

当您使用self.writeline('Ok bye'.encode('utf8'))时,您现在将bytes对象传递给writeline()方法。在该方法中,您将另一个字符串连接到它text.strip() + '\n',导致您尝试连接bytesstr对象。

您的writeline方法可以处理编码,也可以只处理bytes。如果您执行后者,请确保您的readline()方法解码从套接字读取的数据,以保持一致。

换句话说,选择一个从文本转换为字节的抽象级别,并一致地使用它:

def readline(self):
    """Read up to 1024 bytes and return this as a string

    Returns None if there was no data to read.

    """
    result = self.client.recv(1024)
    if result is not None:
        result = result.strip().lower().decode('utf8')
    return result

def writeline(self, text):
    """Write a string to the socket, followed by a newline"""
    self.client.send(text.strip().encode('utf8') + b'\n')

请注意,我使用b'...'字节文字来为换行符创建一个bytes对象。

此处writeline进行编码,因此在调用对象时传入字符串对象

self.writeline('Ok, bye')