2015-02-09 4 views
-5

Из командной строкиPython Ошибка ввода-вывода все время пытается открыть файл

client.py Aaron 12000 HelloWorld.html GET

client.py

def main(argv): 
    serverName = argv[0] 
    serverPort = int(argv[1]) 
    fileName = argv[2] 
    typeOfHttpRequest = argv[3] 
    clientSocket = socket(AF_INET, SOCK_STREAM) 
    clientSocket.connect((serverName, serverPort)) 
    clientSocket.send(typeOfHttpRequest + " " + fileName + " HTTP/1.1\r\n\r\n") 
    content = clientSocket.recv(1024) 
    print content 
    clientSocket.close() 

if __name__ == "__main__": 
    main(sys.argv[1:]) 

server.py

while True: 
    #Establish the connection 
    print 'Ready to serve....' 
    connectionSocket, addr = serverSocket.accept() 

    try: 
     message = connectionSocket.recv(1024) 
     typeOfRequest = message.split()[0] 
     filename = message.split()[1] 
     print typeOfRequest 
     print filename 
     f = open(filename[1:]) 
     outputdata = f.read() 

     if typeOfRequest == 'GET': 
       for i in range(0, len(outputdata)): 
        connectionSocket.send(outputdata[i]) 
       connectionSocket.close() 
     elif typeOfRequest == 'HEAD': 
      connectionSocket.send(True) 
    except IOError: 
     connectionSocket.send('HTTP/1.1 404 Not Found') 
     connectionSocket.close() 

serverSocket.close() 

Я положил Hello World.html в том же каталоге, что и server.py, но это всегда создает IOError. Кто-нибудь знает, почему это может быть так?

  • Эти файлы находятся в каталоге C: \ Networking

  • os.getcwd показывает C: \ Networking

  • HelloWorld.html находится в C: /networking/HelloWorld.html

  • Имя файла печатается правильно.

enter image description here

+0

И правильно ли распечатывается имя файла? То есть это путь к файлу, заданный правилу 'open' –

+1

В будущем для сообщений об ошибках всегда указывайте * full traceback *. –

+0

Можете ли вы рассказать нам, что означает 'os.getcwd()' для вашего сервера? –

ответ

11

Как вы могли заметить, что вы пытаетесь лишить / с начала URL, хотя его там не было. Однако в вашем коде есть и другие ошибки, которые означают, что он не работает, как HTTP-сервер:

Прежде всего, recv() не гарантированно прочитает все данные - даже если бы было всего 1024 байта написано к сокету, recv(1024) может вернуть только 10 байт, скажем. Таким образом, лучше делать в петле:

buffer = [] 
while True: 
    data = connection_socket.recv(1024) 
    if not data: 
     break 
    buffer.append(data) 

message = ''.join(buffer) 

В настоящее время сообщение не может содержать все.

Далее, для обработки заголовка строки запроса, вы можете использовать

from cStringIO import StringIO 
message_reader = StringIO(message) 
first_line = next(message_reader) 
type_of_request, filename = message.split()[:2] 

С этим легче расширить свой код для получения более полной поддержки HTTP.

Теперь откройте файл с open, с with утверждения:

with open(filename) as f: 
    output_data = f.read() 

Это гарантирует, что файл закрыт тоже.

Наконец, когда вы отвечаете на запрос, вы должны ответить HTTP/1.0, а не HTTP/1.1, поскольку вы не поддерживаете полную степень HTTP/1.1.Кроме того, даже OK ответ должен реагировать с полными заголовками, скажем, с:

HTTP/1.1 200 OK 
Server: My Python Server 
Content-Length: 123 
Content-Type: text/html;charset=UTF-8 

data goes here.... 

Таким образом, ваша процедура передачи должен сделать:

if typeOfRequest == 'GET': 
    headers = ('HTTP/1.0 200 OK\r\n' 
     'Server: My Python Server\r\n' 
     'Content-Length: %d\r\n' 
     'Content-Type: text/html;charset=UTF-8\r\n\r\n' 
     'Connection: close\r\n' 
    ) % len(output_data) 

    connection_socket.sendall(headers) 
    connection_socket.sendall(output_data) 

Обратите внимание, как вы можете использовать sendall для отправки всех данных из файла строка.