使用套接字API编写一个基本的HTTP服务器

使用套接字API编写一个基本的HTTP服务器

问题描述:

我有以下代码在我的server.py文件中。它正在等待从客户端接收数据。另外我不能使用任何的http库。只有插座库:使用套接字API编写一个基本的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)声明一次我手动CTRL + C关闭客户端。否则它不会打印。

为什么是这种情况。

ANSWER

您需要确认发送到这样发送的数据已经正确接收客户端。

这将终止连接,而不是等待超时。

这是因为客户端发送:Expect: 100-continue 你需要发送一个确认返回给客户端

+0

另一侧没有关闭插座。在接收通道被另一端关闭后,您只会收到一个空的recv。 – tdelaney

+0

但是如果没有数据从客户端发送,我该怎么办? 你是说即使没有数据从客户端发送,只要有一个连接,我不能达到else语句? – user3450754

+0

您需要定义您的协议才能获得更好的答案。是否有接收更多数据的预期时间表?为什么服务器在连接完成后保持连接状态?有些协议,例如telnet或ssh,可能没有数据的分钟或小时,但连接仍然有效,并且在没有数据的延长时间段之后可能有更多的数据。 – dsh

编辑
既然你提到这是一个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() 

原来的答案:

尝试在发送端发送一个额外\n和使用flush功能后发出的缓冲区内把所有剩余的数据如:

sender.py

def send_data(data,sock_obj,addr): 
    sock_obj.send(data+"\n") 
    sock_obj.flush() 
+0

我使用的卷曲,所以我不能添加这些细节,以客户正在发送 – user3450754

+0

吗?我不需要while循环,虽然,这样我得到的所有数据从客户端发送? – user3450754

您需要实现协议,该协议将会告诉您需要读取多少数据。在HTTP的情况下,请求以CRLF定界标题开始,我们可以读取它以获取我们想要的信息。

w3.orghttp request protocol有很好的描述。它比我想在这里实现更复杂,但我已经包含了一个例子,通过读取套接字一个字符,并寻找一个空的\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() 
+0

好的,客户端会发送一个发送一个包含一些ascii字符的文件的请求。我确实得到了所有的信息,但只要我得到所有信息,就不会关闭连接。就好像它正在等待更多的数据。这是我的问题。 – user3450754

+0

头部可能会包含'Transfer-Encoding'来告诉你它是否是ascii或其他内容,以及'Content-Length'来告诉你要读取多少字节。但像所有事情一样,可能会有复杂性。阅读部分_4.4消息长度_ [这里](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3)。 – tdelaney

+0

这与'expect:100-continue'有关。我发现问题出在哪里 – user3450754