1 | // |
2 | // basic_seq_packet_socket.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
9 | // |
10 | |
11 | #ifndef BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP |
12 | #define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <cstddef> |
20 | #include <boost/asio/basic_socket.hpp> |
21 | #include <boost/asio/detail/handler_type_requirements.hpp> |
22 | #include <boost/asio/detail/throw_error.hpp> |
23 | #include <boost/asio/error.hpp> |
24 | #include <boost/asio/seq_packet_socket_service.hpp> |
25 | |
26 | #include <boost/asio/detail/push_options.hpp> |
27 | |
28 | namespace boost { |
29 | namespace asio { |
30 | |
31 | /// Provides sequenced packet socket functionality. |
32 | /** |
33 | * The basic_seq_packet_socket class template provides asynchronous and blocking |
34 | * sequenced packet socket functionality. |
35 | * |
36 | * @par Thread Safety |
37 | * @e Distinct @e objects: Safe.@n |
38 | * @e Shared @e objects: Unsafe. |
39 | */ |
40 | template <typename Protocol, |
41 | typename SeqPacketSocketService = seq_packet_socket_service<Protocol> > |
42 | class basic_seq_packet_socket |
43 | : public basic_socket<Protocol, SeqPacketSocketService> |
44 | { |
45 | public: |
46 | /// (Deprecated: Use native_handle_type.) The native representation of a |
47 | /// socket. |
48 | typedef typename SeqPacketSocketService::native_handle_type native_type; |
49 | |
50 | /// The native representation of a socket. |
51 | typedef typename SeqPacketSocketService::native_handle_type |
52 | native_handle_type; |
53 | |
54 | /// The protocol type. |
55 | typedef Protocol protocol_type; |
56 | |
57 | /// The endpoint type. |
58 | typedef typename Protocol::endpoint endpoint_type; |
59 | |
60 | /// Construct a basic_seq_packet_socket without opening it. |
61 | /** |
62 | * This constructor creates a sequenced packet socket without opening it. The |
63 | * socket needs to be opened and then connected or accepted before data can |
64 | * be sent or received on it. |
65 | * |
66 | * @param io_service The io_service object that the sequenced packet socket |
67 | * will use to dispatch handlers for any asynchronous operations performed on |
68 | * the socket. |
69 | */ |
70 | explicit basic_seq_packet_socket(boost::asio::io_service& io_service) |
71 | : basic_socket<Protocol, SeqPacketSocketService>(io_service) |
72 | { |
73 | } |
74 | |
75 | /// Construct and open a basic_seq_packet_socket. |
76 | /** |
77 | * This constructor creates and opens a sequenced_packet socket. The socket |
78 | * needs to be connected or accepted before data can be sent or received on |
79 | * it. |
80 | * |
81 | * @param io_service The io_service object that the sequenced packet socket |
82 | * will use to dispatch handlers for any asynchronous operations performed on |
83 | * the socket. |
84 | * |
85 | * @param protocol An object specifying protocol parameters to be used. |
86 | * |
87 | * @throws boost::system::system_error Thrown on failure. |
88 | */ |
89 | basic_seq_packet_socket(boost::asio::io_service& io_service, |
90 | const protocol_type& protocol) |
91 | : basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol) |
92 | { |
93 | } |
94 | |
95 | /// Construct a basic_seq_packet_socket, opening it and binding it to the |
96 | /// given local endpoint. |
97 | /** |
98 | * This constructor creates a sequenced packet socket and automatically opens |
99 | * it bound to the specified endpoint on the local machine. The protocol used |
100 | * is the protocol associated with the given endpoint. |
101 | * |
102 | * @param io_service The io_service object that the sequenced packet socket |
103 | * will use to dispatch handlers for any asynchronous operations performed on |
104 | * the socket. |
105 | * |
106 | * @param endpoint An endpoint on the local machine to which the sequenced |
107 | * packet socket will be bound. |
108 | * |
109 | * @throws boost::system::system_error Thrown on failure. |
110 | */ |
111 | basic_seq_packet_socket(boost::asio::io_service& io_service, |
112 | const endpoint_type& endpoint) |
113 | : basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint) |
114 | { |
115 | } |
116 | |
117 | /// Construct a basic_seq_packet_socket on an existing native socket. |
118 | /** |
119 | * This constructor creates a sequenced packet socket object to hold an |
120 | * existing native socket. |
121 | * |
122 | * @param io_service The io_service object that the sequenced packet socket |
123 | * will use to dispatch handlers for any asynchronous operations performed on |
124 | * the socket. |
125 | * |
126 | * @param protocol An object specifying protocol parameters to be used. |
127 | * |
128 | * @param native_socket The new underlying socket implementation. |
129 | * |
130 | * @throws boost::system::system_error Thrown on failure. |
131 | */ |
132 | basic_seq_packet_socket(boost::asio::io_service& io_service, |
133 | const protocol_type& protocol, const native_handle_type& native_socket) |
134 | : basic_socket<Protocol, SeqPacketSocketService>( |
135 | io_service, protocol, native_socket) |
136 | { |
137 | } |
138 | |
139 | #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
140 | /// Move-construct a basic_seq_packet_socket from another. |
141 | /** |
142 | * This constructor moves a sequenced packet socket from one object to |
143 | * another. |
144 | * |
145 | * @param other The other basic_seq_packet_socket object from which the move |
146 | * will occur. |
147 | * |
148 | * @note Following the move, the moved-from object is in the same state as if |
149 | * constructed using the @c basic_seq_packet_socket(io_service&) constructor. |
150 | */ |
151 | basic_seq_packet_socket(basic_seq_packet_socket&& other) |
152 | : basic_socket<Protocol, SeqPacketSocketService>( |
153 | BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other)) |
154 | { |
155 | } |
156 | |
157 | /// Move-assign a basic_seq_packet_socket from another. |
158 | /** |
159 | * This assignment operator moves a sequenced packet socket from one object to |
160 | * another. |
161 | * |
162 | * @param other The other basic_seq_packet_socket object from which the move |
163 | * will occur. |
164 | * |
165 | * @note Following the move, the moved-from object is in the same state as if |
166 | * constructed using the @c basic_seq_packet_socket(io_service&) constructor. |
167 | */ |
168 | basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other) |
169 | { |
170 | basic_socket<Protocol, SeqPacketSocketService>::operator=( |
171 | BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other)); |
172 | return *this; |
173 | } |
174 | |
175 | /// Move-construct a basic_seq_packet_socket from a socket of another protocol |
176 | /// type. |
177 | /** |
178 | * This constructor moves a sequenced packet socket from one object to |
179 | * another. |
180 | * |
181 | * @param other The other basic_seq_packet_socket object from which the move |
182 | * will occur. |
183 | * |
184 | * @note Following the move, the moved-from object is in the same state as if |
185 | * constructed using the @c basic_seq_packet_socket(io_service&) constructor. |
186 | */ |
187 | template <typename Protocol1, typename SeqPacketSocketService1> |
188 | basic_seq_packet_socket( |
189 | basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other, |
190 | typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) |
191 | : basic_socket<Protocol, SeqPacketSocketService>( |
192 | BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket< |
193 | Protocol1, SeqPacketSocketService1>)(other)) |
194 | { |
195 | } |
196 | |
197 | /// Move-assign a basic_seq_packet_socket from a socket of another protocol |
198 | /// type. |
199 | /** |
200 | * This assignment operator moves a sequenced packet socket from one object to |
201 | * another. |
202 | * |
203 | * @param other The other basic_seq_packet_socket object from which the move |
204 | * will occur. |
205 | * |
206 | * @note Following the move, the moved-from object is in the same state as if |
207 | * constructed using the @c basic_seq_packet_socket(io_service&) constructor. |
208 | */ |
209 | template <typename Protocol1, typename SeqPacketSocketService1> |
210 | typename enable_if<is_convertible<Protocol1, Protocol>::value, |
211 | basic_seq_packet_socket>::type& operator=( |
212 | basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other) |
213 | { |
214 | basic_socket<Protocol, SeqPacketSocketService>::operator=( |
215 | BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket< |
216 | Protocol1, SeqPacketSocketService1>)(other)); |
217 | return *this; |
218 | } |
219 | #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) |
220 | |
221 | /// Send some data on the socket. |
222 | /** |
223 | * This function is used to send data on the sequenced packet socket. The |
224 | * function call will block until the data has been sent successfully, or an |
225 | * until error occurs. |
226 | * |
227 | * @param buffers One or more data buffers to be sent on the socket. |
228 | * |
229 | * @param flags Flags specifying how the send call is to be made. |
230 | * |
231 | * @returns The number of bytes sent. |
232 | * |
233 | * @throws boost::system::system_error Thrown on failure. |
234 | * |
235 | * @par Example |
236 | * To send a single data buffer use the @ref buffer function as follows: |
237 | * @code |
238 | * socket.send(boost::asio::buffer(data, size), 0); |
239 | * @endcode |
240 | * See the @ref buffer documentation for information on sending multiple |
241 | * buffers in one go, and how to use it with arrays, boost::array or |
242 | * std::vector. |
243 | */ |
244 | template <typename ConstBufferSequence> |
245 | std::size_t send(const ConstBufferSequence& buffers, |
246 | socket_base::message_flags flags) |
247 | { |
248 | boost::system::error_code ec; |
249 | std::size_t s = this->get_service().send( |
250 | this->get_implementation(), buffers, flags, ec); |
251 | boost::asio::detail::throw_error(err: ec, location: "send" ); |
252 | return s; |
253 | } |
254 | |
255 | /// Send some data on the socket. |
256 | /** |
257 | * This function is used to send data on the sequenced packet socket. The |
258 | * function call will block the data has been sent successfully, or an until |
259 | * error occurs. |
260 | * |
261 | * @param buffers One or more data buffers to be sent on the socket. |
262 | * |
263 | * @param flags Flags specifying how the send call is to be made. |
264 | * |
265 | * @param ec Set to indicate what error occurred, if any. |
266 | * |
267 | * @returns The number of bytes sent. Returns 0 if an error occurred. |
268 | * |
269 | * @note The send operation may not transmit all of the data to the peer. |
270 | * Consider using the @ref write function if you need to ensure that all data |
271 | * is written before the blocking operation completes. |
272 | */ |
273 | template <typename ConstBufferSequence> |
274 | std::size_t send(const ConstBufferSequence& buffers, |
275 | socket_base::message_flags flags, boost::system::error_code& ec) |
276 | { |
277 | return this->get_service().send( |
278 | this->get_implementation(), buffers, flags, ec); |
279 | } |
280 | |
281 | /// Start an asynchronous send. |
282 | /** |
283 | * This function is used to asynchronously send data on the sequenced packet |
284 | * socket. The function call always returns immediately. |
285 | * |
286 | * @param buffers One or more data buffers to be sent on the socket. Although |
287 | * the buffers object may be copied as necessary, ownership of the underlying |
288 | * memory blocks is retained by the caller, which must guarantee that they |
289 | * remain valid until the handler is called. |
290 | * |
291 | * @param flags Flags specifying how the send call is to be made. |
292 | * |
293 | * @param handler The handler to be called when the send operation completes. |
294 | * Copies will be made of the handler as required. The function signature of |
295 | * the handler must be: |
296 | * @code void handler( |
297 | * const boost::system::error_code& error, // Result of operation. |
298 | * std::size_t bytes_transferred // Number of bytes sent. |
299 | * ); @endcode |
300 | * Regardless of whether the asynchronous operation completes immediately or |
301 | * not, the handler will not be invoked from within this function. Invocation |
302 | * of the handler will be performed in a manner equivalent to using |
303 | * boost::asio::io_service::post(). |
304 | * |
305 | * @par Example |
306 | * To send a single data buffer use the @ref buffer function as follows: |
307 | * @code |
308 | * socket.async_send(boost::asio::buffer(data, size), 0, handler); |
309 | * @endcode |
310 | * See the @ref buffer documentation for information on sending multiple |
311 | * buffers in one go, and how to use it with arrays, boost::array or |
312 | * std::vector. |
313 | */ |
314 | template <typename ConstBufferSequence, typename WriteHandler> |
315 | BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, |
316 | void (boost::system::error_code, std::size_t)) |
317 | async_send(const ConstBufferSequence& buffers, |
318 | socket_base::message_flags flags, |
319 | BOOST_ASIO_MOVE_ARG(WriteHandler) handler) |
320 | { |
321 | // If you get an error on the following line it means that your handler does |
322 | // not meet the documented type requirements for a WriteHandler. |
323 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
324 | |
325 | return this->get_service().async_send(this->get_implementation(), |
326 | buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); |
327 | } |
328 | |
329 | /// Receive some data on the socket. |
330 | /** |
331 | * This function is used to receive data on the sequenced packet socket. The |
332 | * function call will block until data has been received successfully, or |
333 | * until an error occurs. |
334 | * |
335 | * @param buffers One or more buffers into which the data will be received. |
336 | * |
337 | * @param out_flags After the receive call completes, contains flags |
338 | * associated with the received data. For example, if the |
339 | * socket_base::message_end_of_record bit is set then the received data marks |
340 | * the end of a record. |
341 | * |
342 | * @returns The number of bytes received. |
343 | * |
344 | * @throws boost::system::system_error Thrown on failure. An error code of |
345 | * boost::asio::error::eof indicates that the connection was closed by the |
346 | * peer. |
347 | * |
348 | * @par Example |
349 | * To receive into a single data buffer use the @ref buffer function as |
350 | * follows: |
351 | * @code |
352 | * socket.receive(boost::asio::buffer(data, size), out_flags); |
353 | * @endcode |
354 | * See the @ref buffer documentation for information on receiving into |
355 | * multiple buffers in one go, and how to use it with arrays, boost::array or |
356 | * std::vector. |
357 | */ |
358 | template <typename MutableBufferSequence> |
359 | std::size_t receive(const MutableBufferSequence& buffers, |
360 | socket_base::message_flags& out_flags) |
361 | { |
362 | boost::system::error_code ec; |
363 | std::size_t s = this->get_service().receive( |
364 | this->get_implementation(), buffers, 0, out_flags, ec); |
365 | boost::asio::detail::throw_error(err: ec, location: "receive" ); |
366 | return s; |
367 | } |
368 | |
369 | /// Receive some data on the socket. |
370 | /** |
371 | * This function is used to receive data on the sequenced packet socket. The |
372 | * function call will block until data has been received successfully, or |
373 | * until an error occurs. |
374 | * |
375 | * @param buffers One or more buffers into which the data will be received. |
376 | * |
377 | * @param in_flags Flags specifying how the receive call is to be made. |
378 | * |
379 | * @param out_flags After the receive call completes, contains flags |
380 | * associated with the received data. For example, if the |
381 | * socket_base::message_end_of_record bit is set then the received data marks |
382 | * the end of a record. |
383 | * |
384 | * @returns The number of bytes received. |
385 | * |
386 | * @throws boost::system::system_error Thrown on failure. An error code of |
387 | * boost::asio::error::eof indicates that the connection was closed by the |
388 | * peer. |
389 | * |
390 | * @note The receive operation may not receive all of the requested number of |
391 | * bytes. Consider using the @ref read function if you need to ensure that the |
392 | * requested amount of data is read before the blocking operation completes. |
393 | * |
394 | * @par Example |
395 | * To receive into a single data buffer use the @ref buffer function as |
396 | * follows: |
397 | * @code |
398 | * socket.receive(boost::asio::buffer(data, size), 0, out_flags); |
399 | * @endcode |
400 | * See the @ref buffer documentation for information on receiving into |
401 | * multiple buffers in one go, and how to use it with arrays, boost::array or |
402 | * std::vector. |
403 | */ |
404 | template <typename MutableBufferSequence> |
405 | std::size_t receive(const MutableBufferSequence& buffers, |
406 | socket_base::message_flags in_flags, |
407 | socket_base::message_flags& out_flags) |
408 | { |
409 | boost::system::error_code ec; |
410 | std::size_t s = this->get_service().receive( |
411 | this->get_implementation(), buffers, in_flags, out_flags, ec); |
412 | boost::asio::detail::throw_error(err: ec, location: "receive" ); |
413 | return s; |
414 | } |
415 | |
416 | /// Receive some data on a connected socket. |
417 | /** |
418 | * This function is used to receive data on the sequenced packet socket. The |
419 | * function call will block until data has been received successfully, or |
420 | * until an error occurs. |
421 | * |
422 | * @param buffers One or more buffers into which the data will be received. |
423 | * |
424 | * @param in_flags Flags specifying how the receive call is to be made. |
425 | * |
426 | * @param out_flags After the receive call completes, contains flags |
427 | * associated with the received data. For example, if the |
428 | * socket_base::message_end_of_record bit is set then the received data marks |
429 | * the end of a record. |
430 | * |
431 | * @param ec Set to indicate what error occurred, if any. |
432 | * |
433 | * @returns The number of bytes received. Returns 0 if an error occurred. |
434 | * |
435 | * @note The receive operation may not receive all of the requested number of |
436 | * bytes. Consider using the @ref read function if you need to ensure that the |
437 | * requested amount of data is read before the blocking operation completes. |
438 | */ |
439 | template <typename MutableBufferSequence> |
440 | std::size_t receive(const MutableBufferSequence& buffers, |
441 | socket_base::message_flags in_flags, |
442 | socket_base::message_flags& out_flags, boost::system::error_code& ec) |
443 | { |
444 | return this->get_service().receive(this->get_implementation(), |
445 | buffers, in_flags, out_flags, ec); |
446 | } |
447 | |
448 | /// Start an asynchronous receive. |
449 | /** |
450 | * This function is used to asynchronously receive data from the sequenced |
451 | * packet socket. The function call always returns immediately. |
452 | * |
453 | * @param buffers One or more buffers into which the data will be received. |
454 | * Although the buffers object may be copied as necessary, ownership of the |
455 | * underlying memory blocks is retained by the caller, which must guarantee |
456 | * that they remain valid until the handler is called. |
457 | * |
458 | * @param out_flags Once the asynchronous operation completes, contains flags |
459 | * associated with the received data. For example, if the |
460 | * socket_base::message_end_of_record bit is set then the received data marks |
461 | * the end of a record. The caller must guarantee that the referenced |
462 | * variable remains valid until the handler is called. |
463 | * |
464 | * @param handler The handler to be called when the receive operation |
465 | * completes. Copies will be made of the handler as required. The function |
466 | * signature of the handler must be: |
467 | * @code void handler( |
468 | * const boost::system::error_code& error, // Result of operation. |
469 | * std::size_t bytes_transferred // Number of bytes received. |
470 | * ); @endcode |
471 | * Regardless of whether the asynchronous operation completes immediately or |
472 | * not, the handler will not be invoked from within this function. Invocation |
473 | * of the handler will be performed in a manner equivalent to using |
474 | * boost::asio::io_service::post(). |
475 | * |
476 | * @par Example |
477 | * To receive into a single data buffer use the @ref buffer function as |
478 | * follows: |
479 | * @code |
480 | * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler); |
481 | * @endcode |
482 | * See the @ref buffer documentation for information on receiving into |
483 | * multiple buffers in one go, and how to use it with arrays, boost::array or |
484 | * std::vector. |
485 | */ |
486 | template <typename MutableBufferSequence, typename ReadHandler> |
487 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, |
488 | void (boost::system::error_code, std::size_t)) |
489 | async_receive(const MutableBufferSequence& buffers, |
490 | socket_base::message_flags& out_flags, |
491 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler) |
492 | { |
493 | // If you get an error on the following line it means that your handler does |
494 | // not meet the documented type requirements for a ReadHandler. |
495 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; |
496 | |
497 | return this->get_service().async_receive( |
498 | this->get_implementation(), buffers, 0, out_flags, |
499 | BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); |
500 | } |
501 | |
502 | /// Start an asynchronous receive. |
503 | /** |
504 | * This function is used to asynchronously receive data from the sequenced |
505 | * data socket. The function call always returns immediately. |
506 | * |
507 | * @param buffers One or more buffers into which the data will be received. |
508 | * Although the buffers object may be copied as necessary, ownership of the |
509 | * underlying memory blocks is retained by the caller, which must guarantee |
510 | * that they remain valid until the handler is called. |
511 | * |
512 | * @param in_flags Flags specifying how the receive call is to be made. |
513 | * |
514 | * @param out_flags Once the asynchronous operation completes, contains flags |
515 | * associated with the received data. For example, if the |
516 | * socket_base::message_end_of_record bit is set then the received data marks |
517 | * the end of a record. The caller must guarantee that the referenced |
518 | * variable remains valid until the handler is called. |
519 | * |
520 | * @param handler The handler to be called when the receive operation |
521 | * completes. Copies will be made of the handler as required. The function |
522 | * signature of the handler must be: |
523 | * @code void handler( |
524 | * const boost::system::error_code& error, // Result of operation. |
525 | * std::size_t bytes_transferred // Number of bytes received. |
526 | * ); @endcode |
527 | * Regardless of whether the asynchronous operation completes immediately or |
528 | * not, the handler will not be invoked from within this function. Invocation |
529 | * of the handler will be performed in a manner equivalent to using |
530 | * boost::asio::io_service::post(). |
531 | * |
532 | * @par Example |
533 | * To receive into a single data buffer use the @ref buffer function as |
534 | * follows: |
535 | * @code |
536 | * socket.async_receive( |
537 | * boost::asio::buffer(data, size), |
538 | * 0, out_flags, handler); |
539 | * @endcode |
540 | * See the @ref buffer documentation for information on receiving into |
541 | * multiple buffers in one go, and how to use it with arrays, boost::array or |
542 | * std::vector. |
543 | */ |
544 | template <typename MutableBufferSequence, typename ReadHandler> |
545 | BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, |
546 | void (boost::system::error_code, std::size_t)) |
547 | async_receive(const MutableBufferSequence& buffers, |
548 | socket_base::message_flags in_flags, |
549 | socket_base::message_flags& out_flags, |
550 | BOOST_ASIO_MOVE_ARG(ReadHandler) handler) |
551 | { |
552 | // If you get an error on the following line it means that your handler does |
553 | // not meet the documented type requirements for a ReadHandler. |
554 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; |
555 | |
556 | return this->get_service().async_receive( |
557 | this->get_implementation(), buffers, in_flags, out_flags, |
558 | BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); |
559 | } |
560 | }; |
561 | |
562 | } // namespace asio |
563 | } // namespace boost |
564 | |
565 | #include <boost/asio/detail/pop_options.hpp> |
566 | |
567 | #endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP |
568 | |