我不太了解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"))
答案 0 :(得分:2)
当您使用self.writeline('Ok bye'.encode('utf8'))
时,您现在将bytes
对象传递给writeline()
方法。在该方法中,您将另一个字符串连接到它text.strip() + '\n'
,导致您尝试连接bytes
和str
对象。
您的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')