| // MessagePack for C++ example |
| // |
| // Copyright (C) 2008-2015 FURUHASHI Sadayuki and KONDO Takatoshi |
| // |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #include <msgpack.hpp> |
| #include <iostream> |
| #include <stdexcept> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <pthread.h> |
| |
| class Server { |
| public: |
| Server(int sock) : m_sock(sock) { } |
| |
| ~Server() { } |
| |
| typedef msgpack::unique_ptr<msgpack::zone> unique_zone; |
| |
| void socket_readable() |
| { |
| m_pac.reserve_buffer(1024); |
| |
| ssize_t count = |
| read(m_sock, m_pac.buffer(), m_pac.buffer_capacity()); |
| |
| if(count <= 0) { |
| if(count == 0) { |
| throw std::runtime_error("connection closed"); |
| } |
| if(errno == EAGAIN || errno == EINTR) { |
| return; |
| } |
| throw std::runtime_error(strerror(errno)); |
| } |
| |
| m_pac.buffer_consumed(count); |
| |
| msgpack::unpacked result; |
| while (m_pac.next(&result)) { |
| msgpack::object msg = result.get(); |
| unique_zone& life = result.zone(); |
| process_message(msg, life); |
| } |
| |
| if(m_pac.message_size() > 10*1024*1024) { |
| throw std::runtime_error("message is too large"); |
| } |
| } |
| |
| private: |
| void process_message(msgpack::object msg, unique_zone&) |
| { |
| std::cout << "message reached: " << msg << std::endl; |
| } |
| |
| private: |
| int m_sock; |
| msgpack::unpacker m_pac; |
| }; |
| |
| |
| static void* run_server(void* arg) |
| { |
| try { |
| Server* srv = reinterpret_cast<Server*>(arg); |
| |
| while(true) { |
| srv->socket_readable(); |
| } |
| return NULL; |
| |
| } catch (std::exception& e) { |
| std::cerr << "error while processing client packet: " |
| << e.what() << std::endl; |
| return NULL; |
| |
| } catch (...) { |
| std::cerr << "error while processing client packet: " |
| << "unknown error" << std::endl; |
| return NULL; |
| } |
| } |
| |
| struct fwriter { |
| fwriter(int fd) : m_fp( fdopen(fd, "w") ) { } |
| |
| void write(const char* buf, size_t buflen) |
| { |
| size_t count = fwrite(buf, buflen, 1, m_fp); |
| if(count < 1) { |
| std::cout << buflen << std::endl; |
| std::cout << count << std::endl; |
| throw std::runtime_error(strerror(errno)); |
| } |
| } |
| |
| void flush() { fflush(m_fp); } |
| |
| void close() { fclose(m_fp); } |
| |
| private: |
| FILE* m_fp; |
| }; |
| |
| |
| int main(void) |
| { |
| int pair[2]; |
| if (pipe(pair) != 0) return -1; |
| |
| // run server thread |
| Server srv(pair[0]); |
| pthread_t thread; |
| pthread_create(&thread, NULL, |
| run_server, reinterpret_cast<void*>(&srv)); |
| |
| // client thread: |
| fwriter writer(pair[1]); |
| msgpack::packer<fwriter> pk(writer); |
| |
| typedef msgpack::type::tuple<std::string, std::string, std::string> put_t; |
| typedef msgpack::type::tuple<std::string, std::string> get_t; |
| |
| put_t req1("put", "apple", "red"); |
| put_t req2("put", "lemon", "yellow"); |
| get_t req3("get", "apple"); |
| pk.pack(req1); |
| pk.pack(req2); |
| pk.pack(req3); |
| writer.flush(); |
| writer.close(); |
| |
| pthread_join(thread, NULL); |
| } |