在Windows中使用Python,如何通过套接字连接发送和检索任意数量的数据?

时间:2011-10-22 22:45:16

标签: python sockets networking client-server winsock

我试图关注使用标准Python库(版本2.7)的online tutorial关于基本客户端 - 服务器套接字编程的示例,但我无法让这个示例在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()函数中的serve(),程序就会停止响应,并且就我所知,没有收到任何请求的数据。关于Windows处理套接字,我忽略了什么?

1 个答案:

答案 0 :(得分:3)

看起来您可能需要让它在2个不同的进程中运行,或者将客户端和服务器拆分为2个不同的线程。我刚刚在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
  要发送的字符串:“你好!”

单独的控制台

  

C:\ Users \ jon \ Desktop> python server.py
  您好!

有关Winsock Programmer’s FAQ

的更多信息

您使用的脚本在sock, addr = listen_socket.accept()处挂起(如果设置了sock.settimeout(x),则会达到超时)。如果使用sock.setblocking(0),则会在socket.error: [Errno 10035] A non-blocking socket operation could not be completed immediately行引发异常accept(),这就是超时时发生的情况:

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