2012-02-21 82 views
0

失敗,我和我的隊友類是用Python寫的服務器/客戶端模式的學校項目。所有服務器腳本都會接受來自客戶端(在本地主機上運行)的連接,並接收將消息打印到終端窗口。該腳本是在運行OSX10.7.3 64bit的Macbook Air上編寫的,並且在該計算機上運行,​​但在我的同學的Linux計算機(Ubuntu 11.04 64位)或我們的計算機實驗室Linux計算機(Ubuntu 10.04 32位)上運行時,它運行的有點不同。在腳本中,服務器和客戶端都設置爲非阻塞狀態,並且在我的Mac上可以正常工作,但是在Linux機器上,它們充當阻塞的功能,不允許從客戶端nr2發送任何數據,在收到任何來自客戶端nr1之前。服務器/客戶端腳本運行順利MacOSX上,但在Ubuntu

不應該的Python是一個多語言?如果不是,那麼調整我們的代碼的最好方法是什麼,使它在MacOS和Ubuntu上都能正常工作?

我很抱歉,如果這是有些模糊,但我後我的代碼從服務器及以下客戶端腳本兩者。

順便說一句,我的Mac上運行的Python 2.7.1,在Ubuntu 11.04的Python運行2.7.1+,並在Ubuntu 10.04的Python運行2.6.5。

我們都是新Socket編程,並初學者的Python(因此學校的項目和簡單的代碼=)),這將是最欣賞的,如果有人可以以簡單的方式請詳細說明。

首先server.py文件:

import select 
import socket 
import sys 
import threading 
import client 

class Server: 
    def __init__(self): 
    self.host = 'localhost' 
    self.port = 50000 
    self.backlog = 5 
    self.size = 1024 
    self.server = None 
    self.threads = [] 

def openSocket(self): 
    try: 
     self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.server.bind((self.host, self.port)) 
     self.server.listen(5) 
     print "Listening to port " + str(self.port) + "..." 
    except socket.error, (value,message): 
     if self.server: 
      self.server.close() 
     print "Could not open socket: " + message 
     sys.exit(1) 

def run(self): 
    self.openSocket() 
    self.server.setblocking(0) 
    input = [self.server,sys.stdin] 
    running = True 
    while running: 

     inputready, outputready, exceptready = select.select(input,[],[], 0.01)    

     for s in inputready: 
      c = client.Client(self.server.accept()) 
      self.threads.append(c) 
      print "Client " + str(c.address) + " connected" 
      inputready.pop() 
     for c in self.threads: 
      try: 
       data = c.client.recv(self.size) 
       print data 
      except socket.error, (value,message): 
       continue 

    #close threads 
    self.server.close() 
    for c in self.threads: 
     c.join() 

if __name__ == "__main__": 
s = Server() 
s.run() 

然後client.py文件:

import select 
import socket 
import sys 
import server 
import threading 

class Client(threading.Thread): 
def __init__(self,(client,address)): 
    threading.Thread.__init__(self) 
    self.client = client 
    self.address = address 
    self.size = 1024 

def run(self): 
    self.client.connect(('localhost',50000)) 
    c.client.setblocking(0) 
    running = True 
    while running: 

     line = sys.stdin.readline() 
     if line == "exit": 
      self.client.close() 
     else: 
      self.client.sendall(line) 

    self.client.close() 

if __name__ == "__main__": 
c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost')) 
c.run() 

PS:沒關係一些循環縮進。當我複製粘貼我的代碼時發生了一些事情。 PPS:請注意,在任一臺計算機上運行此操作時,我們都不會收到任何錯誤消息。它的行爲不同。

在此先感謝

回答

1

誠然,我與非阻塞套接字零經驗,這樣我就可以真正幫助沒有。但是,您所描述的行爲似乎與您的代碼完全相同 - 服務器接受連接請求,創建新的Client對象,將其附加到列表中,然後逐個偵聽同一列表中的所有客戶端。這意味着第一個客戶端能夠連接併發送消息,但下一個客戶端無法連接,因爲服務器正在從第一個客戶端接收數據。

此外,該代碼是從未達到:

self.server.close() 
    for c in self.threads: 
     c.join() 

因爲服務器永遠不會停止接受請求。更重要的是,你似乎沒有啓動線程,你只是在創建它們。

無論如何,如果你修改服務器的運行功能這樣的,它應該工作:

from threading import Thread #this line is at the top of the file, of course 

def run(self): 
    self.openSocket() 
    self.running = True #make sure to implement some code that'll actually set this variable to False! 
    while self.running: 
     c= client.Client(self.server.accept()) 
     t= Thread(target=self.listenToClient,args=[c]) 
     t.daemon= True #this makes sure to kill the thread when the main thread exits 
     self.threads.append(t) 
     t.start() 

    #close threads 
    self.server.close() 
    for c in self.threads: 
     c.join() 

def listenToClient(self, c): 
    print "Client " + str(c.address) + " connected" 
    while self.running: 
     try: 
      data = c.client.recv(self.size) 
      if data=='': #if the client disconnected 
       return 
      print data 
     except socket.error, (value,message): 
      continue 

要麼我完全錯了或者我不知道爲什麼你的代碼在Mac OSX。

P.S:確保不使用Python 3,那會需要一些怪癖。

+1

哇!它現在在兩個平臺上都很有魅力!儘管我在select()中調用了代碼,但是,因爲我認爲我們需要這個以便從服務器發送文件,或者我在這裏完全錯了嗎?無論如何,非常感謝。我想你讓我看到關於線程的燈也=) – 2012-02-23 09:19:22

+0

我不得不承認,我從未使用過選擇模塊,也沒有發過文件。幫不了你,抱歉。 – 2012-02-23 11:14:24

相關問題