在TCP/IP python中在何处添加编码和解码
我需要从一台笔记本电脑到另一台笔记本电脑发送/接收数据,我使用的是在TCP/IP python中在何处添加编码和解码,python,tcp-ip,Python,Tcp Ip,我需要从一台笔记本电脑到另一台笔记本电脑发送/接收数据,我使用的是Python3.6,看起来这个版本的python需要.encode()和.decode() 函数,我使用的是Python2.7,以前我没有遇到任何问题,但是现在和Python3.6我必须使用这些函数,但是我不确定应该在哪里使用.decode()命令,您可以在我的服务器文件和客户机文件下面找到 服务器文件: import socket import threading import os def RetrFile(name, so
Python3.6
,看起来这个版本的python需要.encode()
和.decode()
函数,我使用的是Python2.7
,以前我没有遇到任何问题,但是现在和Python3.6
我必须使用这些函数,但是我不确定应该在哪里使用.decode()
命令,您可以在我的服务器文件和客户机文件下面找到
服务器文件:
import socket
import threading
import os
def RetrFile(name, sock):
filename = sock.recv(1024)
filename.decode()
if os.path.isfile(filename):
sock.send("EXISTS " + str(os.path.getsize(filename)))
userResponse = sock.recv(1024)
if userResponse[:2] == 'OK':
with open(filename, 'rb') as f:
bytesToSend = f.read(1024)
sock.send(bytesToSend)
while bytesToSend != "":
bytesToSend = f.read(1024)
sock.send(bytesToSend)
else:
sock.send("ERR ")
sock.close()
def MainServer():
host = '172.16.1.2' #my IP adress
port = 5000
s = socket.socket()
s.bind((host,port))
s.listen(5)
print ("Server Started.")
while True:
c, addr = s.accept()
print ("client connected ip:<" + str(addr) + ">")
t = threading.Thread(target=RetrFile, args=("RetrThread", c))
t.start()
s.close()
if __name__ == '__main__':
MainServer()
谢谢你的帮助。你发明了这个协议,所以你可以决定什么时候解码。一个选项是说基本协议(如OK和ERR始终是ascii,可以作为字节管理),但文件名和类似的内容是utf-8编码字符串,需要解码。但是二进制文件呢?您需要将流的该部分定义为二进制,或者对内容进行二进制到ascii编码 但它的方式比这更复杂。TCP是一种流协议。没有任何东西表明,
recv
获取另一方在一次调用中发送的所有内容,或者以方便的utf-8字符边界结束。您不能只recv(1024)
而期望得到确切的消息边界
因此,是时候进行彻底的反思了:定义一个不同的协议。要遵循现有模式,可以使用基于ascii的标头,而不是以新行结尾。标头是一些命令或状态,后跟每个附加参数的字节大小,后跟换行符。之后将直接写入参数
您可以使用如下命令
STAT <sizeof utf-8 encoded file name>\n<utf-8-encoded-filename>
EXISTS ascii-encoded-size\n
DOWNLOAD <sizeof utf-8 encoded file name>\n<utf-8-encoded-filename>
标题告诉您管道中有多少数据,因此您可以为其配备一个读取器
def read_chunk(sock, size, encoding=None):
buf = io.bytesIO()
while size:
tmp = sock.recv(min(size, 4096))
if not tmp:
raise OSError("Unexpected end of stream")
buf.write(tmp)
size -= len(tmp)
if encoding:
return buf.getvalue().encode(encoding)
else:
return buf.getvalue()
阅读这条小溪会很有趣
while True:
hdr = read_header(sock)
# try commands
m = re.match(b"STAT (\d+)", hdr)
if m:
stat_size = int(m.group(1))
file_name = read_chunk(sock, stat_size, 'utf-8')
# do the stat work...
continue
m = re.match(b"DOWNLOAD (\d+)", hdr)
etc...
通过传递
bytes
objectb“ERR”
而不是str
object“ERR”
,可以解决您眼前的问题。但是您知道如何对这行sock.send(bytesToSend)
进行编码吗。感谢您无论何时需要将字符串转换为字节,都可以使用str
类中的encode()
方法,如str.encode()
,或者更具体地说str.encode(“utf-8”)
。所以在你的例子中,bytesToSend.encode()
和“ERR.encode()
。所以我猜应该是这样的:bts=bytesToSend.encode()
sock.send(bts)!谢谢你的回答,我会尽量听你的。非常感谢。
def read_header(sock):
hdr = []
while True:
c = sock.recv(1)
if c == "\n":
return ''.join(hdr).encode('ascii')
def read_chunk(sock, size, encoding=None):
buf = io.bytesIO()
while size:
tmp = sock.recv(min(size, 4096))
if not tmp:
raise OSError("Unexpected end of stream")
buf.write(tmp)
size -= len(tmp)
if encoding:
return buf.getvalue().encode(encoding)
else:
return buf.getvalue()
while True:
hdr = read_header(sock)
# try commands
m = re.match(b"STAT (\d+)", hdr)
if m:
stat_size = int(m.group(1))
file_name = read_chunk(sock, stat_size, 'utf-8')
# do the stat work...
continue
m = re.match(b"DOWNLOAD (\d+)", hdr)
etc...