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 JsonDocument 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 49 50import json 51import msgpack 52 53from spyne.util.six import BytesIO 54 55s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 56s.connect(("localhost", 5551)) 57 58request_document = {"say_hello": ["Dave", 5]} 59 60# Because the server's input protocol is JsonDocument, we serialize the 61# request document to json bytestream. 62request_bytestream = json.dumps(request_document) 63 64# Because our server side transport is msgpack, we put the request bytestream 65# inside a MessagePack document. 66request_wrapper_document = [OUT_REQUEST, request_bytestream] 67 68# and we serialize the request wrapper document to msgpack bytestream as well 69request_wrapper_bytestream = msgpack.packb(request_wrapper_document) 70 71# Some numbers to show how efficient this is: 72print("Raw message length:", len(request_bytestream)) 73print("Wrapped message length:", len(request_wrapper_bytestream)) 74print("Overhead:", len(request_wrapper_bytestream) - len(request_bytestream), 75 "byte(s).") 76 77# which we push to the socket. 78s.sendall(request_wrapper_bytestream) 79 80# This is straight from Python example in msgpack.org 81in_buffer = msgpack.Unpacker() 82 83while True: 84 # We wait for the full message to arrive. 85 in_buffer.feed(s.recv(1)) 86 87 # Again, straight from the Python example in MessagePack homepage. 88 for msg in in_buffer: 89 print("Raw response document:", msg) 90 91 # There should be only one entry in the response dict. We ignore the 92 # rest here but we could whine about invalid response just as well. 93 resp_code, data = iter(msg.items()).next() 94 95 # We finally parse the response. We should probably be doing a dict 96 # lookup here instead. 97 if resp_code == IN_RESPONSE_NO_ERROR: 98 print("Success. Response: ", json.loads(data)) 99 # now that we have the response in a structured format, we could 100 # further deserialize it to a Python object, depending on our needs. 101 102 elif resp_code == IN_RESPONSE_CLIENT_ERROR: 103 print("Invalid Request. Details: ", json.loads(data)) 104 105 elif resp_code == IN_RESPONSE_SERVER_ERROR: 106 print("Internal Error. Details: ", json.loads(data)) 107 108 else: 109 print("Unknown response. Update the client. Additional data:", data) 110 111 # As we only sent one request, we must break after 112 # receiving its response. 113 break 114 else: 115 continue 116 117 break # break after receiving one message. See above for why. 118