2012-03-22 3 views
0

im, выполняющий некоторые базовые программирование сокетов в python. Но у меня возникли проблемы с выяснением того, как мой echoserver мог заметить, что эхоклиент закрыл его соединение, без постоянного пинга/понга или таймаута.Socket close handler and proxy

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. Как я могу получить исключение для своего сервера, когда клиент отключается предпочтительно без сообщения pt/pong-сообщения betw их или установление.

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

  3. Что еще вы должны комментировать плохие/хорошие практики приветствуются

Спасибо!

+0

используя ubuntu 11.10, python 2.7.2 – daniel

ответ

1

Это было мое понимание библиотеки сокетов уже получает сообщение, когда clients disconnect.

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

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

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

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

if data: 
    # process data 
else: 
    # client disconnected 
+0

Не вызывать 'shutdown()' не пренебрегать. Если вам не нужно закрывать сокет наполовину (разрешить отправку больше не принимать или разрешать получать, но больше не отправлять), то просто закрытие дескриптора файла отлично. И это наиболее часто используемые случаи в большинстве случаев. Кроме того, сокеты обычно не являются частью библиотеки (с исключениями: например, на Solaris, они были). Обычно это системные вызовы, реализованные непосредственно ядром. (Вот так вы найдете документы в разделе 2 руководства.) – Celada

+0

Это сработало спасибо! – daniel

0

Библиотека сокетов 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 также может сделать прокси проще реализовать, а также.)

+0

Я думаю, что есть что-то подобное с gevent, который я планирую использовать в будущем. Я делаю это как небольшие упражнения для создания прокси-сервера irc в последующие месяцы в качестве моего первого приложения сокета на питоне. В любом случае спасибо! – daniel

+0

К сожалению, не похоже, что вы можете делать то, что ищете, с обычными розетками без «пинг/понг» или «сердцебиение». http://stackoverflow.com/questions/2697989/socket-lose-connection –

0

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