Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用socket API编写基本HTTP服务器_Python_Python 3.x_Sockets_Python 3.5 - Fatal编程技术网

Python 使用socket API编写基本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')

我的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')
            # 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”头,客户端将在继续之前等待预期的响应。