Используя Python в Windows, как я могу отправлять и извлекать произвольное количество данных через сокет-соединение? - PullRequest
0 голосов
/ 23 октября 2011

Я пытаюсь следовать примеру из онлайн-учебника , касающемуся базового программирования сокетов клиент-сервер с использованием стандартных библиотек 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() в функции serve(), и ни одна из запрошенных данных не получена, насколько я могу судить.Что я упускаю из виду при работе с сокетами в Windows?

1 Ответ

3 голосов
/ 23 октября 2011

Похоже, вам может понадобиться запустить его в 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
Здравствуйте!

Более подробная информация о FAQ программиста Winsock


Сценарий, который вы используете, висит на 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  
...