Обработчик закрытия сокета и прокси - PullRequest
0 голосов
/ 22 марта 2012

Я занимаюсь программированием сокетов в Python.Но у меня возникли проблемы с выяснением того, как мой эхосервер мог заметить, что эхоклиент закрыл соединение, без постоянного пинга / понга или тайм-аута.

echoclient.py

#echoclient
import sys
import socket
import os
import datetime

def log(s):
    return datetime.datetime.now().strftime('%H:%M:%S') + ' - ' + s

s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)

s.connect(('127.0.0.1', 9000))

while 1:
    try:
        foo = raw_input('what do you want to send?: ')
        if len(foo) > 0:
            s.send(foo)
    except KeyboardInterrupt:
        print 'shutting down connection'
        s.close()
        break
    data = s.recv(1024)
    if data:
        print log('Recieved'), repr(data)

echoserver.py

#echoserver
import sys
import socket
import os
import datetime

def log(s):
    return datetime.datetime.now().strftime('%H:%M:%S') + ' - ' + s

port = 9000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', port))
s.listen(5)

while 1:
    conn, addr = s.accept()
    conn.settimeout(10)
    print 'Connected by', addr
    while 1:
        try:
            data = conn.recv(1024)
            if data:
                print log(repr(data))
                conn.send(data)
        except KeyboardInterrupt:
            print 'Closing connection ', addr
            conn.close()
            sys.exit(1)
        except:
            print 'Exception caught! closing connection ', addr
            conn.close()
            break           

Теперь сервер знает, что клиент умер, только с помощью conn.settimeout (10)

  1. Как получить исключение для моегосервер, когда клиент отключается, предпочтительно без сообщения ping / pong между ними или settimeout.

  2. Мой следующий шаг - создать echoproxy между echoclient и echoserver, мне нужно будет использовать потоки/ многопроцессорность для достижения этой цели?Любые советы или указатели?

  3. Любые комментарии по поводу плохих / хороших практик приветствуются

Спасибо!

Ответы [ 3 ]

1 голос
/ 22 марта 2012

Насколько я понимаю, библиотека сокетов уже получает сообщение, когда клиенты отключаются .

Строго говоря, вы должны использовать отключение на сокете, прежде чем закрыть его,Отключение является рекомендацией для сокета на другом конце.В зависимости от аргумента, который вы передаете, это может означать: «Я не собираюсь больше отправлять, но я все равно буду слушать» или «Я не слушаю, хорошее избавление!».Однако большинство библиотек сокетов настолько привыкли к программистам, которые пренебрегают этим этикетом, и обычно закрытие - это то же самое, что shutdown ();близко().Так что в большинстве ситуаций явное отключение не требуется.

Сервер может обнаружить «EOF» при получении 0 байтов.Можно предположить, что у него есть полный запрос.Сервер отправляет ответ.Если отправка завершается успешно, тогда клиент все еще получает.

Когда другой конец отключается внезапно (например, сбой сети или сбой), вот тогда наступает тайм-аут.

В приведенном выше коде сервера вы сможете мгновенно обнаруживать разъединения клиента, используя:

if data:
   # process data
else:
   # client disconnected
0 голосов
/ 22 марта 2012

Используйте socket.shutdown() перед вызовом socket.close(). Прочитайте примечание дать для socket.close() здесь

0 голосов
/ 22 марта 2012

Библиотека сокетов Python является низкоуровневой реализацией, поэтому ее сложно использовать. Я бы порекомендовал использовать что-то более высокого уровня, например, Twisted. В Twisted вы можете делать именно то, что ищете, с помощью метода connectLost.

from twisted.internet.protocol import Protocol

class Echo(Protocol):
    def connectLost(self, reason):
        pass

Подробнее см. http://twistedmatrix.com/documents/current/core/howto/servers.html.

(Twisted также может упростить реализацию прокси).

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