Client read b'2014-06-03 01:29:01.463906'
Client read b'2014-06-03 01:29:06.465802'
Обе эти программы работают вечно, поэтому вам нужно завершать их вручную.
2. Используйте сокеты ZeroMQ REQ и REP, чтобы сделать то же самое.
Так выглядит файл zmq_time_server.py:
import zmq
from datetime import datetime
host = '127.0.0.1'
port = 6789
context = zmq.Context()
server = context.socket(zmq.REP)
server.bind("tcp://%s:%s" % (host, port))
print('Server started at', datetime.utcnow())
while True:
····#··Wait for next request from client
····message = server.recv()
····if message == b'time':
········now = datetime.utcnow()
········reply = str(now)
········server.send(bytes(reply, 'utf-8'))
········print('Server sent', reply)
А так — zmq_time_client.py:
import zmq
from datetime import datetime
from time import sleep
host = '127.0.0.1'
port = 6789
context = zmq.Context()
client = context.socket(zmq.REQ)
client.connect("tcp://%s:%s" % (host, port))
print('Client started at', datetime.utcnow())
while True:
····sleep(5)
····request = b'time'
····client.send(request)
····reply = client.recv()
····print("Client received %s" % reply)
Для простых сокетов вам нужно сначала запустить сервер. С помощью ZeroMQ вы можете запустить первым как клиент, так и сервер:
$ python zmq_time_server.py
Server started at 2014-06-03 01:39:36.933532
$ python zmq_time_client.py
Client started at 2014-06-03 01:39:42.538245
Через 15 секунд вы должны увидеть сообщения от сервера:
Server sent 2014-06-03 01:39:47.539878
Server sent 2014-06-03 01:39:52.540659
Server sent 2014-06-03 01:39:57.541403
Эти строки вы должны увидеть в сообщении от клиента:
Client received b'2014-06-03 01:39:47.539878'
Client received b'2014-06-03 01:39:52.540659'
Client received b'2014-06-03 01:39:57.541403'
3. Попробуйте сделать то же самое с помощью XMLRPC.
Сервер xmlrpc_time_server.py:
from xmlrpc.server import SimpleXMLRPCServer
def now():
····from datetime import datetime
····data = str(datetime.utcnow())
····print('Server sent', data)
····return data
server = SimpleXMLRPCServer(("localhost", 6789))
server.register_function(now, "now")
server.serve_forever()
И клиент xmlrpc_time_client.py:
import xmlrpc.client
from time import sleep
proxy = xmlrpc.client.ServerProxy("http://localhost:6789/")
while True:
····sleep(5)
····data = proxy.now()
····print('Client received', data)
Запустим сервер:
$ python xmlrpc_time_server.py
Запустим клиент:
$ python xmlrpc_time_client.py
Подождите примерно 15 секунд. Так выглядят первые три строки от сервера:
Server sent 2014-06-03 02:14:52.299122
127.0.0.1 — [02/Jun/2014 21:14:52] "POST / HTTP/1.1" 200 -
Server sent 2014-06-03 02:14:57.304741
127.0.0.1 — [02/Jun/2014 21:14:57] "POST / HTTP/1.1" 200 -
Server sent 2014-06-03 02:15:02.310377
127.0.0.1 — [02/Jun/2014 21:15:02] "POST / HTTP/1.1" 200 -
А так — первые три строки от клиента:
Client received 2014-06-03 02:14:52.299122
Client received 2014-06-03 02:14:57.304741
Client received 2014-06-03 02:15:02.310377
4. Возможно, вы видели эпизод телесериала I Love Lucy, в котором Люси и Этель работают на шоколадной фабрике (это классика). Парочка стала отставать, когда линия конвейера, которая направляла к ним на обработку конфеты, начала работать еще быстрее. Напишите симуляцию, которая отправляет разные типы конфет в список Redis, и клиент Lucy, который делает блокирующие выталкивания из списка. Ей нужно 0,5 секунды, чтобы обработать одну конфету. Выведите на экран время и тип каждой конфеты, которую получит Lucy, а также количество необработанных конфет:
redis_choc_supply.py передает бесконечное количество конфет:
import redis
import random
from time import sleep
conn = redis.Redis()
varieties = ['truffle', 'cherry', 'caramel', 'nougat']
conveyor = 'chocolates'
while True:
····seconds = random.random()
····sleep(seconds)
····piece = random.choice(varieties)
····conn.rpush(conveyor, piece)
redis_lucy.py может выглядеть так:
import redis
from datetime import datetime
from time import sleep
conn = redis.Redis()
timeout = 10
conveyor = 'chocolates'
while True:
····sleep(0.5)
····msg = conn.blpop(conveyor, timeout)
····remaining = conn.llen(conveyor)
····if msg:
········piece = msg[1]
········print('Lucy got a', piece, 'at', datetime.utcnow(),
········', only', remaining, 'left')
Запустите их в любом порядке. Поскольку Люси требуется полсекунды для обработки каждой конфеты и они появляются в среднем каждые полсекунды, это становится похоже на гонку. Чем раньше вы запустите конвейер, тем более сложной сделаете жизнь Люси:
$ python redis_choc_supply.py&
$ python redis_lucy.py
Lucy got a b'nougat' at 2014-06-03 03:15:08.721169, only 4 left
Lucy got a b'cherry' at 2014-06-03 03:15:09.222816, only 3 left
Lucy got a b'truffle' at 2014-06-03 03:15:09.723691, only 5 left
Lucy got a b'truffle' at 2014-06-03 03:15:10.225008, only 4 left
Lucy got a b'cherry' at 2014-06-03 03:15:10.727107, only 4 left
Lucy got a b'cherry' at 2014-06-03 03:15:11.228226, only 5 left
Lucy got a b'cherry' at 2014-06-03 03:15:11.729735, only 4 left
Lucy got a b'truffle' at 2014-06-03 03:15:12.230894, only 6 left
Lucy got a b'caramel' at 2014-06-03 03:15:12.732777, only 7 left
Lucy got a b'cherry' at 2014-06-03 03:15:13.234785, only 6 left
Lucy got a b'cherry' at 2014-06-03 03:15:13.736103, only 7 left
Lucy got a b'caramel' at 2014-06-03 03:15:14.238152, only 9 left
Lucy got a b'cherry' at 2014-06-03 03:15:14.739561, only 8 left
Бедная Люси.
5. Используйте ZeroMQ, чтобы публиковать стихотворение из упражнения 7 главы 7 по одному слову за раз. Напишите потребителя ZeroMQ, который будет выводить на экран каждое слово, начинающееся с гласной. Напишите другого потребителя, который будет выводить все слова, состоящие из пяти букв. Знаки препинания игнорируйте.