1#!/usr/bin/env python 2# encoding: utf8 3# 4# Copyright © Burak Arslan <burak at arskom dot com dot tr>, 5# Arskom Ltd. http://www.arskom.com.tr 6# All rights reserved. 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions are met: 10# 11# 1. Redistributions of source code must retain the above copyright notice, 12# this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 3. Neither the name of the owner nor the names of its contributors may be 17# used to endorse or promote products derived from this software without 18# specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, 24# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 27# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 29# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30# 31 32""" 33Raw socket client example for MessagePackDocument via MessagePack server. 34""" 35 36from __future__ import print_function, absolute_import 37 38# These are analogues from spyne.server.msgpack. What's IN_REQUEST there is 39# OUT_REQUEST here because an outgoing request from a client's perspective is an 40# incoming request from a server's perspective. 41IN_RESPONSE_NO_ERROR = 0 42IN_RESPONSE_CLIENT_ERROR = 1 43IN_RESPONSE_SERVER_ERROR = 2 44 45OUT_REQUEST = 1 46 47 48import socket 49import msgpack 50 51from spyne.util.six import BytesIO 52 53s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 54s.connect(("localhost", 5550)) 55 56request_document = {"say_hello": ["Dave", 5]} 57 58# Because the server's input protocol is MessagePackDocument, we serialize the 59# request document to msgpack bytestream. 60request_bytestream = msgpack.packb(request_document) 61 62# Because our server side transport is msgpack, we put the request bytestream 63# inside another MessagePack document. 64request_wrapper_document = [OUT_REQUEST, request_bytestream] 65 66# and we serialize the request wrapper document to msgpack bytestream as well 67request_wrapper_bytestream = msgpack.packb(request_wrapper_document) 68 69# Some numbers to show how efficient this is: 70print("Raw message length:", len(request_bytestream)) 71print("Wrapped message length:", len(request_wrapper_bytestream)) 72print("Overhead:", len(request_wrapper_bytestream) - len(request_bytestream), 73 "byte(s).") 74 75# which we push to the socket. 76s.sendall(request_wrapper_bytestream) 77 78# This is straight from Python example in msgpack.org 79in_buffer = msgpack.Unpacker() 80 81while True: 82 # We wait for the full message to arrive. 83 in_buffer.feed(s.recv(1)) 84 85 # Again, straight from the Python example in MessagePack homepage. 86 for msg in in_buffer: 87 print("Raw response document:", msg) 88 89 # There should be only one entry in the response dict. We ignore the 90 # rest here but we could whine about invalid response just as well. 91 resp_code, data = iter(msg.items()).next() 92 93 # We finally parse the response. We should probably do a dict lookup 94 # here. 95 if resp_code == IN_RESPONSE_NO_ERROR: 96 print("Success. Response: ", msgpack.unpackb(data)) 97 # now that we have the response in a structured format, we could 98 # further deserialize it to a Python object, depending on our needs. 99 100 elif resp_code == IN_RESPONSE_CLIENT_ERROR: 101 print("Invalid Request. Details: ", msgpack.unpackb(data)) 102 103 elif resp_code == IN_RESPONSE_SERVER_ERROR: 104 print("Internal Error. Details: ", msgpack.unpackb(data)) 105 106 else: 107 print("Unknown response. Update the client. Additional data:", data) 108 109 # As we only sent one request, we must break after 110 # receiving its response. 111 break 112 else: 113 continue 114 115 break # break after receiving one message. See above for why. 116