1 module yu.asyncsocket.tcpclient; 2 3 import std.socket; 4 import std.exception; 5 6 import yu.eventloop; 7 import yu.asyncsocket.tcpsocket; 8 import yu.asyncsocket.exception; 9 import yu.exception; 10 11 alias ConnectCallBack = void delegate(bool connect) nothrow; 12 13 @trusted final class TCPClient : TCPSocket { 14 this(EventLoop loop, bool isIpV6 = false) { 15 super(loop, isIpV6); 16 } 17 18 this(EventLoop loop, AddressFamily family) { 19 super(loop, family); 20 } 21 22 override @property bool isAlive() @trusted nothrow { 23 return super.isAlive() && _isConnect; 24 } 25 26 pragma(inline) bool connect(Address addr) { 27 if (isAlive()) 28 throw new ConnectedException("This Socket is Connected! Please close before connect!"); 29 static if (IOMode == IO_MODE.iocp) { 30 Address bindddr; 31 if (addr.addressFamily() == AddressFamily.INET) { 32 bindddr = new InternetAddress(InternetAddress.PORT_ANY); 33 } else if (addr.addressFamily() == AddressFamily.INET6) { 34 bindddr = new Internet6Address(Internet6Address.PORT_ANY); 35 } else 36 throw new ConnectedException("This Address is not a network address!"); 37 _socket.bind(bindddr); 38 _loop.addEvent(&_event); 39 _iocpread.event = &_event; 40 _iocpread.operationType = IOCP_OP_TYPE.connect; 41 int b = ConnectEx(cast(SOCKET) _socket.handle, 42 cast(SOCKADDR*) addr.name(), addr.nameLen(), null, 0, null, &_iocpread.ol); 43 if (b == 0) { 44 DWORD dwLastError = GetLastError(); 45 if (dwLastError != ERROR_IO_PENDING) { 46 error("ConnectEx failed with error: ", dwLastError); 47 return false; 48 } 49 } 50 return true; 51 } else { 52 if (!start()) 53 return false; 54 _isFrist = true; 55 _socket.connect(addr); 56 return true; 57 } 58 } 59 60 pragma(inline) void setConnectCallBack(ConnectCallBack cback) { 61 _connectBack = cback; 62 } 63 64 protected: 65 override void onClose() nothrow { 66 if (_isFrist && !_isConnect && _connectBack) { 67 _isFrist = false; 68 _connectBack(false); 69 return; 70 } 71 _isConnect = false; 72 super.onClose(); 73 } 74 75 override void onWrite() nothrow { 76 if (_isFrist && !_isConnect && _connectBack) { 77 _isFrist = false; 78 _isConnect = true; 79 _connectBack(true); 80 } 81 82 super.onWrite(); 83 } 84 85 private: 86 bool _isConnect = false; 87 bool _isFrist = true; 88 ConnectCallBack _connectBack; 89 }