CWebSocketClient::CWebSocketClient(QUrl url, QObject *parent) : m_url(url), QObject(parent) { //m_url = QUrl(QStringLiteral("ws://localhost:1234")); connect(&m_webSocket, &QWebSocket::connected, this, &CWebSocketClient::onConnected); connect(&m_webSocket, &QWebSocket::disconnected, this, &CWebSocketClient::serverDisconnected); //Client tries to connect every 5s connection_Timer = new QTimer(this); connection_Timer->setInterval(5000); connect(connection_Timer, SIGNAL(timeout()), this, SLOT(onConnectionTimeout())); connect(&m_webSocket, SIGNAL(disconnected()), this, SLOT(resetSocket())); connect(&m_webSocket, SIGNAL(connected()), connection_Timer, SLOT(stop())); connect(&m_webSocket, SIGNAL(disconnected()), connection_Timer, SLOT(start())); connection_Timer->start(); }
void IoConnection::writeSocket() { switch (_wsock_state) { case SOCKET_CONNECTING: { int error = -1; socklen_t len = sizeof(error); getsockopt(_socket, SOL_SOCKET, SO_ERROR, &error, &len); if (error != 0) { LOG(INFO) << "connecting error\n"; resetSocket(); return; } _wsock_state = SOCKET_DATA_WRITE; } case SOCKET_DATA_WRITE: { if (_current_push == 0) { _current_push = getPushData(); if (_current_push == 0) { _setWrite(false); _setRead(true); return; } } if (_current_push->_msg->_close_conn) { //need closed by upstream logic resetSocket(); return; } char* wbuf = _current_push->_wbuf + _current_push->_wpos; int left = _current_push->_wsize - _current_push->_wpos; while (left > 0) { int32_t put = ::send(_socket, wbuf, left, MSG_NOSIGNAL); if (put > 0) { _current_push->_wpos += put; left -= put; break; } else if (put == -1) { switch (errno) { case EINTR: continue; case EAGAIN: return; default: resetSocket(); return; } } else { return; } } if (left == 0) { //TODO //we send msg to wan,but the peer may not receive //we just drop the msg, in the future may be use ack destroyMsgData(_current_push); _current_push = getPushData(); if (_current_push == 0) { _setWrite(false); _setRead(true); return; } } break; } default: { LOG(INFO) << "write state(" << _wsock_state << ") error\n"; resetSocket(); return; } } }
void IoConnection::readSocket() { switch (_rsock_state) { case SOCKET_RECV_FRAMING: { while (true) { int fetch = ::recv(_socket, _rbuf+_rpos, _rsize-_rpos, 0); if (fetch > 0) { _rpos += fetch; } else if (fetch == 0) { //we think client closed closeSocket(); return; } else { switch (errno) { case EAGAIN: break; case EINTR: continue; default: //any other error, reset conn resetSocket(); break; /* default: { //the latest write may cause error: ETIMEDOUT,EHOSTUNREACH,ENETUNREACH if (_rpos > 0 || errno == ETIMEDOUT || errno == EHOSTUNREACH || errno == ENETUNREACH) { //we have received some data,so we think client abnormally closed //resetSocket(); //we should keep TIME_WAIT closeSocket(); } else { //the latest write may cause error: ECONNRESET, but we can't distinguish this situation //we think client normally close closeSocket(); } return; } */ } } break; } //we have some data arrived if (_rpos < (int)sizeof(int)) { //TODO,if we reset timeout return; } _frame_size = ntohl(*((unsigned int*)_rbuf)) + sizeof(int); if (_frame_size > FRAME_MAX_SIZE) { //frame too large, close resetSocket(); return; } if ((int)_frame_size > _rsize) { int new_size = _frame_size + READ_BUFFER_INCREAMENT_SIZE; if (new_size > FRAME_MAX_SIZE) new_size = FRAME_MAX_SIZE; char* new_buffer = new (std::nothrow) char [new_size]; if (new_buffer == 0) { //memory error,reset resetSocket(); return; } memcpy(new_buffer, _rbuf, _rpos); delete [] _rbuf; _rbuf = new_buffer; _rsize = new_size; } _rsock_state = SOCKET_DATA_RECV; } case SOCKET_DATA_RECV: { int left = _frame_size-_rpos; while (left > 0) { int fetch = ::recv(_socket, _rbuf+_rpos, left, 0); if (fetch > 0) { _rpos += fetch; break; } else if (fetch == 0) { closeSocket(); return; } else { switch (errno) { case EINTR: continue; case EAGAIN: return; default: resetSocket(); return; } } } if (_rpos == (int)_frame_size) { int ret = this->whenReceivedFrame(_rbuf, _frame_size); if (ret == -1) { //internal error, close resetSocket(); return; } //接着读新请求 _rpos = 0; _rsock_state = SOCKET_RECV_FRAMING; } else if (_rpos > (int)_frame_size) { char* b = _rbuf; int frame_size = _frame_size; int len = _rpos; int ret; while (len >= frame_size) { ret = this->whenReceivedFrame(b, frame_size); if (ret == -1) { //internal error, close resetSocket(); return; } b += frame_size; len -= frame_size; if (len >= (int)sizeof(int)) { frame_size = ntohl(*((unsigned int*)b)) + sizeof(int); } else { break; } } memcpy(_rbuf, b, len); _rpos = len; _rsock_state = SOCKET_RECV_FRAMING; } break; } default: { LOG(ERROR) << "socket state error, abort\n"; abort(); } } }