fastdo  0.6.8
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 private:
17 };
18 
20 class SocketError : public winux::Error
21 {
22 public:
23  SocketError( int errType, winux::AnsiString const & errStr ) : winux::Error( errType, errStr ) { }
24 };
25 
28 {
29 public:
30  EndPoint() { }
31  virtual ~EndPoint() { }
32 
34  virtual void * get() const = 0;
36  template < typename _Ty >
37  _Ty * get() const { return reinterpret_cast<_Ty *>( this->get() ); }
39  virtual winux::uint & size() const = 0;
41  virtual winux::String toString() const = 0;
42 };
43 
48 {
49 public:
50 
51  // classes and types ------------------------------------------------------------------
52 
54  enum AddrFamily {
55  afUnspec = 0,
56  afLocal = 1,
57  afUnix = afLocal,
58  afFile = afLocal,
59  afInet = 2,
60  afAx25 = 3,
61  afIpx = 4,
62  afAppletalk = 5,
63  afNetrom = 6,
64  afBridge = 7,
65  afAtmpvc = 8,
66  afX25 = 9,
67  afInet6 = 10,
68  afRose = 11,
69  afDecnet = 12,
70  afNetbeui = 13,
71  afSecurity = 14,
72  afKey = 15,
73  afNetlink = 16,
74  afRoute = afNetlink,
75  afPacket = 17,
76  afAsh = 18,
77  afEconet = 19,
78  afAtmsvc = 20,
79  afRds = 21,
80  afSna = 22,
81  afIrda = 23,
82  afPppox = 24,
83  afWanpipe = 25,
84  afLlc = 26,
85  afUnknown27 = 27,
86  afUnknown28 = 28,
87  afCan = 29,
88  afTipc = 30,
89  afBluetooth = 31,
90  afIucv = 32,
91  afRxrpc = 33,
92  afIsdn = 34,
93  afPhonet = 35,
94  afIeee802154 = 36,
95  afMax = 37
96  };
97 
99  enum SockType {
107  sockPacket,
110  /* Flags to be ORed into the type parameter of socket and socketpair and used for the flags parameter of paccept. */
111 
113  sockNonblock
114  };
115 
117  enum Protocol {
118  protoUnspec = 0, protoIp = 0,
121  protoIpip, protoIpv4 = protoIpip,
142  protoMax
143  };
144 
145 public:
146  // static members ---------------------------------------------------------------------
147  // send/recv's message flags
148  static int const MsgDefault;
149 #if defined(_MSC_VER) || defined(WIN32)
150  static int const MsgOob;
151  static int const MsgPeek;
152  static int const MsgDontRoute;
153  static int const MsgWaitAll;
154  static int const MsgPartial;
155  static int const MsgInterrupt;
156  static int const MsgMaxIovLen;
157 #else
158  static int const MsgOob;
159  static int const MsgPeek;
160  static int const MsgDontRoute;
161 # ifdef __USE_GNU
162  /* DECnet uses a different name. */
163  static int const MsgTryHard;
164 # endif
165  static int const MsgCTrunc;
166  static int const MsgProxy;
167  static int const MsgTrunc;
168  static int const MsgDontWait;
169  static int const MsgEor;
170  static int const MsgWaitAll;
171  static int const MsgFin;
172  static int const MsgSyn;
173  static int const MsgConfirm;
174  static int const MsgRst;
175  static int const MsgErrQueue;
176  static int const MsgNoSignal;
177  static int const MsgMore;
178  static int const MsgWaitForOne;
179  static int const MsgCMsgCloexec;
180 
181 #endif
182  // shutdown's how flags
183  static int const SdReceive;
184  static int const SdSend;
185  static int const SdBoth;
186 
187  typedef std::function< void ( size_t hadBytes, void * param ) > FunctionSuccessCallback;
188 public:
189  // constructor/destructor -------------------------------------------------------------
190 
195  explicit Socket( int sock = -1, bool isNewSock = false );
196 
198  Socket( AddrFamily af, SockType sockType, Protocol proto );
199 
200 #ifndef MOVE_SEMANTICS_DISABLED
201 
202  Socket( Socket && other );
204  Socket & operator = ( Socket && other );
205 #endif
206 
207  virtual ~Socket();
208 
209 public:
210  // methods ----------------------------------------------------------------------------
212  void setParams( AddrFamily af, SockType sockType, Protocol proto );
213 
215  bool create( AddrFamily af, SockType sockType, Protocol proto );
217  bool create();
218 
220  int close();
221 
225  int shutdown( int how = SdSend );
226 
228  int send( void const * data, size_t size, int msgFlags = MsgDefault );
230  int send( winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->send( data.c_str(), data.size(), msgFlags ); }
232  int send( winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->send( data.getBuf(), data.getSize(), msgFlags ); }
233 
237  bool sendUntil( size_t targetSize, void const * data, int msgFlags = MsgDefault );
238  bool sendUntil( winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->sendUntil( data.size(), data.c_str(), msgFlags ); }
239  bool sendUntil( winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->sendUntil( data.getSize(), data.getBuf(), msgFlags ); }
240 
249  int sendWaitUntil(
250  size_t targetSize,
251  void const * data,
252  size_t * hadSent,
253  double sec,
254  int * rcWait,
255  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
256  void * param = nullptr,
257  int msgFlags = MsgDefault
258  );
259 
261  winux::AnsiString const & data,
262  size_t * hadSent,
263  double sec,
264  int * rcWait,
265  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
266  void * param = nullptr,
267  int msgFlags = MsgDefault
268  ) { return this->sendWaitUntil( data.size(), data.c_str(), hadSent, sec, rcWait, std::move(eachSuccessCallback), param, msgFlags ); }
269 
271  winux::Buffer const & data,
272  size_t * hadSent,
273  double sec,
274  int * rcWait,
275  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
276  void * param = nullptr,
277  int msgFlags = MsgDefault
278  ) { return this->sendWaitUntil( data.getSize(), data.getBuf(), hadSent, sec, rcWait, std::move(eachSuccessCallback), param, msgFlags ); }
279 
281  template < typename _PodType, size_t _N = sizeof(_PodType) >
282  bool sendUntilType( _PodType const & v, int msgFlags = MsgDefault ) { return this->sendUntil( _N, &v, msgFlags ); }
283 
285  int recv( void * buf, size_t size, int msgFlags = MsgDefault );
286 
293  winux::Buffer recv( size_t size, int msgFlags = MsgDefault );
294 
298  bool recvUntilTarget( winux::AnsiString const & target, winux::GrowBuffer * data, winux::GrowBuffer * extraData, int msgFlags = MsgDefault );
299 
309  int recvWaitUntilTarget(
310  winux::AnsiString const & target,
311  winux::GrowBuffer * data,
312  winux::GrowBuffer * extraData,
313  size_t * hadRead,
314  size_t * startpos,
315  size_t * pos,
316  double sec,
317  int * rcWait,
318  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
319  void * param = nullptr,
320  int msgFlags = MsgDefault
321  );
322 
326  bool recvUntilSize( size_t targetSize, winux::GrowBuffer * data, int msgFlags = MsgDefault );
327 
336  int recvWaitUntilSize(
337  size_t targetSize,
338  winux::GrowBuffer * data,
339  size_t * hadRead,
340  double sec,
341  int * rcWait,
342  FunctionSuccessCallback eachSuccessCallback = FunctionSuccessCallback(),
343  void * param = nullptr,
344  int msgFlags = MsgDefault
345  );
346 
348  template < typename _PodType, size_t _N = sizeof(_PodType) >
349  bool recvUntilType( _PodType * v, int msgFlags = MsgDefault )
350  {
351  winux::GrowBuffer data;
352  data.setBuf( v, 0, _N, true );
353  return this->recvUntilSize( _N, &data, msgFlags );
354  }
355 
362  winux::Buffer recvAvail( int msgFlags = MsgDefault );
363 
372  winux::Buffer recvWaitAvail( double sec, int * rcWait, int msgFlags = MsgDefault );
373 
375  int sendTo( EndPoint const & ep, void const * data, size_t size, int msgFlags = MsgDefault );
377  int sendTo( EndPoint const & ep, winux::AnsiString const & data, int msgFlags = MsgDefault ) { return this->sendTo( ep, data.c_str(), data.size(), msgFlags ); }
379  int sendTo( EndPoint const & ep, winux::Buffer const & data, int msgFlags = MsgDefault ) { return this->sendTo( ep, data.getBuf(), data.getSize(), msgFlags ); }
380 
384  int recvFrom( EndPoint * ep, void * buf, size_t size, int msgFlags = MsgDefault );
392  winux::Buffer recvFrom( EndPoint * ep, size_t size, int msgFlags = MsgDefault );
393 
395  bool connect( EndPoint const & ep );
396 
398  bool bind( EndPoint const & ep, SockType sockType = sockStream );
399 
401  bool listen( int backlog );
402 
406  bool accept( int * sock, EndPoint * ep = NULL );
407 
410  {
411  int sock;
412  return this->accept( &sock, ep ) ? winux::SharedPointer<Socket>( new Socket( sock, true ) ) : winux::SharedPointer<Socket>();
413  }
414 
415  // socket's options -------------------------------------------------------------------
416 
418  int getRecvBufSize() const;
420  bool setRecvBufSize( int optval );
421 
423  int getSendBufSize() const;
425  bool setSendBufSize( int optval );
426 
428  winux::uint32 getRecvTimeout() const;
430  bool setRecvTimeout( winux::uint32 optval );
431 
433  winux::uint32 getSendTimeout() const;
437  bool setSendTimeout( winux::uint32 optval );
438 
440  bool getReUseAddr() const;
442  bool setReUseAddr( bool optval );
443 
445  bool getBroadcast() const;
447  bool setBroadcast( bool optval );
448 
450  int getError() const;
451 
453  SockType getType() const;
454 
458  bool isListening() const;
459 
460  // ioctls -----------------------------------------------------------------------------
461 
463  int getAvailable() const;
464 
466  bool setBlocking( bool blocking );
467 
468  // attributes -------------------------------------------------------------------------
469 
471  int get() const;
472 
474  operator bool() const { return this->get() > -1; }
475 
476  // static -----------------------------------------------------------------------------
477 
479  static int ErrNo();
480 
481 protected:
484 };
485 
488 {
489  enum {
490  RetryCount = 10
491  };
492 
495  size_t startpos;
496  size_t pos;
497  size_t hadBytes;
498  size_t targetBytes;
499  size_t retryCount;
500 
502  {
503  this->resetStatus();
504  }
505 
507  void resetData()
508  {
509  this->data.free();
510  this->extraData.free();
511  }
512 
514  void resetStatus()
515  {
516  this->startpos = 0;
517  this->pos = winux::npos;
518  this->hadBytes = 0;
519  this->targetBytes = 0;
520  this->retryCount = 0;
521  }
522 
524  void append( winux::Buffer const & data )
525  {
526  this->data.append(data);
527  }
528 
532  template < typename _IndexType >
533  bool find( winux::AnsiString const & target, std::vector<_IndexType> const & targetNextVal )
534  {
535  // 如果接收到的数据小于标记长度 或者 搜不到标记 则退出
536  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 )
537  {
538  if ( this->data.getSize() >= target.size() ) this->startpos = this->data.getSize() - target.size() + 1; // 计算下次搜索起始
539  return false;
540  }
541  else
542  {
543  return true;
544  }
545  }
546 
549  {
550  // 搜到指定标记时收到数据的大小(含指定标记)
551  size_t searchedDataSize = this->pos + target.size();
552  this->extraData._setSize(0);
553  // 额外收到的数据
554  this->extraData.append( this->data.getBuf<char>() + searchedDataSize, this->data.getSize() - searchedDataSize );
555  this->data._setSize(searchedDataSize);
556 
557  winux::Buffer actualData(this->data);
558 
559  // 额外的数据移入主数据中
560  this->data = std::move(extraData);
561  this->resetStatus(); // 重置数据收发场景
562 
563  return actualData;
564  }
565 };
566 
568 
569 class EIENNET_DLL SocketStreamBuf : public std::streambuf
570 {
571 public:
573  eiennet::Socket * sock,
574  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out,
575  size_t inputBufSize = (size_t)-1,
576  size_t outputBufSize = (size_t)-1
577  );
578 
579  virtual ~SocketStreamBuf();
580 
581  Socket * getSocket() const { return _sock; }
582  // input buffer begin -----------------------------------------------------------------------
583 protected:
584  virtual int_type underflow();
585  // input buffer end -----------------------------------------------------------------------
586 
587  // output buffer begin -----------------------------------------------------------------------
588 protected:
589  virtual int_type overflow( int_type c );
590  virtual int sync();
591  int _flush();
592  // output buffer end -----------------------------------------------------------------------
593 
594 
595 private:
596  eiennet::Socket * _sock;
597  winux::Buffer _inputBuf;
598  winux::Buffer _outputBuf;
599 
601 };
602 
604 class EIENNET_DLL SocketStreamOut : public std::ostream
605 {
606 private:
607  SocketStreamBuf * _sockBuf;
608 public:
609  SocketStreamOut( SocketStreamBuf * sockBuf ) : std::ostream(sockBuf), _sockBuf(sockBuf) { }
610  SocketStreamOut( SocketStreamBuf & sockBuf ) : std::ostream(&sockBuf), _sockBuf(&sockBuf) { }
611  SocketStreamOut( winux::SimplePointer<SocketStreamBuf> & sockBuf ) : std::ostream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
612  SocketStreamOut( winux::SharedPointer<SocketStreamBuf> & sockBuf ) : std::ostream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
613 
615  SocketStreamOut & writeAndFlush( winux::Buffer const & data );
616 };
617 
619 class EIENNET_DLL SocketStreamIn : public std::istream
620 {
621 private:
622  SocketStreamBuf * _sockBuf;
623 public:
624  SocketStreamIn( SocketStreamBuf * sockBuf ) : std::istream(sockBuf), _sockBuf(sockBuf) { }
625  SocketStreamIn( SocketStreamBuf & sockBuf ) : std::istream(&sockBuf), _sockBuf(&sockBuf) { }
626  SocketStreamIn( winux::SimplePointer<SocketStreamBuf> & sockBuf ) : std::istream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
627  SocketStreamIn( winux::SharedPointer<SocketStreamBuf> & sockBuf ) : std::istream(sockBuf.get()), _sockBuf(sockBuf.get()) { }
628 
630  std::streamsize getAvailable() const;
632  SocketStreamIn & readAvail( winux::Buffer * data );
634  SocketStreamIn & read( winux::Buffer * data, size_t size );
636  std::streamsize waitAvail( double sec );
637 };
638 
640 
641 namespace ip
642 {
643 
646 {
647 public:
651  EndPoint( winux::Mixed const & ipAndPort );
655  EndPoint( winux::String const & ipAddr, winux::ushort port );
656 
657  EndPoint( EndPoint const & other );
658  EndPoint & operator = ( EndPoint const & other );
659 
660 #ifndef MOVE_SEMANTICS_DISABLED
661  EndPoint( EndPoint && other );
662  EndPoint & operator = ( EndPoint && other );
663 #endif
664 
665  virtual ~EndPoint();
666 
668  void init( Socket::AddrFamily af = Socket::afUnspec );
670  void init( winux::Mixed const & ipAndPort );
674  void init( winux::String const & ipAddr, winux::ushort port );
675 
677  virtual void * get() const override;
679  template < typename _Ty >
680  _Ty * get() const { return reinterpret_cast<_Ty *>( this->get() ); }
682  virtual winux::uint & size() const override;
684  virtual winux::String toString() const override;
685 
687  operator winux::Mixed() const;
688 
690  winux::String getIp() const;
692  winux::ushort getPort() const;
693 private:
695 };
696 
699 {
700 public:
701  typedef std::vector<ip::EndPoint> EndPointArray;
703  Resolver( winux::Mixed const & hostAndPort );
705  Resolver( winux::String const & hostName, winux::ushort port );
706 
707  EndPointArray::iterator begin() { return _epArr.begin(); }
708  EndPointArray::const_iterator begin() const { return _epArr.begin(); }
709  EndPointArray::iterator end() { return _epArr.end(); }
710  EndPointArray::const_iterator end() const { return _epArr.end(); }
711 
713  size_t count() const { return _epArr.size(); }
715  winux::String const & getHostname() const { return _hostName; }
717  winux::ushort getPort() const { return _port; }
718 
719  EndPointArray::value_type const & operator [] ( int i ) const { return _epArr[i]; }
720  EndPointArray::value_type & operator [] ( int i ) { return _epArr[i]; }
721 
722  EndPointArray & getArr() { return _epArr; }
723  EndPointArray const & getArr() const { return _epArr; }
724 
726  virtual winux::String toString() const;
728  operator winux::Mixed() const;
729 private:
730  size_t _resolve( winux::String const & hostName, winux::ushort port );
731  winux::String _hostName;
732  winux::ushort _port;
733  EndPointArray _epArr;
734 };
735 
736 namespace tcp
737 {
740 {
741 public:
743 
748  explicit Socket( int sock, bool isNewSock = false ) : BaseClass( sock, isNewSock ) { }
749 
751  Socket() : BaseClass( BaseClass::afInet, BaseClass::sockStream, BaseClass::protoUnspec ) { }
752 
753 #ifndef MOVE_SEMANTICS_DISABLED
754 
755  Socket( Socket && other ) : BaseClass( std::move(other) ) { }
757  Socket & operator = ( Socket && other )
758  {
759  BaseClass::operator = ( std::move(other) );
760  return *this;
761  }
762 #endif
763 
766  {
767  int sock;
768  return BaseClass::accept( &sock, ep ) ? winux::SharedPointer<Socket>( new Socket( sock, true ) ) : winux::SharedPointer<Socket>();
769  }
770 };
771 
773 EIENNET_FUNC_DECL(int) ConnectAttempt( Socket * sock, EndPoint const & ep, winux::uint32 timeoutMs );
774 
781 EIENNET_FUNC_DECL(int) ConnectAttempt( Socket * sock, Resolver const & resolver, winux::uint32 perCnnTimeoutMs );
782 
783 } // namespace tcp
784 
785 namespace udp
786 {
789 {
790 public:
792 
797  explicit Socket( int sock, bool isNewSock = false ) : BaseClass( sock, isNewSock ) { }
798 
800  Socket() : BaseClass( BaseClass::afInet, BaseClass::sockDatagram, BaseClass::protoUnspec ) { }
801 
802 #ifndef MOVE_SEMANTICS_DISABLED
803 
804  Socket( Socket && other ) : BaseClass( std::move(other) ) { }
806  Socket & operator = ( Socket && other )
807  {
808  BaseClass::operator = ( std::move(other) );
809  return *this;
810  }
811 #endif
812 
813 };
814 
815 } // namespace udp
816 
817 } // namespace ip
818 
820 
822 namespace io
823 {
824 
827 {
828 public:
829  SelectRead();
830  SelectRead( Socket const & sock );
831  SelectRead( Socket const * sock );
832  SelectRead( int fd );
833  SelectRead( winux::Mixed const & fds );
834  ~SelectRead();
835 
836  SelectRead & setReadSock( Socket const & sock ) { return setReadFd( sock.get() ); }
837  SelectRead & setReadSock( Socket const * sock ) { return setReadFd( sock->get() ); }
838  SelectRead & setReadFd( int fd );
839  SelectRead & delReadFd( int fd );
840  SelectRead & setReadFds( winux::Mixed const & fds );
841  SelectRead & clear();
842  int hasReadSock( Socket const & sock ) const { return hasReadFd( sock.get() ); }
843  int hasReadFd( int fd ) const;
844 
849  int wait( double sec = -1 );
850 protected:
853 };
854 
857 {
858 public:
859  SelectWrite();
860  SelectWrite( Socket const & sock );
861  SelectWrite( Socket const * sock );
862  SelectWrite( int fd );
863  SelectWrite( winux::Mixed const & fds );
864  ~SelectWrite();
865 
866  SelectWrite & setWriteSock( Socket const & sock ) { return setWriteFd( sock.get() ); }
867  SelectWrite & setWriteSock( Socket const * sock ) { return setWriteFd( sock->get() ); }
868  SelectWrite & setWriteFd( int fd );
869  SelectWrite & delWriteFd( int fd );
870  SelectWrite & setWriteFds( winux::Mixed const & fds );
871  SelectWrite & clear();
872  int hasWriteSock( Socket const & sock ) const { return hasWriteFd( sock.get() ); }
873  int hasWriteFd( int fd ) const;
874 
879  int wait( double sec = -1 );
880 protected:
883 };
884 
887 {
888 public:
889  SelectExcept();
890  SelectExcept( Socket const & sock );
891  SelectExcept( Socket const * sock );
892  SelectExcept( int fd );
893  SelectExcept( winux::Mixed const & fds );
894  ~SelectExcept();
895 
896  SelectExcept & setExceptSock( Socket const & sock ) { return setExceptFd( sock.get() ); }
897  SelectExcept & setExceptSock( Socket const * sock ) { return setExceptFd( sock->get() ); }
898  SelectExcept & setExceptFd( int fd );
899  SelectExcept & delExceptFd( int fd );
900  SelectExcept & setExceptFds( winux::Mixed const & fds );
901  SelectExcept & clear();
902  int hasExceptSock( Socket const & sock ) const { return hasExceptFd( sock.get() ); }
903  int hasExceptFd( int fd ) const;
904 
909  int wait( double sec = -1 );
910 protected:
913 };
914 
916 class EIENNET_DLL Select : public SelectRead, public SelectWrite, public SelectExcept
917 {
918 public:
920  Select() { }
921 
922  Select & setReadSock( Socket const & sock ) { SelectRead::setReadSock(sock); return *this; }
923  Select & setReadFd( int fd ) { SelectRead::setReadFd(fd); return *this; }
924  Select & delReadFd( int fd ) { SelectRead::delReadFd(fd); return *this; }
925  Select & setReadFds( winux::Mixed const & fds ) { SelectRead::setReadFds(fds); return *this; }
926  Select & clearReadFds() { SelectRead::clear(); return *this; }
927 
928  Select & setWriteSock( Socket const & sock ) { SelectWrite::setWriteSock(sock); return *this; }
929  Select & setWriteFd( int fd ) { SelectWrite::setWriteFd(fd); return *this; }
930  Select & delWriteFd( int fd ) { SelectWrite::delWriteFd(fd); return *this; }
931  Select & setWriteFds( winux::Mixed const & fds ) { SelectWrite::setWriteFds(fds); return *this; }
932  Select & clearWriteFds() { SelectWrite::clear(); return *this; }
933 
934  Select & setExceptSock( Socket const & sock ) { SelectExcept::setExceptSock(sock); return *this; }
935  Select & setExceptFd( int fd ) { SelectExcept::setExceptFd(fd); return *this; }
936  Select & delExceptFd( int fd ) { SelectExcept::delExceptFd(fd); return *this; }
937  Select & setExceptFds( winux::Mixed const & fds ) { SelectExcept::setExceptFds(fds); return *this; }
938  Select & clearExceptFds() { SelectExcept::clear(); return *this; }
939 
941  Select & clear() { SelectRead::clear(); SelectWrite::clear(); SelectExcept::clear(); return *this; }
942 
947  int wait( double sec = -1 );
948 };
949 
950 } // namespace io
951 
953 
955 {
956 public:
957  ClientCtx( winux::uint64 clientId, winux::String const & clientEpStr, winux::SharedPointer<eiennet::ip::tcp::Socket> clientSockPtr );
958 
959  virtual ~ClientCtx();
960 
962  winux::String getStamp() const;
963 
967  bool canRemove;
969 
970 private:
972 };
973 
981 {
982 public:
984  Server();
985 
995  Server( bool autoReadData, ip::EndPoint const & ep, int threadCount = 4, int backlog = 0, double serverWait = 0.002, double verboseInterval = 0.01, bool verbose = true );
996 
997  virtual ~Server();
998 
1008  bool startup( bool autoReadData, ip::EndPoint const & ep, int threadCount = 4, int backlog = 0, double serverWait = 0.002, double verboseInterval = 0.01, bool verbose = true );
1009 
1011  virtual int run( void * runParam );
1012 
1014  void stop( bool b = true );
1015 
1017  size_t getClientsCount() const;
1018 
1020  void removeClient( winux::uint64 clientId );
1021 
1022 protected:
1024  winux::SharedPointer<ClientCtx> & _addClient( ip::EndPoint const & clientEp, winux::SharedPointer<ip::tcp::Socket> clientSockPtr );
1026  template < typename _Fx, typename... _ArgType >
1027  void _postTask( winux::SharedPointer<ClientCtx> clientCtxPtr, _Fx fn, _ArgType&& ... arg )
1028  {
1029  auto routine = MakeSimple( NewRunable( fn, std::forward<_ArgType>(arg)... ) );
1030  // 标记为处理事件中
1031  clientCtxPtr->processingEvent = true;
1032  this->_pool.task( [routine, clientCtxPtr] () {
1033  routine->invoke();
1034  // 事件处理完毕,可再次select()事件
1035  clientCtxPtr->processingEvent = false;
1036  } ).post();
1037  }
1038 
1043  std::map< winux::uint64, winux::SharedPointer<ClientCtx> > _clients;
1044 
1046  bool _stop;
1050 
1051  double _serverWait;
1053  bool _verbose;
1054 
1055 private:
1056  // 客户数据通知
1058  ClientDataNotify,
1059  ( winux::SharedPointer<ClientCtx> clientCtxPtr, size_t readableSize ),
1060  ( clientCtxPtr, readableSize )
1061  )
1062 
1063  // 客户数据到达
1065  ClientDataArrived,
1066  ( winux::SharedPointer<ClientCtx> clientCtxPtr, winux::Buffer data ),
1067  ( clientCtxPtr, std::move(data) )
1068  )
1069 
1070  // 当创建客户连接对象
1072  ClientCtx *,
1073  CreateClient,
1074  ( winux::uint64 clientId, winux::String const & clientEpStr, winux::SharedPointer<ip::tcp::Socket> clientSockPtr )
1075  );
1076 
1078 };
1079 
1081 
1083 namespace old_v1
1084 {
1086 class ClientCtx
1087 {
1088 public:
1090  clientId(clientId),
1091  clientEpStr(clientEpStr),
1092  clientSockPtr(clientSockPtr)
1093  {
1094  }
1095 
1096  virtual ~ClientCtx()
1097  {
1098  }
1099 
1103 
1104 private:
1105  DISABLE_OBJECT_COPY(ClientCtx)
1106 };
1107 
1113 template < class _ClientCtxClass >
1114 class Server
1115 {
1116 public:
1118  using StartupHandlerFunction = std::function< void( ClientCtxSharedPointer clientCtxPtr ) >;
1119 
1125  Server( ip::EndPoint const & ep, int threadCount = 4, int backlog = 0 ) :
1126  _cumulativeClientId(0),
1127  _stop(false),
1128  _pool(threadCount),
1129  _mtxServer(true)
1130  {
1131  _servSock.setReUseAddr(true);
1132  _stop = !( _servSock.eiennet::Socket::bind( ep, Socket::sockStream ) && _servSock.listen(backlog) );
1133  }
1134 
1135  virtual ~Server()
1136  {
1137  }
1138 
1139  virtual int run()
1140  {
1141  while ( !_stop )
1142  {
1143  io::Select sel;
1144  sel.setExceptSock(_servSock);
1145  sel.setReadSock(_servSock);
1146  int rc = sel.wait(0.01);
1147  if ( rc > 0 )
1148  {
1149  if ( sel.hasReadSock(_servSock) )
1150  {
1151  ip::EndPoint clientEp;
1152  auto clientSockPtr = _servSock.accept(&clientEp);
1153  if ( clientSockPtr )
1154  {
1155  auto & clientCtxPtr = this->_addClient( clientEp, clientSockPtr );
1156 
1157  // 进入该客户的业务逻辑
1158  this->onStartup(clientCtxPtr);
1159  }
1160  }
1161  else if ( sel.hasExceptSock(_servSock) )
1162  {
1163  _stop = true;
1164  }
1165  }
1166  }
1167 
1168  _pool.whenEmptyStopAndWait();
1169  return 0;
1170  }
1171 
1173  void stop( bool b = true ) { static_cast<volatile bool &>(_stop) = b; }
1174 
1175  size_t getClientsCount() const
1176  {
1177  winux::ScopeGuard guard( const_cast<winux::Mutex &>(_mtxServer) );
1178  return _clients.size();
1179  }
1180 
1182  {
1183  _startupHandler = handler;
1184  }
1185 
1186  void removeClient( winux::uint64 clientId )
1187  {
1188  winux::ScopeGuard guard(_mtxServer);
1189  _clients.erase(clientId);
1190  }
1191 
1192 protected:
1194  {
1195  ClientCtxSharedPointer * client;
1196  {
1197  winux::ScopeGuard guard(_mtxServer);
1198  ++_cumulativeClientId;
1199  client = &_clients[_cumulativeClientId];
1200  }
1201  client->attachNew( new _ClientCtxClass( _cumulativeClientId, clientEp.toString(), clientSockPtr ) );
1202  return *client;
1203  }
1204 
1205  winux::uint64 _cumulativeClientId; // 客户唯一标识
1206  bool _stop; // 是否停止
1207  winux::ThreadPool _pool; // 线程池
1208  winux::Mutex _mtxServer; // 互斥量保护服务器共享数据
1209  ip::tcp::Socket _servSock; // 服务器监听套接字
1210  std::map< winux::uint64, ClientCtxSharedPointer > _clients; // 客户表
1211 
1212  // 一个客户的业务逻辑开启
1213  virtual void onStartup( ClientCtxSharedPointer clientCtxPtr )
1214  {
1215  if ( this->_startupHandler ) this->_startupHandler(clientCtxPtr);
1216  }
1217  StartupHandlerFunction _startupHandler; // onStartup()事件处理
1218 
1219 private:
1220  DISABLE_OBJECT_COPY(Server)
1221 };
1222 
1223 } // namespace old_v1
1224 
1225 } // namespace eiennet
1226 
1227 
1228 
1229 #endif // __SOCKET_HPP__
XString< char > AnsiString
Definition: utilities.hpp:212
#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)
Socket(Socket &&other)
移动构造函数
SelectWrite Io模型
SocketStreamIn(SocketStreamBuf *sockBuf)
void * getBuf() const
暴露缓冲区指针
Definition: utilities.hpp:585
socket库初始化
void whenEmptyStopAndWait()
当任务队列为空,任务链为0,就停止线程池运行,并等待线程组线程正常退出
Definition: threadtask.hpp:237
基础客户场景类
Select & clear()
清空所有fds
SocketStreamOut(winux::SimplePointer< SocketStreamBuf > &sockBuf)
winux::uint64 _cumulativeClientId
客户唯一标识
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)
std::map< winux::uint64, winux::SharedPointer< ClientCtx > > _clients
客户映射表
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
是否事件处理中,保证同一个客户连接仅投递一个事件到线程池中
winux::RecursiveMutex _mtxServer
互斥量保护服务器共享数据
static int const MsgDefault
XString< tchar > String
Definition: utilities.hpp:216
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)
winux::MembersWrapper< struct Socket_Data > _self
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:613
#define DISABLE_OBJECT_COPY(clsname)
Definition: utilities.hpp:81
Select & setWriteSock(Socket const &sock)
Select & delWriteFd(int fd)
double _serverWait
服务器IO等待时间间隔(秒)
static int const MsgDontRoute
Select & delExceptFd(int fd)
winux::uint64 _cumulativeClientId
double _verboseInterval
Verbose信息刷新间隔(秒)
互斥量
Definition: threads.hpp:272
winux::SharedPointer< Socket > accept(EndPoint *ep=NULL)
接受一个客户连接
void removeClient(winux::uint64 clientId)
SocketStreamIn(winux::SharedPointer< SocketStreamBuf > &sockBuf)
bool _servSockAIsListening
servSockA是否处于监听中
SelectRead Io模型
std::function< void(size_t hadBytes, void *param) > FunctionSuccessCallback
Select & setReadFds(winux::Mixed const &fds)
Select & setExceptSock(Socket const &sock)
ip::tcp::Socket _servSockB
服务器监听套接字B
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:685
作用域范围保护
Definition: system.hpp:207
winux::SharedPointer< Socket > accept(EndPoint *ep=NULL)
接受一个客户连接
size_t startpos
起始位置
static constexpr size_t const npos
非位置,值为-1。
Definition: utilities.hpp:240
bool _stop
是否停止
Socket(Socket &&other)
移动构造函数
void onStartupHandler(StartupHandlerFunction handler)
套接字基础类
Select & setReadFd(int fd)
缓冲区,表示内存中一块二进制数据(利用malloc/realloc进行内存分配)
Definition: utilities.hpp:528
size_t hadBytes
已接收/发送数据量
#define EIENNET_DLL
数据收发场景,存放数据收发过程中的一些变量
Socket(int sock, bool isNewSock=false)
构造函数1,包装现有socket描述符
winux::MembersWrapper< struct SelectRead_Data > _self
virtual winux::String toString() const override
转换成"IP:port"的字符串形式
size_t getClientsCount() const
EndPointArray::iterator end()
套接字错误
#define DEFINE_CUSTOM_EVENT_RETURN_EX(ret, evtname, paramtypes)
Definition: utilities.hpp:152
static int const MsgPartial
unsigned int uint
Definition: utilities.hpp:170
void _setSize(size_t dataSize)
设置数据大小,不能超过容量大小(不建议外部调用)
Definition: utilities.hpp:619
SelectExcept & setExceptSock(Socket const &sock)
void setBuf(void const *buf, size_t size, size_t capacity, bool isPeek)
设置缓冲区,当isPeek为false时拷贝数据缓冲区
int hasWriteSock(Socket const &sock) const
SockType
套接字类型
bool _servSockBIsListening
servSockB是否处于监听中
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:432
winux::Buffer adjust(winux::AnsiString const &target)
data里搜到target内容后,调整data大小,把多余的数据放入extraData,然后返回data,并把extraData移到data...
std::map< winux::uint64, ClientCtxSharedPointer > _clients
winux::GrowBuffer data
数据
线程池,创建一组线程等待着从任务队列中获取任务执行
Definition: threadtask.hpp:159
bool recvUntilType(_PodType *v, int msgFlags=MsgDefault)
接收一个Plain of Data类型的变量,若成功返回true,否则返回false。
SocketStreamOut(winux::SharedPointer< SocketStreamBuf > &sockBuf)
void append(winux::Buffer const &data)
添加数据到data
static int const MsgWaitAll
int sendWaitUntil(winux::AnsiString const &data, size_t *hadSent, double sec, int *rcWait, FunctionSuccessCallback eachSuccessCallback=FunctionSuccessCallback(), void *param=nullptr, int msgFlags=MsgDefault)
virtual void onStartup(ClientCtxSharedPointer clientCtxPtr)
Select & delReadFd(int fd)
bool sendUntil(winux::Buffer const &data, int msgFlags=MsgDefault)
网络通信库
winux::ThreadPool _pool
线程池
AddrFamily
地址族
高效的可增长缓冲区,1.33倍冗余量
Definition: utilities.hpp:659
static int const MsgInterrupt
套接字输入流
ip::tcp::Socket _servSockA
服务器监听套接字A
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:137
bool find(winux::AnsiString const &target, std::vector< _IndexType > const &targetNextVal)
在data里查找target内容。startpos指定起始位置,pos表示搜索到的位置。
size_t retryCount
已重试次数
主机名解析器(可以把域名解析为一个或多个IP端点)
virtual winux::uint & size() const =0
取得地址的数据大小,一般为内部地址结构体的大小.
StartupHandlerFunction _startupHandler
std::vector< ip::EndPoint > EndPointArray
unsigned short ushort
Definition: utilities.hpp:173
混合体,能表示多种类型的值
Definition: utilities.hpp:750
winux::MembersWrapper< struct SelectExcept_Data > _self
int send(winux::AnsiString const &data, int msgFlags=MsgDefault)
发送数据。返回已发送大小,出错返回-1。
简单指针
Definition: smartptr.hpp:235
std::function< void(ClientCtxSharedPointer clientCtxPtr) > StartupHandlerFunction
static int const MsgMaxIovLen
错误类
Definition: utilities.hpp:505
SimplePointer< _Ty > MakeSimple(_Ty *newObj)
Definition: smartptr.hpp:911
EndPointArray::const_iterator begin() const
bool _isAutoReadData
是否自动读取客户到达的数据。当为true时,客户数据达到时调用ClientDataArrived事件,否则调用ClientDataNo...
Select()
Select模型构造函数
static int const SdReceive
bool _verbose
显示提示信息
SelectWrite & setWriteSock(Socket const &sock)
unsigned __int64 uint64
Definition: utilities.hpp:185
unsigned int uint32
Definition: utilities.hpp:170
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)
size_t size() const
获取数据大小
Definition: utilities.hpp:616
winux::uint64 clientId
客户Id
bool sendUntilType(_PodType const &v, int msgFlags=MsgDefault)
发送一个Plain of Data类型的变量,若成功返回true,否则返回false。
static int const MsgPeek
EndPointArray const & getArr() const
Select & setExceptFds(winux::Mixed const &fds)
跨平台基础功能库
Definition: archives.hpp:7
SelectExcept Io模型
winux::MembersWrapper< struct SelectWrite_Data > _self