Скрипт сервера / клиента работает нормально в MacOSX, но не работает в Ubuntu - PullRequest
0 голосов
/ 21 февраля 2012

Я и мой одноклассник пишем модель сервера / клиента на Python для школьного проекта. Все, что делает серверный скрипт - принимает соединения, сделанные от клиентов (запущенных на локальном хосте), и получает сообщения, распечатывая их в окне терминала. Сценарий был написан на Macbook Air, работающем под управлением OSX10.7.3 64bit, и работает так, как должен на этом компьютере, но при запуске на компьютере моего одноклассника Linux (Ubuntu 11.04 64bit) или на нашем компьютере под управлением Linux (Ubuntu 10.04 32bit) он работает несколько иначе , В сценарии и сервер, и клиент настроены как неблокирующие, и, как указано, на моем Mac это работает нормально, но на Linux-машине они действуют так же, как и на блокировке, не позволяя отправлять какие-либо данные с клиента nr2, до получения любого от клиента № 1.

Разве Python не должен быть мультиплатформенным языком? И если нет, то как лучше всего настроить наш код, чтобы он работал как на MacOS, так и на Ubuntu?

Извините, если это было несколько расплывчато, но я публикую свой код из сценария сервера и клиента ниже.

Кстати, мой Mac работает на Python 2.7.1, Ubuntu 11.04 работает на Python 2.7.1+, а Ubuntu 10.04 работает на Python 2.6.5.

Поскольку мы оба новички в программировании сокетов и являемся новичками в 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 Ответ

1 голос
/ 22 февраля 2012

По общему признанию, у меня нулевой опыт работы с неблокирующими сокетами, поэтому я не могу с этим ничего поделать.Однако описанное вами поведение, по-видимому, в точности соответствует вашему коду: сервер принимает запрос на подключение, создает новый объект 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.

PS: не используйте Python 3. Это потребует некоторых причуд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...