Python socket.send()只能发送一次,然后socket.error:[Errno 32]发生了断管

hen*_*ice 11 python broken-pipe socketserver

我是网络编程的新手,所以如果这是一个愚蠢的问题,请原谅我:)我使用Python2.7在Ubuntu 10.04.2上创建了1个客户端和1个SocketServer.ThreadingMixIn服务器,但似乎我只能调用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
Run Code Online (Sandbox Code Playgroud)

这是我写的代码:

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)
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

我在两个独立的终端中运行它们:

第一终端的输出:

$ python2.7 testServer.py
server start
0
1
2
3
4
c1:0
5
6
7
8
9
10
11
...
Run Code Online (Sandbox Code Playgroud)

第二终端输出:

$ 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
Run Code Online (Sandbox Code Playgroud)

我尝试直接在testClient.py中调用sock.send()两次,例如:

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

但终端的输出仍然是相同的:(任何人都可以请指出我在这里做错了什么?谢谢!

这是我提出的[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()
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

Mar*_*nen 16

SocketServer.StreamRequestHandler每次连接都会调用一次handle().如果从handle连接返回则关闭.

如果您希望服务器处理多个send/recv,则必须循环直到recv()返回0,表示客户端关闭了连接(或者至少在发送时调用了shutdown()).

另请注意,TCP是一种流协议.您需要设计一个消息协议,指示消息的长度或结束,并缓冲,recv直到您有完整的消息.检查send返回值以确保发送所有消息,或使用sendall.