2011-01-09 157 views
6

我正在研究python中的一個項目。我有一個客戶端和一臺服務器。服務器監聽連接,一旦收到連接,它就等待來自客戶端的輸入。這個想法是,客戶端可以連接到服務器並執行系統命令,例如ls和cat。這是我的服務器代碼:Python客戶端/服務器問題

import sys, os, socket 


host = ''     
port = 50105 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host, port)) 
print("Server started on port: ", port) 

s.listen(5) 
print("Server listening\n") 
conn, addr = s.accept() 
print 'New connection from ', addr 
while (1): 
    rc = conn.recv(5) 
    pipe = os.popen(rc) 
    rl = pipe.readlines() 
    file = conn.makefile('w', 0) 
    file.writelines(rl[:-1]) 
    file.close() 
    conn.close() 

這是我的客戶端代碼:

import sys, socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
host = 'localhost' 
port = input('Port: ') 
s.connect((host, port)) 
cmd = raw_input('$ ') 
s.send(cmd) 
file = s.makefile('r', 0) 
sys.stdout.writelines(file.readlines()) 

當我開始我得到正確的輸出服務器,稱該服務器監聽。但是,當我與我的客戶端連接,並鍵入命令在服務器退出這個錯誤:

Traceback (most recent call last): 
File "server.py", line 21, in <module> 
    rc = conn.recv(2) 
File "/usr/lib/python2.6/socket.py", line 165, in _dummy 
    raise error(EBADF, 'Bad file descriptor') 
socket.error: [Errno 9] Bad file descriptor 

在客戶端,我得到LS的輸出,但服務器被搞砸了。

+1

那麼究竟什麼是你的問題? – 2011-01-10 00:34:55

+0

我該怎麼做才能使客戶端保持打開狀態,以獲取更多的命令。這樣客戶端可以繼續輸入命令並在服務器上執行。 – AustinM 2011-01-10 00:39:18

+1

你似乎在重塑ssh,爲什麼? – nosklo 2011-01-10 00:41:21

回答

6

您的代碼調用conn.close(),然後循環回到conn.recv(),但conn已關閉。

3

如果你希望你的客戶重複它在做什麼,只需要添加一個循環在那裏;)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
host = 'localhost' 
port = input('Port: ') 
s.connect((host, port)) 
while True: 
    cmd = raw_input('$ ') 
    s.send(cmd) 
    file = s.makefile('r', 0) 
    sys.stdout.writelines(file.readlines()) 

大概應該是更接近你想要什麼。

其他評論:

s.listen(1) 

這種說法也許應該while循環外移動。您只需撥打listen一次。

pipe = os.popen(rc) 

os.popen已被棄用,請改用subprocess module

file = s.makefile('r', 0) 

您正在打開一個文件,但您永遠不會關閉該文件。您應該在撥打sys.stdout.writelines()後添加file.close()

編輯:回答下面的評論;由於長度和格式不同而在此處完成

就目前而言,您從套接字中讀取一次,然後立即關閉它。因此,當客戶端發送下一個命令時,它會看到服務器關閉了套接字並指出錯誤。

解決方案是更改您的服務器代碼,以便它可以處理接收多個命令。請注意,這是通過引入另一個循環來解決的。

你需要用

rc = conn.recv(2) 
pipe = os.popen(rc) 
rl = pipe.readlines() 
fl = conn.makefile('w', 0) 
fl.writelines(rl[:-1]) 

在另一個while True:循環,使其反覆進行,直到客戶端斷開連接,然後包裹在一個try-except塊先得的IOError由conn.recv拋出( )當客戶端斷開連接時。

的try-except塊應該像

try: 
    # the described above loop goes here 
except IOError: 
    conn.close() 
# execution continues on...