2015-02-09 47 views
-5

從命令行Python的IO錯誤所有的時間試圖打開一個文件

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() 

我已經把你好World.html與server.py位於同一目錄中,但這總是會產生IOError。任何人都知道爲什麼它可能是這種情況?

  • 該文件位於C:\網絡

  • os.getcwd示出了C:\網絡

  • HelloWorld.html的位於C:/networking/HelloWorld.html

  • 文件名打印正確。

enter image description here

+0

並且文件名打印出來是否正確?即是給「open」正確的文件路徑 – 2015-02-09 08:57:17

+1

將來,對於錯誤消息,請始終包含* full tr​​aceback *。 – 2015-02-09 08:58:45

+0

你能告訴我們什麼'os.getcwd()'是你的服務器? – 2015-02-09 09:00:11

回答

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從發送的所有數據串。

相關問題