在Windows中使用Python,如何通过套接字连接发送和接收任意数量的数据?
我正在尝试跟着一个在线教程学习基本的客户端-服务器套接字编程,使用的是标准的Python库(版本2.7),但是在Windows(Vista)上这个例子无法运行。它在Ubuntu 11.10上运行得很好,所以我知道以下代码至少在基于UNIX的环境中是可以工作的:
import optparse, os, socket, time
def parse_args():
parser = optparse.OptionParser(usage)
help = "The port to listen on. Default to a random available port."
parser.add_option('--port', type='int', help=help)
help = "The interface to listen on. Default is localhost."
parser.add_option('--iface', help=help, default='localhost')
help = "The number of seconds between sending bytes."
parser.add_option('--delay', type='float', help=help, default=.1)
help = "The number of bytes to send at a time."
parser.add_option('--num-bytes', type='int', help=help, default=10)
options, args = parser.parse_args()
if len(args) != 1:
parser.error('Provide exactly one poetry file.')
poetry_file = args[0]
if not os.path.exists(args[0]):
parser.error('No such file: %s' % poetry_file)
return options, poetry_file
def send_poetry(sock, poetry_file, num_bytes, delay):
inputf = open(poetry_file)
while True:
bytes = inputf.read(num_bytes)
if not bytes:
sock.close()
inputf.close()
return
print 'Sending %d bytes' % len(bytes)
try:
sock.sendall(bytes) # this is a blocking call
except socket.error:
sock.close()
inputf.close()
return
time.sleep(delay)
def serve(listen_socket, poetry_file, num_bytes, delay):
while True:
sock, addr = listen_socket.accept()
print 'Somebody at %s wants poetry!' % (addr,)
send_poetry(sock, poetry_file, num_bytes, delay)
def main():
options, poetry_file = parse_args()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((options.iface, options.port or 0))
sock.listen(5)
print 'Serving %s on port %s.' % (poetry_file, sock.getsockname()[1])
serve(sock, poetry_file, options.num_bytes, options.delay)
if __name__ == '__main__':
main()
程序在调用套接字的accept()
方法时就停止响应了,而我能看到的情况是没有收到任何请求的数据。我在Windows处理套接字时忽略了什么呢?
1 个回答
3
看起来你可能需要在两个不同的进程中运行,或者把客户端和服务器分成两个不同的线程。我刚刚在我的Win7电脑上让这个工作起来了:
client.py
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 4242))
while True:
line = input("String to send: ")
s.send(line.encode("utf-8"))
server.py:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("0.0.0.0", 0))
s.listen(5)
client, address = s.accept()
while 1:
data = client.recv(1024)
if data:
client.send(data)
print(data.decode("utf-8"))
结果:
C:\Users\jon\Desktop>python.exe client.py
要发送的字符串: "Hello!"
另一个控制台
C:\Users\jon\Desktop>python server.py
Hello!
更多有用的信息可以在Winsock程序员常见问题解答找到
你使用的脚本在sock, addr = listen_socket.accept()
这行会卡住(如果设置了超时,会等到超时)。如果使用sock.setblocking(0)
,在accept()
这一行会抛出异常socket.error: [Errno 10035] 非阻塞套接字操作无法立即完成
,这就是超时发生时的情况:
def serve(listen_socket, poetry_file, num_bytes, delay):
while True:
print "accepting data"
try:
sock, addr = listen_socket.accept()
except socket.error, e:
print e
else:
print 'Somebody at %s wants poetry!' % (addr,)
send_poetry(sock, poetry_file, num_bytes, delay)
def main():
options, poetry_file = parse_args()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((options.iface, options.port or 0))
sock.listen(5)
sock.settimeout(5)
print 'Serving %s on port %s.' % (poetry_file, sock.getsockname()[1])
serve(sock, poetry_file, options.num_bytes, options.delay)
if __name__ == '__main__':
main()
结果是:
C:\Users\jon\Desktop>python.exe test.py poetry.txt
Serving poetry.txt on port 25355.
accepting data
timed out
accepting data
timed out
accepting data
timed out
accepting data
timed out
accepting data
timed out
accepting data
timed out
accepting data
timed out
accepting data