Python socket.send()只能发送一次,然后出现socket.error:[Errno 32]发生管道损坏
我是网络编程的新手,所以如果这是一个愚蠢的问题,请原谅我:)
我在Ubuntu 10.04.2上使用Python2.7创建了1个客户端和1个SocketServer.ThreadingMixIn服务器,但是
似乎我只能在客户端调用sock.send()一次,然后得到一个:
I'm a newbie in network programming, so please forgive me if this is a dumb question :) I created 1 client and 1 SocketServer.ThreadingMixIn server on Ubuntu 10.04.2 using Python2.7, but it seems like I can only call sock.send() once in client, then I'll get a:
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:
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:
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()
我在两个单独的终端中运行它们:
I ran them in 2 separate terminals:
第一个终端的输出:
$ python2.7 testServer.py
server start
0
1
2
3
4
c1:0
5
6
7
8
9
10
11
...
第二终端的输出:
$ 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
我尝试直接在testClient.py中两次调用sock.send(),例如
:
I tried calling sock.send() twice directly in testClient.py, for ex:
while n<=1000:
sock.send('c1:{0}'.format(n))
sock.send('12333')
result=sock.recv(1024)
print(result)
n+=1
time.sleep(1)
但终端的输出仍然相同:(
有人可以指出我在这里做错什么吗? !
but the outputs of the terminals are still the same :( Can anyone please point out what am I doing wrong here? Thx in adv!
这是我想出的[Sol]。谢谢Mark:)
Here's the [Sol] I came up with. Thank you Mark:)
testClient1.py:
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:
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()
handle()在 SocketServer.StreamRequestHandler
中为每个连接调用一次。如果从句柄
返回,则连接已关闭。
handle() is called in the SocketServer.StreamRequestHandler
once for each connection. If you return from handle
the connection is closed.
如果您希望服务器处理多个发送/ recv,您必须循环播放,直到recv()返回0,表示客户端关闭了连接(或至少在发送时调用了shutdown())。
If you want the server to handle more than one send/recv, you must loop until recv() returns 0, indicating the client closed the connection (or at least called shutdown() on sends).
还要注意,TCP是流协议。您需要设计一个消息协议,以指示消息的长度或结尾,并缓冲 recv
直到收到完整的消息。检查发送
的返回值以确保所有消息也都已发送,或者使用 sendall
。
Also note that TCP is a streaming protocol. You'll need to design a message protocol that indicates the length or end of a message, and buffer recv
until you have a complete message. Check send
return value to make sure all the message is sent as well, or use sendall
.