Python 使用socket API编写基本HTTP服务器
我的server.py文件中有以下代码。它正在等待从客户端接收数据。此外,我不能使用任何http库。只有套接字库:Python 使用socket API编写基本HTTP服务器,python,python-3.x,sockets,python-3.5,Python,Python 3.x,Sockets,Python 3.5,我的server.py文件中有以下代码。它正在等待从客户端接收数据。此外,我不能使用任何http库。只有套接字库: def handle_client(conn, addr): print ('New client from', addr) x = [] try: while True: data = conn.recv(1024) decoded_data = data.decode('utf-8')
def handle_client(conn, addr):
print ('New client from', addr)
x = []
try:
while True:
data = conn.recv(1024)
decoded_data = data.decode('utf-8')
# if "GET / " in data.decode('utf-8'):
# handle_client_get(conn)
# else:
if data:
print(data)
x.append(decoded_data)
else:
print(x)
break
finally:
print("in close now")
conn.close()
我遇到的问题是,在手动关闭客户端后,我只能访问print(x)
语句。否则它不会打印
为什么会这样呢
答复
您需要向客户端发送确认,以便正确接收发送的数据
这将终止连接,而不是等待超时
这是因为客户端发送:Expect:100 continue
您需要将确认信息发送回客户端编辑:既然您提到这是一个HTTP服务器,并且只能使用
socket
库来完成,那么我建议您在此阶段从程序中删除某些复杂元素,比如删除while
块,直到问题解决为止
server.py
def handle_client(conn, addr):
print ('New client from', addr)
x = []
try:
data = conn.recv(1024)
decoded_data = data.decode('utf-8')
if data:
print(data)
x.append(decoded_data)
else:
print(x)
break
finally:
print("in close now")
conn.close()
def send_data(data,sock_obj,addr):
sock_obj.send(data+"\n")
sock_obj.flush()
原始答案:
尝试在发送方端发送一个附加的\n
,稍后使用刷新功能发送缓冲区上的任何剩余数据,如:
sender.py
def handle_client(conn, addr):
print ('New client from', addr)
x = []
try:
data = conn.recv(1024)
decoded_data = data.decode('utf-8')
if data:
print(data)
x.append(decoded_data)
else:
print(x)
break
finally:
print("in close now")
conn.close()
def send_data(data,sock_obj,addr):
sock_obj.send(data+"\n")
sock_obj.flush()
您需要实现协议,该协议将有一种方法告诉您要读取多少数据。在HTTP的情况下,请求以CRLF分隔的头开始,我们可以读取该头以获得所需的信息
w3.org
对。它比我想在这里实现的要复杂,但我已经包含了一个示例,它通过一次读取一个字符并查找一个空的\n
终止行来拉入请求头。通过一次读取一个字符,我不必实现自己的行缓冲区
第一行是请求方法,其余的行是请求中包含的其他参数。例如,对于POST,还有更多的数据需要从套接字读取
import re
def handle_client(conn, addr):
print ('New client from', addr)
header = []
line = []
try:
# read ascii http client header.
while True:
c = conn.recv(1)
# check for early termination
if not c:
return None
# check for end of request line
elif c == b"\n":
# make line a string to add to header
line = ''.join(line).decode('ascii').strip()
# are we at the empty line signalling end-of-header?
if not line:
break
header.append(line)
line = []
# filter out \r
elif c == b"\r":
continue
# request is first line of header
request_line = header.pop(0)
method, uri, http_version = re.split(r" +" request_line)
if method.upper() == "GET":
# this function needs more parameters... the uri to get and the protocol
# version to use.
handle_client_get(...)
finally:
print("in close now")
conn.close()
另一边没有关上插座。只有在接收通道被另一方关闭后,您才能获得一个空recv。但是,如果没有从客户端发送数据,我如何中断?你是说,即使没有数据从客户端发送,只要有一个连接,我就无法到达else语句?你需要定义你的协议以获得更好的答案。是否有接收更多数据的预期时间表?如果连接完成,服务器为什么保持打开状态?某些协议,例如telnet或ssh,可能在几分钟或几小时内没有数据,但连接仍然有效,并且在长时间没有数据之后可能会有更多数据。我使用的是curl,它是一个带有http协议的tcp连接。我应该定义内容长度吗?例如,http服务器将发送一个以换行符分隔的头、一个数据计数,然后发送数据本身。客户端需要实现此协议才能正常工作。我正在使用cURL,因此无法将此类详细信息添加到正在发送的客户端。不过,我不需要while循环,以便获得从客户端发送的所有数据??确定,以便客户端发出post请求,发送包含一些ascii字符的文件。我确实获得了所有信息,但一旦我获得了所有信息,它就不会关闭连接。就好像它在等待更多的数据。这就是我的问题。标题可能包含传输编码
来告诉您是ascii还是其他内容,以及内容长度
来告诉您要读取多少字节。但就像所有http一样,也可能会有复杂的情况。阅读第4.4节消息长度。这与Expect:100 continue
有关。我发现了问题所在是的,您必须实现协议!:)客户端将在发送请求后等待,以便从服务器接收响应。HTTP规范告诉您如何确定客户端何时完成发送请求。正如您所发现的,HTTPV1.1协议定义了“Expect”头,客户端将在继续之前等待预期的响应。