fastdo  0.6.16
eiennet_socket.hpp
浏览该文件的文档.
1 #ifndef __SOCKET_HPP__
2 #define __SOCKET_HPP__
3 
4 namespace eiennet
5 {
6 //#define SOCKET_EXCEPTION_USE // 错误机制是使用错误异常机制,还是使用传统返回值模式
7 
10 {
11 public:
12  SocketLib();
13  ~SocketLib();
14 
15 private:
18 };
19 
21 class SocketError : public winux::Error
22 {
23 public:
24  SocketError( int errType, winux::AnsiString const & errStr ) : winux::Error( errType, errStr ) { }
25 };
26 
27 class EndPoint;
28 
33 {
34 public:
35  // classes and types ------------------------------------------------------------------
36 
38  enum AddrFamily {
39  afUnspec = 0,
40  afLocal = 1,
41  afUnix = afLocal,
42  afFile = afLocal,
43  afInet = 2,
44  afAx25 = 3,
45  afIpx = 4,
46  afAppletalk = 5,
47  afNetrom = 6,
48  afBridge = 7,
49  afAtmpvc = 8,
50  afX25 = 9,
51  afInet6 = 10,
52  afRose = 11,
53  afDecnet = 12,
54  afNetbeui = 13,
55  afSecurity = 14,
56  afKey = 15,
57  afNetlink = 16,
58  afRoute = afNetlink,
59  afPacket = 17,
60  afAsh = 18,
61  afEconet = 19,
62  afAtmsvc = 20,
63  afRds = 21,
64  afSna = 22,
65  afIrda = 23,
66  afPppox = 24,
67  afWanpipe = 25,
68  afLlc = 26,
69  afUnknown27 = 27,
70  afUnknown28 = 28,
71  afCan = 29,
72  afTipc = 30,
73  afBluetooth = 31,
74  afIucv = 32,
75  afRxrpc = 33,
76  afIsdn = 34,
77  afPhonet = 35,
78  afIeee802154 = 36,
79  afMax = 37
80  };
81 
83  enum SockType {
91  sockPacket,
94  /* Flags to be ORed into the type parameter of socket and socketpair and used for the flags parameter of paccept. */
95 
97  sockNonblock
98  };
99 
101  enum Protocol {
102  protoUnspec = 0, protoIp = 0,
105  protoIpip, protoIpv4 = protoIpip,
126  protoMax
127  };
128 
129 public:
130  // static members ---------------------------------------------------------------------
131  // send/recv's message flags
132  static int const MsgDefault;
133 #if defined(_MSC_VER) || defined(WIN32)
134  static int const MsgOob;
135  static int const MsgPeek;
136  static int const MsgDontRoute;
137  static int const MsgWaitAll;
138  static int const MsgPartial;
139  static int const MsgInterrupt;
140  static int const MsgMaxIovLen;
141 #else
142  static int const MsgOob;
143  static int const MsgPeek;
144  static int const MsgDontRoute;
145 # ifdef __USE_GNU
146  /* DECnet uses a different name. */
147  static int const MsgTryHard;
148 # endif
149  static int const MsgCTrunc;
150  static int const MsgProxy;
151  static int const MsgTrunc;
152  static int const MsgDontWait;
153  static int const MsgEor;
154  static int const MsgWaitAll;
155  static int const MsgFin;
156  static int const MsgSyn;
157  static int const MsgConfirm;
158  static int const MsgRst;
159  static int const MsgErrQueue;
160  static int const MsgNoSignal;
161  static int const MsgMore;
162  static int const MsgWaitForOne;
163  static int const MsgCMsgCloexec;
164 
165 #endif
166  // shutdown's how flags
167  static int const SdReceive;
168  static int const SdSend;
169  static int const SdBoth;
170 
171  typedef std::function< void ( size_t hadBytes, void * param ) > FunctionSuccessCallback;
172 public:
173  // constructor/destructor -------------------------------------------------------------
174 
179  explicit Socket( int sock = -1, bool isNewSock = false );
180 
182  Socket( AddrFamily af, SockType sockType, Protocol proto );
183 
184 // #ifndef MOVE_SEMANTICS_DISABLED
185 // /** \brief 移动构造函数 */
186 // Socket( Socket && other );
187 // /** \brief 移动赋值操作 */
188 // Socket & operator = ( Socket && other );
189 // #endif
190 
191  virtual ~Socket();
192 
193 public:
194  // methods ----------------------------------------------------------------------------
196  AddrFamily getAddrFamily() const;
198  void setAddrFamily( AddrFamily af );
199 
201  SockType getSockType() const;
203  void setSockType( SockType sockType );
204 
206  Protocol getProtocol() const;
208  void setProtocol( Protocol proto );
209 
211  void getParams( AddrFamily * af, SockType * sockType, Protocol * proto );
213  void setParams( AddrFamily af, SockType sockType, Protocol proto );
214 
216  bool create( AddrFamily af, SockType sockType, Protocol proto );
218  bool create();
219 
220 protected:
224  bool _tryCreate( AddrFamily af, bool hasAf, SockType sockType, bool hasSockType, Protocol proto, bool hasProto );
225 
226 public:
228  int close();
229 
233  int shutdown( int how = SdSend );
234 
236  int send( void const * data, size_t size, int msgFlags = MsgDefault );
238  int send( winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->send( data.c_str(), data.size(), msgFlags ); }
240  int send( winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->send( data.getBuf(), data.getSize(), msgFlags ); }
241 
245  bool sendUntil( size_t targetSize, void const * data, int msgFlags = MsgDefault );
249  bool sendUntil( winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->sendUntil( data.size(), data.c_str(), msgFlags ); }
253  bool sendUntil( winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->sendUntil( data.getSize(), data.getBuf(), msgFlags ); }
254 
263  int sendWaitUntil(
264  size_t targetSize,
265  void const * data,
266  size_t * hadSent,
267  double sec,
268  int * rcWait,
269  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
270  void * param = nullptr,
271  int msgFlags = MsgDefault
272  );
273 
275  winux::AnsiString const & data,
276  size_t * hadSent,
277  double sec,
278  int * rcWait,
279  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
280  void * param = nullptr,
281  int msgFlags = MsgDefault
282  ) { return this->sendWaitUntil( data.size(), data.c_str(), hadSent, sec, rcWait, std::move(eachSuccessCallback), param, msgFlags ); }
283 
285  winux::Buffer const & data,
286  size_t * hadSent,
287  double sec,
288  int * rcWait,
289  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
290  void * param = nullptr,
291  int msgFlags = MsgDefault
292  ) { return this->sendWaitUntil( data.getSize(), data.getBuf(), hadSent, sec, rcWait, std::move(eachSuccessCallback), param, msgFlags ); }
293 
295  template < typename _PodType >
296  bool sendUntilType( _PodType const & v, size_t size = sizeof(_PodType), int msgFlags = MsgDefault ) { return this->sendUntil( size, &v, msgFlags ); }
297 
299  int recv( void * buf, size_t size, int msgFlags = MsgDefault );
300 
307  winux::Buffer recv( size_t size, int msgFlags = MsgDefault );
308 
312  bool recvUntilTarget( winux::AnsiString const & target, winux::GrowBuffer * data, winux::GrowBuffer * extraData, int msgFlags = MsgDefault );
313 
323  int recvWaitUntilTarget(
324  winux::AnsiString const & target,
325  winux::GrowBuffer * data,
326  winux::GrowBuffer * extraData,
327  size_t * hadRead,
328  size_t * startpos,
329  size_t * pos,
330  double sec,
331  int * rcWait,
332  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
333  void * param = nullptr,
334  int msgFlags = MsgDefault
335  );
336 
341  bool recvUntilSize( size_t targetSize, winux::GrowBuffer * data, int msgFlags = MsgDefault );
342 
352  int recvWaitUntilSize(
353  size_t targetSize,
354  winux::GrowBuffer * data,
355  size_t * hadRead,
356  double sec,
357  int * rcWait,
358  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
359  void * param = nullptr,
360  int msgFlags = MsgDefault
361  );
362 
364  template < typename _PodType >
365  bool recvUntilType( _PodType * v, size_t size = sizeof(_PodType), int msgFlags = MsgDefault )
366  {
367  winux::GrowBuffer data;
368  data.setBuf( v, 0, size, true );
369  return this->recvUntilSize( size, &data, msgFlags );
370  }
371 
378  winux::Buffer recvAvail( int msgFlags = MsgDefault );
379 
388  winux::Buffer recvWaitAvail( double sec, int * rcWait, int msgFlags = MsgDefault );
389 
391  int sendTo( EndPoint const & ep, void const * data, size_t size, int msgFlags = MsgDefault );
393  int sendTo( EndPoint const & ep, winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->sendTo( ep, data.c_str(), data.size(), msgFlags ); }
395  int sendTo( EndPoint const & ep, winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->sendTo( ep, data.getBuf(), data.getSize(), msgFlags ); }
396 
400  int recvFrom( EndPoint * ep, void * buf, size_t size, int msgFlags = MsgDefault );
408  winux::Buffer recvFrom( EndPoint * ep, size_t size, int msgFlags = MsgDefault );
409 
411  bool connect( EndPoint const & ep );
412 
414  bool bind( EndPoint const & ep );
415 
417  bool listen( int backlog );
418 
422  bool accept( int * sock, EndPoint * ep = NULL );
423 
426  {
427  int sock;
428  return this->accept( &sock, ep ) ? winux::SharedPointer<Socket>( new Socket( sock, true ) ) : winux::SharedPointer<Socket>();
429  }
430 
431  // socket's options -------------------------------------------------------------------
432 
434  int getRecvBufSize() const;
436  bool setRecvBufSize( int optval );
437 
439  int getSendBufSize() const;
441  bool setSendBufSize( int optval );
442 
444  winux::uint32 getRecvTimeout() const;
446  bool setRecvTimeout( winux::uint32 optval );
447 
449  winux::uint32 getSendTimeout() const;
453  bool setSendTimeout( winux::uint32 optval );
454 
456  bool getReUseAddr() const;
458  bool setReUseAddr( bool optval );
459 
461  bool getBroadcast() const;
463  bool setBroadcast( bool optval );
464 
466  bool getIpv6Only() const;
468  bool setIpv6Only( bool optval );
469 
471  int getError() const;
472 
474  SockType getType() const;
475 
479  bool isListening() const;
480 
481  // ioctls -----------------------------------------------------------------------------
482 
484  int getAvailable() const;
485 
487  bool setBlocking( bool blocking );
488 
489  // attributes -------------------------------------------------------------------------
490 
492  int get() const;
493 
495  operator bool() const { return this->get() > -1; }
496 
497  // static -----------------------------------------------------------------------------
498 
500  static int ErrNo();
501 
502 protected:
503  // 延迟创建socket使用参数
504  AddrFamily _addrFamily; // 地址族
505  SockType _sockType; // 套接字类型
506  Protocol _protocol; // 协议
507 
508  // 延迟设置socket属性
509  winux::uint32 _attrSendTimeout; // 发送超时(ms)
510  winux::uint32 _attrRecvTimeout; // 接收超时(ms)
511  int _attrSendBufSize; // 发送缓冲区大小
512  int _attrRecvBufSize; // 接收缓冲区大小
513  bool _attrBlocking; // 是否阻塞
514  bool _attrBroadcast; // 是否启用广播
515  bool _attrReUseAddr; // 是否开启了地址重用
516  bool _attrIpv6Only; // IPV6套接字只开启IPV6功能
517 
518  // 属性种类
520  {
521  attrNone, // 无意义
522  attrBlocking, // 是否阻塞
523  attrBroadcast, // 是否启用广播
524  attrReUseAddr, // 是否开启了地址重用
525  attrSendTimeout, // 发送超时(ms)
526  attrRecvTimeout, // 接收超时(ms)
527  attrSendBufSize, // 发送缓冲区大小
528  attrRecvBufSize, // 接收缓冲区大小
529  attrIpv6Only, // IPV6套接字只开启IPV6功能
530  };
531  std::vector<AttrCategory> _attrExecSets; // 执行属性设置的操作集
532 
533  // socket资源管理
534  int _sock; // socket描述符
535  bool _isNewSock; // 指示是否为新建socket。如果为true,则会在Socket对象析构时自动关闭sock
536 
537  // 初始化全部成员
539  {
540  this->_addrFamily = afUnspec;
541  this->_sockType = sockUnknown;
542  this->_protocol = protoUnspec;
543 
544  _attrBlocking = true;
545  _attrBroadcast = false;
546  _attrReUseAddr = false;
547  _attrSendTimeout = 0U;
548  _attrRecvTimeout = 0U;
549  _attrSendBufSize = 0;
550  _attrRecvBufSize = 0;
551  #if defined(OS_WIN)
552  _attrIpv6Only = true; // IPV6套接字只开启IPV6功能
553  #else
554  _attrIpv6Only = false; // IPV6套接字只开启IPV6功能
555  #endif
556 
557  this->_resetManaged();
558  }
559 
560  // 重置socket资源管理相关变量
562  {
563  this->_sock = -1;
564  this->_isNewSock = false;
565  }
566 
568 };
569 
572 {
573 public:
574  EndPoint() { }
575  virtual ~EndPoint() { }
576 
578  virtual void * get() const = 0;
580  template < typename _Ty >
581  _Ty * get() const { return reinterpret_cast<_Ty *>( this->get() ); }
583  virtual winux::uint & size() const = 0;
585  virtual winux::String toString() const = 0;
587  virtual EndPoint * clone() const = 0;
589  virtual Socket::AddrFamily getAddrFamily() const = 0;
590 };
591 
594 {
595  enum {
596  RetryCount = 10
597  };
598 
601  size_t startpos;
602  size_t pos;
603  size_t hadBytes;
604  size_t targetBytes;
605  size_t retryCount;
606 
608  {
609  this->resetStatus();
610  }
611 
613  void resetData()
614  {
615  this->data.free();
616  this->extraData.free();
617  }
618 
620  void resetStatus()
621  {
622  this->startpos = 0;
623  this->pos = winux::npos;
624  this->hadBytes = 0;
625  this->targetBytes = 0;
626  this->retryCount = 0;
627  }
628 
630  void append( winux::Buffer const & data )
631  {
632  this->data.append(data);
633  }
634 
638  template < typename _IndexType >
639  bool find( winux::AnsiString const & target, std::vector<_IndexType> const & targetNextVal )
640  {
641  // 如果接收到的数据小于标记长度 或者 搜不到标记 则退出
642  if ( this->data.getSize() - this->startpos < target.size() || ( this->pos = winux::_Templ_KmpMatchEx( this->data.getBuf<char>(), this->data.getSize(), target.c_str(), target.size(), this->startpos, targetNextVal ) ) == winux::npos )
643  {
644  if ( this->data.getSize() >= target.size() ) this->startpos = this->data.getSize() - target.size() + 1; // 计算下次搜索起始
645  return false;
646  }
647  else
648  {
649  return true;
650  }
651  }
652 
656  winux::Buffer adjust( size_t actualDataSize )
657  {
658  this->extraData._setSize(0);
659  // 额外收到的数据
660  this->extraData.append( this->data.getBuf<char>() + actualDataSize, this->data.getSize() - actualDataSize );
661  this->data._setSize(actualDataSize);
662 
663  winux::Buffer actualData(this->data);
664 
665  // 额外的数据移入主数据中
666  this->data = std::move(extraData);
667  // 重置数据收发场景
668  this->resetStatus();
669 
670  return actualData;
671  }
672 };
673 
675 
676 class EIENNET_DLL SocketStreamBuf : public std::streambuf
677 {
678 public:
680  eiennet::Socket * sock,
681  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out,
682  size_t inputBufSize = (size_t)-1,
683  size_t outputBufSize = (size_t)-1
684  );
685 
686  virtual ~SocketStreamBuf();
687 
688  Socket * getSocket() const { return _sock; }
689  // input buffer begin -----------------------------------------------------------------------
690 protected:
691  virtual int_type underflow();
692  // input buffer end -----------------------------------------------------------------------
693 
694  // output buffer begin -----------------------------------------------------------------------
695 protected:
696  virtual int_type overflow( int_type c );
697  virtual int sync();
698  int _flush();
699  // output buffer end -----------------------------------------------------------------------
700 
701 
702 private:
703  eiennet::Socket * _sock;
704  winux::Buffer _inputBuf;
705  winux::Buffer _outputBuf;
706 
708 };
709 
711 class EIENNET_DLL SocketStreamOut : public std::ostream
712 {
713 private:
714  SocketStreamBuf * _sockBuf;
715 public:
716  SocketStreamOut( SocketStreamBuf * sockBuf ) : std::ostream(sockBuf), _sockBuf(sockBuf) { }
717  SocketStreamOut( SocketStreamBuf & sockBuf ) : std::ostream(&sockBuf), _sockBuf(&sockBuf) { }
718  SocketStreamOut( winux::SimplePointer<SocketStreamBuf> & sockBuf ) : std::ostream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
719  SocketStreamOut( winux::SharedPointer<SocketStreamBuf> & sockBuf ) : std::ostream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
720 
722  SocketStreamOut & writeAndFlush( winux::Buffer const & data );
723 };
724 
726 class EIENNET_DLL SocketStreamIn : public std::istream
727 {
728 private:
729  SocketStreamBuf * _sockBuf;
730 public:
731  SocketStreamIn( SocketStreamBuf * sockBuf ) : std::istream(sockBuf), _sockBuf(sockBuf) { }
732  SocketStreamIn( SocketStreamBuf & sockBuf ) : std::istream(&sockBuf), _sockBuf(&sockBuf) { }
733  SocketStreamIn( winux::SimplePointer<SocketStreamBuf> & sockBuf ) : std::istream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
734  SocketStreamIn( winux::SharedPointer<SocketStreamBuf> & sockBuf ) : std::istream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
735 
737  std::streamsize getAvailable() const;
739  SocketStreamIn & readAvail( winux::Buffer * data );
741  SocketStreamIn & read( winux::Buffer * data, size_t size );
743  std::streamsize waitAvail( double sec );
744 };
745 
747 
748 namespace ip
749 {
752 {
753 public:
757  EndPoint( winux::Mixed const & ipAndPort );
761  EndPoint( winux::String const & ipAddr, winux::ushort port );
762 
763  EndPoint( EndPoint const & other );
764  EndPoint & operator = ( EndPoint const & other );
765 
766 #ifndef MOVE_SEMANTICS_DISABLED
767  EndPoint( EndPoint && other );
768  EndPoint & operator = ( EndPoint && other );
769 #endif
770 
771  virtual ~EndPoint();
772 
774  void init( Socket::AddrFamily af = Socket::afUnspec );
776  void init( winux::Mixed const & ipAndPort );
780  void init( winux::String const & ipAddr, winux::ushort port );
781 
783  virtual void * get() const override;
785  template < typename _Ty >
786  _Ty * get() const { return reinterpret_cast<_Ty *>( this->get() ); }
788  virtual winux::uint & size() const override;
790  virtual winux::String toString() const override;
792  virtual eiennet::EndPoint * clone() const override;
794  virtual Socket::AddrFamily getAddrFamily() const override;
795 
797  operator winux::Mixed() const;
798 
800  winux::String getIp() const;
802  winux::ushort getPort() const;
803 
804 private:
806 };
807 
810 {
811 public:
812  typedef std::vector<ip::EndPoint> EndPointArray;
814  Resolver( winux::Mixed const & hostAndPort );
816  Resolver( winux::String const & hostName, winux::ushort port );
817 
818  EndPointArray::iterator begin() { return _epArr.begin(); }
819  EndPointArray::const_iterator begin() const { return _epArr.begin(); }
820  EndPointArray::iterator end() { return _epArr.end(); }
821  EndPointArray::const_iterator end() const { return _epArr.end(); }
822 
824  size_t count() const { return _epArr.size(); }
826  winux::String const & getHostname() const { return _hostName; }
828  winux::ushort getPort() const { return _port; }
829 
830  EndPointArray::value_type const & operator [] ( int i ) const { return _epArr[i]; }
831  EndPointArray::value_type & operator [] ( int i ) { return _epArr[i]; }
832 
833  EndPointArray & getArr() { return _epArr; }
834  EndPointArray const & getArr() const { return _epArr; }
835 
837  virtual winux::String toString() const;
839  operator winux::Mixed() const;
840 
841 private:
842  size_t _resolve( winux::String const & hostName, winux::ushort port );
843  winux::String _hostName;
844  winux::ushort _port;
845  EndPointArray _epArr;
846 };
847 
848 namespace tcp
849 {
852 {
853 public:
855 
860  explicit Socket( int sock, bool isNewSock = false ) : BaseClass( sock, isNewSock ) { }
861 
863  Socket() : BaseClass( BaseClass::afInet, BaseClass::sockStream, BaseClass::protoUnspec ) { }
864 
867  {
868  int sock;
869  return BaseClass::accept( &sock, ep ) ? winux::SharedPointer<Socket>( new Socket( sock, true ) ) : winux::SharedPointer<Socket>();
870  }
871 };
872 
874 EIENNET_FUNC_DECL(int) ConnectAttempt( Socket * sock, EndPoint const & ep, winux::uint32 timeoutMs );
875 
882 EIENNET_FUNC_DECL(int) ConnectAttempt( Socket * sock, Resolver const & resolver, winux::uint32 perCnnTimeoutMs );
883 
884 } // namespace tcp
885 
886 namespace udp
887 {
890 {
891 public:
893 
898  explicit Socket( int sock, bool isNewSock = false ) : BaseClass( sock, isNewSock ) { }
899 
901  Socket() : BaseClass( BaseClass::afInet, BaseClass::sockDatagram, BaseClass::protoUnspec ) { }
902 };
903 
904 } // namespace udp
905 
906 } // namespace ip
907 
909 
911 namespace io
912 {
913 
916 {
917 public:
918  SelectRead();
919  SelectRead( Socket const & sock );
920  SelectRead( Socket const * sock );
921  SelectRead( int fd );
922  SelectRead( winux::Mixed const & fds );
923  ~SelectRead();
924 
925  SelectRead & setReadSock( Socket const & sock ) { return setReadFd( sock.get() ); }
926  SelectRead & setReadSock( Socket const * sock ) { return setReadFd( sock->get() ); }
927  SelectRead & setReadFd( int fd );
928  SelectRead & delReadFd( int fd );
929  SelectRead & setReadFds( winux::Mixed const & fds );
930  SelectRead & clear();
931  int hasReadSock( Socket const & sock ) const { return hasReadFd( sock.get() ); }
932  int hasReadFd( int fd ) const;
933 
938  int wait( double sec = -1 );
939 
940 protected:
943 };
944 
947 {
948 public:
949  SelectWrite();
950  SelectWrite( Socket const & sock );
951  SelectWrite( Socket const * sock );
952  SelectWrite( int fd );
953  SelectWrite( winux::Mixed const & fds );
954  ~SelectWrite();
955 
956  SelectWrite & setWriteSock( Socket const & sock ) { return setWriteFd( sock.get() ); }
957  SelectWrite & setWriteSock( Socket const * sock ) { return setWriteFd( sock->get() ); }
958  SelectWrite & setWriteFd( int fd );
959  SelectWrite & delWriteFd( int fd );
960  SelectWrite & setWriteFds( winux::Mixed const & fds );
961  SelectWrite & clear();
962  int hasWriteSock( Socket const & sock ) const { return hasWriteFd( sock.get() ); }
963  int hasWriteFd( int fd ) const;
964 
969  int wait( double sec = -1 );
970 
971 protected:
974 };
975 
978 {
979 public:
980  SelectExcept();
981  SelectExcept( Socket const & sock );
982  SelectExcept( Socket const * sock );
983  SelectExcept( int fd );
984  SelectExcept( winux::Mixed const & fds );
985  ~SelectExcept();
986 
987  SelectExcept & setExceptSock( Socket const & sock ) { return setExceptFd( sock.get() ); }
988  SelectExcept & setExceptSock( Socket const * sock ) { return setExceptFd( sock->get() ); }
989  SelectExcept & setExceptFd( int fd );
990  SelectExcept & delExceptFd( int fd );
991  SelectExcept & setExceptFds( winux::Mixed const & fds );
992  SelectExcept & clear();
993  int hasExceptSock( Socket const & sock ) const { return hasExceptFd( sock.get() ); }
994  int hasExceptFd( int fd ) const;
995 
1000  int wait( double sec = -1 );
1001 
1002 protected:
1005 };
1006 
1008 class EIENNET_DLL Select : public SelectRead, public SelectWrite, public SelectExcept
1009 {
1010 public:
1012  Select() { }
1013 
1014  Select & setReadSock( Socket const & sock ) { SelectRead::setReadSock(sock); return *this; }
1015  Select & setReadFd( int fd ) { SelectRead::setReadFd(fd); return *this; }
1016  Select & delReadFd( int fd ) { SelectRead::delReadFd(fd); return *this; }
1017  Select & setReadFds( winux::Mixed const & fds ) { SelectRead::setReadFds(fds); return *this; }
1018  Select & clearReadFds() { SelectRead::clear(); return *this; }
1019 
1020  Select & setWriteSock( Socket const & sock ) { SelectWrite::setWriteSock(sock); return *this; }
1021  Select & setWriteFd( int fd ) { SelectWrite::setWriteFd(fd); return *this; }
1022  Select & delWriteFd( int fd ) { SelectWrite::delWriteFd(fd); return *this; }
1023  Select & setWriteFds( winux::Mixed const & fds ) { SelectWrite::setWriteFds(fds); return *this; }
1024  Select & clearWriteFds() { SelectWrite::clear(); return *this; }
1025 
1026  Select & setExceptSock( Socket const & sock ) { SelectExcept::setExceptSock(sock); return *this; }
1027  Select & setExceptFd( int fd ) { SelectExcept::setExceptFd(fd); return *this; }
1028  Select & delExceptFd( int fd ) { SelectExcept::delExceptFd(fd); return *this; }
1029  Select & setExceptFds( winux::Mixed const & fds ) { SelectExcept::setExceptFds(fds); return *this; }
1030  Select & clearExceptFds() { SelectExcept::clear(); return *this; }
1031 
1033  Select & clear() { SelectRead::clear(); SelectWrite::clear(); SelectExcept::clear(); return *this; }
1034 
1039  int wait( double sec = -1 );
1040 };
1041 
1042 } // namespace io
1043 
1045 class Server;
1048 {
1052 };
1053 
1056 {
1057 public:
1058  ClientCtx( Server * server, winux::uint64 clientId, winux::String const & clientEpStr, winux::SharedPointer<eiennet::ip::tcp::Socket> clientSockPtr );
1059 
1060  virtual ~ClientCtx();
1061 
1063  winux::String getStamp() const;
1064 
1069 
1070  bool canRemove;
1072 
1073 private:
1075 };
1076 
1084 {
1085 public:
1087  Server();
1088 
1098  Server( bool autoReadData, ip::EndPoint const & ep, int threadCount = 4, int backlog = 0, double serverWait = 0.002, double verboseInterval = 0.01, VerboseOutputType verbose = votConsole );
1099 
1100  virtual ~Server();
1101 
1111  bool startup( bool autoReadData, ip::EndPoint const & ep, int threadCount = 4, int backlog = 0, double serverWait = 0.002, double verboseInterval = 0.01, VerboseOutputType verbose = votConsole );
1112 
1114  virtual int run( void * runParam );
1115 
1117  void stop( bool b = true );
1118 
1120  size_t getClientsCount() const;
1121 
1123  void removeClient( winux::uint64 clientId );
1124 
1125 protected:
1127  virtual bool _canAddClient( ClientCtx * clientCtx );
1129  bool _addClient( ip::EndPoint const & clientEp, winux::SharedPointer<ip::tcp::Socket> clientSockPtr, winux::SharedPointer<ClientCtx> ** ppClientCtxPtr );
1131  template < typename _Fx, typename... _ArgType >
1132  void _postTask( winux::SharedPointer<ClientCtx> clientCtxPtr, _Fx fn, _ArgType&& ... arg )
1133  {
1134  auto routine = MakeSimple( NewRunable( fn, std::forward<_ArgType>(arg)... ) );
1135  // 标记为处理事件中
1136  clientCtxPtr->processingEvent = true;
1137  this->_pool.task( [routine, clientCtxPtr] () {
1138  routine->invoke();
1139  // 事件处理完毕,可再次select()事件
1140  clientCtxPtr->processingEvent = false;
1141  } ).post();
1142  }
1143 
1144  // 客户数据通知
1150  ClientDataNotify,
1151  ( winux::SharedPointer<ClientCtx> clientCtxPtr, size_t readableSize ),
1152  ( clientCtxPtr, readableSize )
1153  )
1154 
1155  // 客户数据到达
1161  ClientDataArrived,
1162  ( winux::SharedPointer<ClientCtx> clientCtxPtr, winux::Buffer & data ),
1163  ( clientCtxPtr, data )
1164  )
1165 
1166  // 当创建客户连接对象
1173  ClientCtx *,
1174  CreateClient,
1175  ( winux::uint64 clientId, winux::String const & clientEpStr, winux::SharedPointer<ip::tcp::Socket> clientSockPtr )
1176  );
1177 
1178 protected:
1179  winux::ThreadPool _pool;
1180  winux::RecursiveMutex _mtxServer;
1181  ip::tcp::Socket _servSockA;
1182  ip::tcp::Socket _servSockB;
1183  std::map< winux::uint64, winux::SharedPointer<ClientCtx> > _clients;
1184 
1185  winux::uint64 _cumulativeClientId;
1186  bool _stop;
1187  bool _servSockAIsListening;
1188  bool _servSockBIsListening;
1189  bool _isAutoReadData;
1190 
1191  double _serverWait;
1192  double _verboseInterval;
1194 
1195  friend class ClientCtx;
1196 
1198 };
1199 
1201 
1203 namespace old_v1
1204 {
1206 class ClientCtx
1207 {
1208 public:
1210  clientId(clientId),
1211  clientEpStr(clientEpStr),
1212  clientSockPtr(clientSockPtr)
1213  {
1214  }
1215 
1216  virtual ~ClientCtx()
1217  {
1218  }
1219 
1223 
1224 private:
1225  DISABLE_OBJECT_COPY(ClientCtx)
1226 };
1227 
1233 template < class _ClientCtxClass >
1234 class Server
1235 {
1236 public:
1238  using StartupHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr ) >;
1239 
1245  Server( ip::EndPoint const & ep, int threadCount = 4, int backlog = 0 ) :
1246  _cumulativeClientId(0),
1247  _stop(false),
1248  _pool(threadCount),
1249  _mtxServer(true)
1250  {
1251  _servSock.setReUseAddr(true);
1252  _stop = !( _servSock.eiennet::Socket::bind(ep) && _servSock.listen(backlog) );
1253  }
1254 
1255  virtual ~Server()
1256  {
1257  }
1258 
1259  virtual int run()
1260  {
1261  io::Select sel;
1262  while ( !_stop )
1263  {
1264  sel.clear();
1265  sel.setExceptSock(_servSock);
1266  sel.setReadSock(_servSock);
1267  int rc = sel.wait(0.01);
1268  if ( rc > 0 )
1269  {
1270  if ( sel.hasReadSock(_servSock) )
1271  {
1272  ip::EndPoint clientEp;
1273  auto clientSockPtr = _servSock.accept(&clientEp);
1274  if ( clientSockPtr )
1275  {
1276  auto & clientCtxPtr = this->_addClient( clientEp, clientSockPtr );
1277 
1278  // 进入该客户的业务逻辑
1279  this->onStartup(clientCtxPtr);
1280  }
1281  }
1282  else if ( sel.hasExceptSock(_servSock) )
1283  {
1284  _stop = true;
1285  }
1286  }
1287  }
1288 
1289  _pool.whenEmptyStopAndWait();
1290  return 0;
1291  }
1292 
1294  void stop( bool b = true ) { static_cast<volatile bool &>(_stop) = b; }
1295 
1296  size_t getClientsCount() const
1297  {
1298  winux::ScopeGuard guard( const_cast<winux::Mutex &>(_mtxServer) );
1299  return _clients.size();
1300  }
1301 
1303  {
1304  _startupHandler = handler;
1305  }
1306 
1307  void removeClient( winux::uint64 clientId )
1308  {
1309  winux::ScopeGuard guard(_mtxServer);
1310  _clients.erase(clientId);
1311  }
1312 
1313 protected:
1315  {
1316  ClientCtxSharedPointer * client;
1317  {
1318  winux::ScopeGuard guard(_mtxServer);
1319  ++_cumulativeClientId;
1320  client = &_clients[_cumulativeClientId];
1321  }
1322  client->attachNew( new _ClientCtxClass( _cumulativeClientId, clientEp.toString(), clientSockPtr ) );
1323  return *client;
1324  }
1325 
1326  winux::uint64 _cumulativeClientId; // 客户唯一标识
1327  bool _stop; // 是否停止
1328  winux::ThreadPool _pool; // 线程池
1329  winux::Mutex _mtxServer; // 互斥量保护服务器共享数据
1330  ip::tcp::Socket _servSock; // 服务器监听套接字
1331  std::map< winux::uint64, ClientCtxSharedPointer > _clients; // 客户表
1332 
1333  // 一个客户的业务逻辑开启
1334  virtual void onStartup( ClientCtxSharedPointer clientCtxPtr )
1335  {
1336  if ( this->_startupHandler ) this->_startupHandler(clientCtxPtr);
1337  }
1338  StartupHandlerFunction _startupHandler; // onStartup()事件处理
1339 
1340 private:
1341  DISABLE_OBJECT_COPY(Server)
1342 };
1343 
1344 } // namespace old_v1
1345 
1346 } // namespace eiennet
1347 
1348 
1349 
1350 #endif // __SOCKET_HPP__
XString< char > AnsiString
Definition: utilities.hpp:257
#define EIENNET_FUNC_DECL(ret)
SelectWrite & setWriteSock(Socket const *sock)
RunableT< _Fx, std::tuple< typename std::decay< _ArgType >::type... > > * NewRunable(_Fx fn, _ArgType &&...arg)
创建一个Runable对象
Definition: utilities.hpp:119
void stop(bool b=true)
是否停止服务运行
void append(void const *data, size_t size)
添加数据:C语言缓冲区
int hasExceptSock(Socket const &sock) const
winux::GrowBuffer extraData
额外收到的数据
SelectRead & setReadSock(Socket const &sock)
SelectWrite Io模型
SocketStreamIn(SocketStreamBuf *sockBuf)
void * getBuf() const
暴露缓冲区指针
Definition: utilities.hpp:993
Socket库初始化
基础客户场景类
Select & clear()
清空所有fds
SocketStreamOut(winux::SimplePointer< SocketStreamBuf > &sockBuf)
Select & setExceptFd(int fd)
int sendTo(EndPoint const &ep, winux::AnsiString const &data, int msgFlags=MsgDefault)
无连接模式发送数据到指定端点。返回已发送大小,出错返回-1。
int wait(double sec=-1)
等待相应的fd就绪。sec<1表示小于1秒的时间,sec<0表示无限等待。eg: sec=1.5表示等待1500ms ...
winux::SharedPointer< ip::tcp::Socket > clientSockPtr
static int const SdSend
SelectExcept & setExceptSock(Socket const *sock)
int sendWaitUntil(winux::Buffer const &data, size_t *hadSent, double sec, int *rcWait, FunctionSuccessCallback eachSuccessCallback=FunctionSuccessCallback(), void *param=nullptr, int msgFlags=MsgDefault)
winux::String const & getHostname() const
获取主机名
void resetData()
重置数据和额外数据为空
Select & setReadSock(Socket const &sock)
Select & setWriteFd(int fd)
EndPointArray & getArr()
EndPointArray::const_iterator end() const
不输出冗余信息
bool canRemove
是否标记为可以移除
bool processingEvent
是否事件处理中,保证同一个客户连接仅投递一个事件到线程池中
static int const MsgDefault
XString< tchar > String
Definition: utilities.hpp:261
Select Io模型
在日志查看器输出
int get() const
Windows:socket句柄,或Linux:socket描述符
void _postTask(winux::SharedPointer< ClientCtx > clientCtxPtr, _Fx fn, _ArgType &&...arg)
往线程池投递任务
size_t count() const
获取解析到的IP端点数
static int const MsgOob
STL namespace.
size_t pos
找到位置
EndPointArray::iterator begin()
Socket * getSocket() const
winux::ushort getPort() const
获取端口号
int sendTo(EndPoint const &ep, winux::Buffer const &data, int msgFlags=MsgDefault)
无连接模式发送数据到指定端点。返回已发送大小,出错返回-1。
端点基类(套接字地址对象基类)
SocketStreamIn(SocketStreamBuf &sockBuf)
Socket(int sock, bool isNewSock=false)
构造函数1,包装现有socket描述符
void free()
释放缓冲区
在控制台输出
SocketStreamIn(winux::SimplePointer< SocketStreamBuf > &sockBuf)
Server * server
服务器
SelectRead & setReadSock(Socket const *sock)
ClientCtx(winux::uint64 clientId, winux::String clientEpStr, winux::SharedPointer< ip::tcp::Socket > clientSockPtr)
int hasReadSock(Socket const &sock) const
winux::String clientEpStr
客户终端字符串
套接字输出流
size_t getSize() const
获取数据大小
Definition: utilities.hpp:1025
#define DISABLE_OBJECT_COPY(clsname)
Definition: utilities.hpp:85
Select & setWriteSock(Socket const &sock)
Select & delWriteFd(int fd)
static int const MsgDontRoute
Select & delExceptFd(int fd)
winux::uint64 _cumulativeClientId
winux::uint32 _attrRecvTimeout
互斥量
Definition: threads.hpp:349
winux::SharedPointer< Socket > accept(EndPoint *ep=NULL)
接受一个客户连接
bool recvUntilType(_PodType *v, size_t size=sizeof(_PodType), int msgFlags=MsgDefault)
接收一个Plain of Data类型的变量,若成功返回true,否则返回false。
void removeClient(winux::uint64 clientId)
winux::uint32 _attrSendTimeout
SocketStreamIn(winux::SharedPointer< SocketStreamBuf > &sockBuf)
SelectRead Io模型
std::function< void(size_t hadBytes, void *param) > FunctionSuccessCallback
Select & setReadFds(winux::Mixed const &fds)
Select & setExceptSock(Socket const &sock)
int ConnectAttempt(Socket *sock, Resolver const &resolver, winux::uint32 perCnnTimeoutMs)
阻塞模式Socket连接尝试,连接成功返回0,超时返回1,失败返回-1
int send(winux::Buffer const &data, int msgFlags=MsgDefault)
发送数据。返回已发送大小,出错返回-1。
static int const SdBoth
void attachNew(_Ty *p)
附加新指针,管理新对象
Definition: smartptr.hpp:951
作用域范围保护
Definition: system.hpp:217
winux::SharedPointer< Socket > accept(EndPoint *ep=NULL)
接受一个客户连接
套接字流缓冲区
size_t startpos
起始位置
static constexpr size_t const npos
非位置,值为-1。
Definition: utilities.hpp:285
引用计数共享指针
Definition: smartptr.hpp:456
void onStartupHandler(StartupHandlerFunction handler)
套接字基础类
Select & setReadFd(int fd)
缓冲区,表示内存中一块二进制数据(利用malloc/realloc进行内存分配)
Definition: utilities.hpp:906
size_t hadBytes
已接收/发送数据量
#define EIENNET_DLL
数据收发场景,存放数据收发过程中的一些变量
Socket(int sock, bool isNewSock=false)
构造函数1,包装现有socket描述符
virtual winux::String toString() const override
转换成"IP:port"的字符串形式
winux::Members< struct SelectExcept_Data > _self
size_t getClientsCount() const
EndPointArray::iterator end()
套接字错误
#define DEFINE_CUSTOM_EVENT_RETURN_EX(ret, evtname, paramtypes)
Definition: utilities.hpp:197
static int const MsgPartial
unsigned int uint
Definition: utilities.hpp:215
void _setSize(size_t dataSize)
设置数据大小,不能超过容量大小(不建议外部调用)
Definition: utilities.hpp:1039
SelectExcept & setExceptSock(Socket const &sock)
void setBuf(void const *buf, size_t size, size_t capacity, bool isPeek)
设置缓冲区,当isPeek为false时拷贝数据缓冲区
winux::Members< struct SelectWrite_Data > _self
int hasWriteSock(Socket const &sock) const
SockType
套接字类型
Select & setWriteFds(winux::Mixed const &fds)
基础服务器类
static size_t _Templ_KmpMatchEx(_ChTy const *str, size_t len, _ChTy const *substr, size_t sublen, size_t pos, std::vector< _IndexType > const &next)
KMP匹配算法:传入已经求好的next进行匹配
Definition: strings.hpp:669
std::map< winux::uint64, ClientCtxSharedPointer > _clients
winux::GrowBuffer data
数据
线程池,创建一组线程等待着从任务队列中获取任务执行
Definition: threadtask.hpp:159
SocketStreamOut(winux::SharedPointer< SocketStreamBuf > &sockBuf)
void append(winux::Buffer const &data)
添加数据到data
static int const MsgWaitAll
std::vector< AttrCategory > _attrExecSets
int sendWaitUntil(winux::AnsiString const &data, size_t *hadSent, double sec, int *rcWait, FunctionSuccessCallback eachSuccessCallback=FunctionSuccessCallback(), void *param=nullptr, int msgFlags=MsgDefault)
VerboseOutputType
冗余信息输出类型
virtual void onStartup(ClientCtxSharedPointer clientCtxPtr)
Select & delReadFd(int fd)
bool sendUntil(winux::Buffer const &data, int msgFlags=MsgDefault)
发送缓冲区,直到发送完该大小的缓冲区。
网络通信库
AddrFamily _addrFamily
AddrFamily
地址族
高效的可增长缓冲区,1.33倍冗余量
Definition: utilities.hpp:1103
static int const MsgInterrupt
套接字输入流
ClientCtxSharedPointer & _addClient(ip::EndPoint const &clientEp, winux::SharedPointer< ip::tcp::Socket > clientSockPtr)
SocketError(int errType, winux::AnsiString const &errStr)
#define DEFINE_CUSTOM_EVENT(evtname, paramtypes, calledparams)
Definition: utilities.hpp:182
bool find(winux::AnsiString const &target, std::vector< _IndexType > const &targetNextVal)
在data里查找target内容。startpos指定起始位置,pos接收搜索到的位置。
bool sendUntilType(_PodType const &v, size_t size=sizeof(_PodType), int msgFlags=MsgDefault)
发送一个Plain of Data类型的变量,若成功返回true,否则返回false。
size_t retryCount
已重试次数
主机名解析器(可以把域名解析为一个或多个IP端点)
virtual winux::uint & size() const =0
取得地址的数据大小,一般为内部地址结构体的大小
StartupHandlerFunction _startupHandler
std::vector< ip::EndPoint > EndPointArray
unsigned short ushort
Definition: utilities.hpp:218
混合体,能表示多种类型的值
Definition: utilities.hpp:1440
int send(winux::AnsiString const &data, int msgFlags=MsgDefault)
发送数据。返回已发送大小,出错返回-1。
简单指针
Definition: smartptr.hpp:302
std::function< void(ClientCtxSharedPointer clientCtxPtr) > StartupHandlerFunction
static int const MsgMaxIovLen
错误类
Definition: utilities.hpp:838
SimplePointer< _Ty > MakeSimple(_Ty *newObj)
创建一个SimplePointer来管理新对象资源
Definition: smartptr.hpp:1270
winux::Members< struct SelectRead_Data > _self
EndPointArray::const_iterator begin() const
Select()
Select模型构造函数
static int const SdReceive
#define U(s)
Definition: strings.hpp:1141
SelectWrite & setWriteSock(Socket const &sock)
unsigned __int64 uint64
Definition: utilities.hpp:230
unsigned int uint32
Definition: utilities.hpp:215
bool sendUntil(winux::AnsiString const &data, int msgFlags=MsgDefault)
发送字符串,直到发送完该长度的字符串。
void resetStatus()
重置状态
Server(ip::EndPoint const &ep, int threadCount=4, int backlog=0)
构造函数1
SocketStreamOut(SocketStreamBuf &sockBuf)
winux::SharedPointer< ip::tcp::Socket > clientSockPtr
客户套接字
size_t targetBytes
目标数据量
SocketStreamOut(SocketStreamBuf *sockBuf)
winux::uint64 clientId
客户Id
winux::Buffer adjust(size_t actualDataSize)
在find()到目标内容后,调整data大小。把多余的数据放入extraData,然后返回data内容,并把extraData移到dat...
static int const MsgPeek
EndPointArray const & getArr() const
Select & setExceptFds(winux::Mixed const &fds)
跨平台基础功能库
Definition: archives.hpp:7
SelectExcept Io模型