Гнездо: двухстороннее общение в питоне - PullRequest
5 голосов
/ 24 ноября 2011

Я хочу двустороннюю связь в Python:

Я хочу привязать сокет, к которому может подключиться один клиент, а затем сервер и клиент могут «общаться» друг с другом.

У меня уже есть основной слушатель:

import socket
HOST='' #localhost
PORT=50008

s=socket.socket(socket.AF_INET, socket.SOCK_STREAM ) #create an INET, STREAMing socket
s.bind((HOST,PORT)) #bind to that port
s.listen(1) #listen for user input and accept 1 connection at a time.

conn, addr = s.accept()

print "The connection has been set up"
bool=1
while bool==1:
        data=conn.recv(1024)
        print data
        if "#!END!#" in data:
                print "closing the connection"
                s.close()
                bool=0

Что я хочу сейчас сделать, так это реализовать что-то, поэтому этот сценарий также принимает пользовательский ввод и после нажатия клавиши ввода отправляет его обратно клиенту.

Но я не могу понять, как я могу это сделать? Потому что, если бы я сделал это так:

while bool==1:
    data=conn.recv(1024)
    print data
    u_input = raw_input("input now")
    if u_input != "":
       conn.send(u_input)
       u_input= ""

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

Как мне решить это?

Я хочу сохранить это в одном окне, это можно решить с помощью потоков?

(я никогда не использовал потоки в python)

Ответы [ 3 ]

3 голосов
/ 24 ноября 2011

В сокетах Python есть инструмент makefile , который значительно упрощает взаимодействие такого рода.После создания сокета s , затем запустите f = s.makefile().Это вернет объект с файловым интерфейсом (так что вы можете использовать readline , write , writelines и другие удобные вызовы методов).Сама стандартная библиотека Python использует этот подход (см., Например, исходные коды для ftplib и poplib ).

Чтобы получить текст от клиента и отобразить его на консоли сервера, напишите цикл с помощью print f.readline().

Чтобы получить текст с консоли сервера и отправить его клиенту, напишитецикл с f.write(raw_input('+ ') + '\n').

Чтобы отправлять и получать одновременно, делайте эти два шага в отдельных потоках:

 Thread(target=read_client_and_print_to_console).start()
 Thread(target=read_server_console_and_send).start()

Если вы предпочитаете асинхронную обработку по потокам, вот два примераНачало работы:

2 голосов
/ 24 ноября 2011

Основная проблема в том, что у вас есть два источника ввода, которые вы ожидаете: сокет и пользователь.Я могу придумать три основных подхода: использовать асинхронный ввод-вывод, использовать синхронный (блокирующий) ввод-вывод с несколькими потоками или использовать синхронный ввод-вывод с тайм-аутами.Последний подход концептуально самый простой: подождите, пока данные в сокете не дадут некоторый период ожидания, затем переключитесь на ожидание ввода данных пользователем для отправки, затем обратно в сокет и т. Д.

Я знаюна более низком уровне вы могли бы реализовать это сравнительно легко, обрабатывая сокет и стандартный ввод в качестве дескрипторов ввода-вывода и используя select для одновременного ожидания обоих, но я не могу вспомнить, отображается ли эта функциональность в Pythonили если да, то как.Это потенциально очень хороший способ справиться с этим, если вы можете заставить его работать.РЕДАКТИРОВАТЬ: Я посмотрел его, и Python имеет модуль select, но похоже, что он работает только в операционных системах Unix, как это - в Windows он может принимать только сокеты, а не STDIN или файлы.

1 голос
/ 24 ноября 2011

ты проверял скрученный? витая сетевая система и библиотека, управляемая событиями Python, или oidranot библиотека Python, специально разработанная для веб-сервера torando

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