육현진

Upload new file

1 +#ifndef __ZHELPERS_HPP_INCLUDED__
2 +#define __ZHELPERS_HPP_INCLUDED__
3 +
4 +// Include a bunch of headers that we will need in the examples
5 +
6 +#include <zmq.hpp> // https://github.com/zeromq/cppzmq
7 +
8 +#include <iostream>
9 +#include <iomanip>
10 +#include <string>
11 +#include <sstream>
12 +
13 +#include <time.h>
14 +#include <assert.h>
15 +#include <stdlib.h> // random() RAND_MAX
16 +#include <stdio.h>
17 +#include <stdarg.h>
18 +#include <signal.h>
19 +#if (!defined(WIN32))
20 +# include <sys/time.h>
21 +# include <unistd.h>
22 +#endif
23 +
24 +// Bring Windows MSVC up to C99 scratch
25 +#if (defined (WIN32))
26 + typedef unsigned long ulong;
27 + typedef unsigned int uint;
28 + typedef __int64 int64_t;
29 +#endif
30 +
31 +// On some version of Windows, POSIX subsystem is not installed by default.
32 +// So define srandom and random ourself.
33 +//
34 +#if (defined (WIN32))
35 +# define srandom srand
36 +# define random rand
37 +#endif
38 +
39 +// Visual Studio versions below 2015 do not support sprintf properly. This is a workaround.
40 +// Taken from http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
41 +#if defined(_MSC_VER) && _MSC_VER < 1900
42 +
43 +#define snprintf c99_snprintf
44 +#define vsnprintf c99_vsnprintf
45 +
46 + inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
47 + {
48 + int count = -1;
49 +
50 + if (size != 0)
51 + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
52 + if (count == -1)
53 + count = _vscprintf(format, ap);
54 +
55 + return count;
56 + }
57 +
58 + inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
59 + {
60 + int count;
61 + va_list ap;
62 +
63 + va_start(ap, format);
64 + count = c99_vsnprintf(outBuf, size, format, ap);
65 + va_end(ap);
66 +
67 + return count;
68 + }
69 +
70 +#endif
71 +
72 +// Provide random number from 0..(num-1)
73 +#define within(num) (int) ((float)((num) * random ()) / (RAND_MAX + 1.0))
74 +
75 +// Receive 0MQ string from socket and convert into C string
76 +// Caller must free returned string.
77 +inline static char *
78 +s_recv(void *socket, int flags = 0) {
79 + zmq_msg_t message;
80 + zmq_msg_init(&message);
81 +
82 + int rc = zmq_msg_recv(&message, socket, flags);
83 +
84 + if (rc < 0)
85 + return nullptr; // Context terminated, exit
86 +
87 + size_t size = zmq_msg_size(&message);
88 + char *string = (char*)malloc(size + 1);
89 + memcpy(string, zmq_msg_data(&message), size);
90 + zmq_msg_close(&message);
91 + string[size] = 0;
92 + return (string);
93 +}
94 +
95 +// Receive 0MQ string from socket and convert into string
96 +inline static std::string
97 +s_recv (zmq::socket_t & socket, int flags = 0) {
98 +
99 + zmq::message_t message;
100 + socket.recv(&message, flags);
101 +
102 + return std::string(static_cast<char*>(message.data()), message.size());
103 +}
104 +
105 +inline static bool s_recv(zmq::socket_t & socket, std::string & ostring, int flags = 0)
106 +{
107 + zmq::message_t message;
108 + bool rc = socket.recv(&message, flags);
109 +
110 + if (rc) {
111 + ostring = std::string(static_cast<char*>(message.data()), message.size());
112 + }
113 +
114 + return (rc);
115 +}
116 +
117 +// Convert C string to 0MQ string and send to socket
118 +inline static int
119 +s_send(void *socket, const char *string, int flags = 0) {
120 + int rc;
121 + zmq_msg_t message;
122 + zmq_msg_init_size(&message, strlen(string));
123 + memcpy(zmq_msg_data(&message), string, strlen(string));
124 + rc = zmq_msg_send(&message, socket, flags);
125 + assert(-1 != rc);
126 + zmq_msg_close(&message);
127 + return (rc);
128 +}
129 +
130 +// Convert string to 0MQ string and send to socket
131 +inline static bool
132 +s_send (zmq::socket_t & socket, const std::string & string, int flags = 0) {
133 +
134 + zmq::message_t message(string.size());
135 + memcpy (message.data(), string.data(), string.size());
136 +
137 + bool rc = socket.send (message, flags);
138 + return (rc);
139 +}
140 +
141 +// Sends string as 0MQ string, as multipart non-terminal
142 +inline static int
143 +s_sendmore(void *socket, char *string) {
144 + int rc;
145 + zmq_msg_t message;
146 + zmq_msg_init_size(&message, strlen(string));
147 + memcpy(zmq_msg_data(&message), string, strlen(string));
148 + //rc = zmq_send(socket, string, strlen(string), ZMQ_SNDMORE);
149 + rc = zmq_msg_send(&message, socket, ZMQ_SNDMORE);
150 + assert(-1 != rc);
151 + zmq_msg_close(&message);
152 + return (rc);
153 +}
154 +
155 +// Sends string as 0MQ string, as multipart non-terminal
156 +inline static bool
157 +s_sendmore (zmq::socket_t & socket, const std::string & string) {
158 +
159 + zmq::message_t message(string.size());
160 + memcpy (message.data(), string.data(), string.size());
161 +
162 + bool rc = socket.send (message, ZMQ_SNDMORE);
163 + return (rc);
164 +}
165 +
166 +// Receives all message parts from socket, prints neatly
167 +//
168 +inline static void
169 +s_dump (zmq::socket_t & socket)
170 +{
171 + std::cout << "----------------------------------------" << std::endl;
172 +
173 + while (1) {
174 + // Process all parts of the message
175 + zmq::message_t message;
176 + socket.recv(&message);
177 +
178 + // Dump the message as text or binary
179 + size_t size = message.size();
180 + std::string data(static_cast<char*>(message.data()), size);
181 +
182 + bool is_text = true;
183 +
184 + size_t char_nbr;
185 + unsigned char byte;
186 + for (char_nbr = 0; char_nbr < size; char_nbr++) {
187 + byte = data [char_nbr];
188 + if (byte < 32 || byte > 127)
189 + is_text = false;
190 + }
191 + std::cout << "[" << std::setfill('0') << std::setw(3) << size << "]";
192 + for (char_nbr = 0; char_nbr < size; char_nbr++) {
193 + if (is_text)
194 + std::cout << (char)data [char_nbr];
195 + else
196 + std::cout << std::setfill('0') << std::setw(2)
197 + << std::hex << (unsigned int) data [char_nbr];
198 + }
199 + std::cout << std::endl;
200 +
201 + int more = 0; // Multipart detection
202 + size_t more_size = sizeof (more);
203 + socket.getsockopt (ZMQ_RCVMORE, &more, &more_size);
204 + if (!more)
205 + break; // Last message part
206 + }
207 +}
208 +
209 +#if (!defined (WIN32))
210 +// Set simple random printable identity on socket
211 +// Caution:
212 +// DO NOT call this version of s_set_id from multiple threads on MS Windows
213 +// since s_set_id will call rand() on MS Windows. rand(), however, is not
214 +// reentrant or thread-safe. See issue #521.
215 +inline std::string
216 +s_set_id (zmq::socket_t & socket)
217 +{
218 + std::stringstream ss;
219 + ss << std::hex << std::uppercase
220 + << std::setw(4) << std::setfill('0') << within (0x10000) << "-"
221 + << std::setw(4) << std::setfill('0') << within (0x10000);
222 + socket.setsockopt(ZMQ_IDENTITY, ss.str().c_str(), ss.str().length());
223 + return ss.str();
224 +}
225 +#else
226 +// Fix #521
227 +inline std::string
228 +s_set_id(zmq::socket_t & socket, intptr_t id)
229 +{
230 + std::stringstream ss;
231 + ss << std::hex << std::uppercase
232 + << std::setw(4) << std::setfill('0') << id;
233 + socket.setsockopt(ZMQ_IDENTITY, ss.str().c_str(), ss.str().length());
234 + return ss.str();
235 +}
236 +#endif
237 +
238 +// Report 0MQ version number
239 +//
240 +inline static void
241 +s_version (void)
242 +{
243 + int major, minor, patch;
244 + zmq_version (&major, &minor, &patch);
245 + std::cout << "Current 0MQ version is " << major << "." << minor << "." << patch << std::endl;
246 +}
247 +
248 +inline static void
249 +s_version_assert (int want_major, int want_minor)
250 +{
251 + int major, minor, patch;
252 + zmq_version (&major, &minor, &patch);
253 + if (major < want_major
254 + || (major == want_major && minor < want_minor)) {
255 + std::cout << "Current 0MQ version is " << major << "." << minor << std::endl;
256 + std::cout << "Application needs at least " << want_major << "." << want_minor
257 + << " - cannot continue" << std::endl;
258 + exit (EXIT_FAILURE);
259 + }
260 +}
261 +
262 +// Return current system clock as milliseconds
263 +inline static int64_t
264 +s_clock (void)
265 +{
266 +#if (defined (WIN32))
267 + FILETIME fileTime;
268 + GetSystemTimeAsFileTime(&fileTime);
269 + unsigned __int64 largeInt = fileTime.dwHighDateTime;
270 + largeInt <<= 32;
271 + largeInt |= fileTime.dwLowDateTime;
272 + largeInt /= 10000; // FILETIME is in units of 100 nanoseconds
273 + return (int64_t)largeInt;
274 +#else
275 + struct timeval tv;
276 + gettimeofday (&tv, NULL);
277 + return (int64_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000);
278 +#endif
279 +}
280 +
281 +// Sleep for a number of milliseconds
282 +inline static void
283 +s_sleep (int msecs)
284 +{
285 +#if (defined (WIN32))
286 + Sleep (msecs);
287 +#else
288 + struct timespec t;
289 + t.tv_sec = msecs / 1000;
290 + t.tv_nsec = (msecs % 1000) * 1000000;
291 + nanosleep (&t, NULL);
292 +#endif
293 +}
294 +
295 +inline static void
296 +s_console (const char *format, ...)
297 +{
298 + time_t curtime = time (NULL);
299 + struct tm *loctime = localtime (&curtime);
300 + char *formatted = new char[20];
301 + strftime (formatted, 20, "%y-%m-%d %H:%M:%S ", loctime);
302 + printf ("%s", formatted);
303 + delete[] formatted;
304 +
305 + va_list argptr;
306 + va_start (argptr, format);
307 + vprintf (format, argptr);
308 + va_end (argptr);
309 + printf ("\n");
310 +}
311 +
312 +// ---------------------------------------------------------------------
313 +// Signal handling
314 +//
315 +// Call s_catch_signals() in your application at startup, and then exit
316 +// your main loop if s_interrupted is ever 1. Works especially well with
317 +// zmq_poll.
318 +
319 +static int s_interrupted = 0;
320 +inline static void s_signal_handler (int signal_value)
321 +{
322 + s_interrupted = 1;
323 +}
324 +
325 +inline static void s_catch_signals ()
326 +{
327 +#if (!defined(WIN32))
328 + struct sigaction action;
329 + action.sa_handler = s_signal_handler;
330 + action.sa_flags = 0;
331 + sigemptyset (&action.sa_mask);
332 + sigaction (SIGINT, &action, NULL);
333 + sigaction (SIGTERM, &action, NULL);
334 +#endif
335 +}
336 +
337 +
338 +
339 +#endif