Pytanie Python socket.send () może wysłać tylko raz, a następnie socket.error: [Errno 32] Zerwana rura wystąpiła


Jestem początkującym programistą w sieci, więc proszę wybaczyć, jeśli to głupie pytanie :) Stworzyłem serwer 1 klienta i 1 serwer SocketServer.ThreadingMixIn na Ubuntu 10.04.2, używając Python2.7, ale wydaje się, że mogę tylko wywołać sock.send () raz w kliencie, wtedy otrzymam:

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

Oto kod, który napisałem:

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()

Przeprowadziłem je w 2 oddzielnych terminalach:

wyjście pierwszego terminala:

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

wyjście drugiego terminala:

$ 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

Próbowałem wywołać sock.send () dwa razy bezpośrednio w testClient.py, na przykład:

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

ale wyjścia terminali są wciąż takie same :( Czy ktoś może wskazać, co tutaj robię źle? Thx in adv!

Oto [Sol] wymyśliłem. Dziękuję Mark :)

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()

11
2018-06-04 15:21


pochodzenie




Odpowiedzi:


Funkcja handle () jest wywoływana w SocketServer.StreamRequestHandler raz dla każdego połączenie. Jeśli wrócisz handle połączenie jest zamknięte.

Jeśli chcesz, aby serwer obsługiwał więcej niż jeden send / recv, musisz zapętlić, aż recv () zwróci 0, wskazując, że klient zamknął połączenie (lub przynajmniej wywołał shutdown () podczas wysyłania).

Zauważ również, że TCP to protokół przesyłania strumieniowego. Będziesz musiał zaprojektować protokół komunikatów wskazujący długość lub koniec wiadomości oraz bufor recv dopóki nie otrzymasz kompletnej wiadomości. Czek send zwracaj wartość, aby upewnić się, że wszystkie wiadomości są wysyłane, lub użyj sendall.


16
2018-06-04 16:16



Thx za informacje! W końcu udało mi się to zrobić :) - hencrice
dzięki, miałem również ten sam problem. Zastanawiam się, dlaczego te rzeczy nie są zawarte w dokumentacji SocketServer. Czy wiesz, gdzie mogę znaleźć szczegółowe dokumenty na temat SocketServer.TCPServer? - Punit Soni
@PunitSoni, the SocketServer.py plik jest bardzo prosty. Pouczające jest po prostu przeczytanie źródła. - Mark Tolonen