Python socket.send() может отправить только один раз, затем socket.error: [Errno 32] Обрыв канала

Я новичок в сетевом программировании, поэтому, пожалуйста, простите меня, если это глупый вопрос :) Я создал 1 клиент и 1 сервер SocketServer.ThreadingMixIn на Ubuntu 10.04.2 с использованием Python2.7, но, похоже, я могу вызывать только sock .send() один раз в клиенте, тогда я получу:

Traceback (most recent call last):
  File "testClient1.py", line 33, in <module>
    sock.send('c1:{0}'.format(n))   
socket.error: [Errno 32] Broken pipe

Вот код, который я написал:

testClient1.py:

#! /usr/bin/python2.7
# -*- coding: UTF-8 -*-
import sys,socket,time,threading
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    sock.connect(('localhost',20000))
except socket.error:
    print('connection error')
    sys.exit(0)
n=0
while n<=1000:
    sock.send('c1:{0}'.format(n))   
    result=sock.recv(1024)
    print(result)
    n+=1
    time.sleep(1)

testServer.py:

#! /usr/bin/python2.7
# -*- coding: UTF-8 -*-
import threading,SocketServer,time

class requestHandler(SocketServer.StreamRequestHandler):
    #currentUserLogin={} #{clientArr:accountName}
    def handle(self):
        requestForUpdate=self.rfile.read(4)
        print(requestForUpdate)
        self.wfile.write('server reply:{0}'.format(requestForUpdate))

class broadcastServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

if __name__ == '__main__':

    server=broadcastServer(('localhost',20000),requestHandler)
    t = threading.Thread(target=server.serve_forever)
    t.daemon=True
    t.start()
    print('server start')
    n=0
    while n<=60:
        print(n)
        n+=1
        time.sleep(1)
    server.socket.close()

Я запустил их в 2 отдельных терминалах:

вывод 1-го терминала:

$ python2.7 testServer.py
server start
0
1
2
3
4
c1:0
5
6
7
8
9
10
11
...

выход 2-го терминала:

$ python2.7 testClient1.py
server reply:c1:0

Traceback (most recent call last):
  File "testClient1.py", line 33, in <module>
    sock.send('c1:{0}'.format(n))   
socket.error: [Errno 32] Broken pipe

Я попытался дважды вызвать sock.send() непосредственно в testClient.py, например:

while n<=1000:
        sock.send('c1:{0}'.format(n))
        sock.send('12333')    
        result=sock.recv(1024)
        print(result)
        n+=1
        time.sleep(1)

но выходы терминалов все те же :( Может ли кто-нибудь указать, что я здесь делаю неправильно? Спасибо за рекламу!

Вот [Sol], который я придумал. Спасибо Марк :)

testClient1.py:

import sys,socket,time
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    sock.connect(('localhost',20000))
except socket.error:
    print('connection error')
    sys.exit(0)
n=0
while n<=10:    #connect once
    sock.send('c1:{0}'.format(n))
    result=sock.recv(1024)
    print(result)    
    n+=1
    time.sleep(1)
sock.close()

#once you close a socket, you'll need to initialize it again to another socket obj if you want to retransmit
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    sock.connect(('localhost',20000))
except socket.error:
    print('connection error')
    sys.exit(0)
n=0
while n<=10:    #connect once
    sock.send('c3:{0}'.format(n))
    result=sock.recv(1024)
    print(result)    
    n+=1
    time.sleep(1)
sock.close()

testServer.py:

import threading,SocketServer,time

class requestHandler(SocketServer.StreamRequestHandler):
    #currentUserLogin={} #{clientArr:accountName}
    def handle(self):
        requestForUpdate=self.request.recv(1024)
        print(self.client_address)
        while requestForUpdate!='':           
            print(requestForUpdate)
            self.wfile.write('server reply:{0}'.format(requestForUpdate))
            requestForUpdate=self.request.recv(1024)
        print('client disconnect')

class broadcastServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

if __name__ == '__main__':

    server=broadcastServer(('localhost',20000),requestHandler)
    t = threading.Thread(target=server.serve_forever)
    t.daemon=True
    t.start()
    print('server start')
    n=0
    while n<=60:
        print(n)
        n+=1
        time.sleep(1)
    server.socket.close()

person hencrice    schedule 04.06.2011    source источник


Ответы (1)


handle() вызывается в SocketServer.StreamRequestHandler один раз для каждого соединения. Если вы вернетесь из handle, соединение будет закрыто.

Если вы хотите, чтобы сервер обрабатывал более одной отправки/получения, вы должны зацикливаться до тех пор, пока recv() не вернет 0, указывая на то, что клиент закрыл соединение (или, по крайней мере, вызвал shutdown() при отправке).

Также обратите внимание, что TCP является потоковым протоколом. Вам потребуется разработать протокол сообщений, указывающий длину или конец сообщения, и буферизовать recv, пока вы не получите полное сообщение. Проверьте возвращаемое значение send, чтобы убедиться, что все сообщения также отправлены, или используйте sendall.

person Mark Tolonen    schedule 04.06.2011
comment
спасибо, у меня тоже была такая же проблема. Интересно, почему этот материал не включен в документацию SocketServer. Вы знаете, где я могу найти подробную документацию по SocketServer.TCPServer? - person Punit Soni; 07.11.2013
comment
@PunitSoni, файл SocketServer.py очень простой. Поучительно просто прочитать источник. - person Mark Tolonen; 08.11.2013