QT/Embedded QTcpSocket사용 시 플러그 뽑힘 증상 체크 방법
페이지 정보
작성자
본문
아래는 진행하면서 참고했던 사이트들입니다.
참조 사이트
Unplugging ethernet
Qt에서 소켓을 사용하다보면 끊어진 경우를 확인해야할 상황이 발생합니다.
뭐... 굳이 Qt가 아니더라도 언제 어디서나 서비스 제공자는 무조건 확인해야 합니다만,
Qt를 이용한 프로그래밍을 할 땐, 단순히 플러그가 뽑힌 경우를 체크하기엔 조금 까다롭습니다.
왜냐면 QAbstractSocket 클래스가 제공하는 ConnectedState는
연결된 이후에 물리적인 플러그 뽑힘 현상에 대해선 확인해주질 못합니다.
슬프게도,
Qt가 제공하는 그 어떤 소켓 클래스들도 물리적인 플러그 Unconnected를 확인하질 못합니다.
그래서 조금 돌아가는 방법을 사용해야 합니다.
Simple Main Code
우선, 간단한 Socket Program을 만들어 봅니다.
1 2 3 4 5 6 7 8 9 10 11 | #include <QProcess> #include <QTcpSocket> QProcess ping_process_; QStringList ping_params_; private slots: void HandleConnected(); void HandleDisconnected(); void HandleReadyRead(); void HandleStateChange(QAbstractSocket::SocketState state); |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 | tcp_socket_ = new QTcpSocket(this); //tcp_socket_->setSocketOption(QAbstractSocket::KeepAliveOption, 1); connect(tcp_socket_, SIGNAL(connected()), this, SLOT(HandleConnected())); connect(tcp_socket_, SIGNAL(readyRead()), this, SLOT(HandleReadyRead())); connect(tcp_socket_, SIGNAL(disconnected()), this, SLOT(HandleDisconnected())); connect(tcp_socket_, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(HandleStateChange(QAbstractSocket::SocketState))); ping_params_ << "-c" << "1" << server_ip_; |
아주 간단한 프로그램입니다.
4개의 slot은 연결, 끊김, 읽기, 상태 변화를 의미합니다.
메인 코드의 마지막엔 연결이 잘 이루어졌는지 ping을 날려보는 간단한 코드도 들어있습니다.
Ping and QProcess
Ping 테스트를 할 땐, http://를 넣으면 오류가 발생하고,
Window와 Linux에선 서로 다른 인자를 사용하니 그것도 확인해 줘야 합니다.
이를 확인하지 않으면 아래와 유사한 에러 메세지가 뜰겁니다.
error, message
- Try removing "http://" in line number
- Ping expects an IP or an hostname, "http://" isn't part of the hostname.
- cout<<"\n\nexitCode,exitStatus=="<<exitCode<<","<<exitStatus
ping 코드를 작성할 아래처럼 http://를 제거하고 난 뒤에 시도하셔야 합니다.
그러면 아래와 같은 코드를 작성하실 수 있습니다. 아주 간단하게 말이죠.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #if defined(WIN32) QString parameter = "-n 1"; #else QString parameter = "-c 1"; #endif int exitCode = QProcess::execute("ping", QStringList() << parameter << "1.1.1.11"); if (exitCode==0) { // it's alive } else { // it's dead } ..... params << "-c" << "1" << "www.google.com"; |
ConnectToServer function
1 2 3 4 5 6 7 | void TcpClient::ConnectToServer() { if (tcp_socket_->state() != QAbstractSocket::ConnectedState && tcp_socket_->state() != QAbstractSocket::ConnectingState) { tcp_socket_->connectToHost(server_ip_, server_port_); } } |
위에서 선언만 했던 ConnecToServer 함수를 정의합니다.
socket 객체가 아직도 연결되지 않은 상태라면 연결을 시도합니다.
이것도 아주 간단하죠?
HandleConnected function
1 2 3 4 5 6 7 8 | void TcpClient::HandleConnected() { qWarning() << "connect Complete"; bla~ bla~ bla~ emit ConnectionComplete(); } |
이름 그대로 연결이 되면 구동되는 함수입니다.
내부의 코드는 각자 입맛에 맞춰 구성하면 됩니다.
StateChange property
StateChange 속성은 아래와 같습니다.
Constant |
Value |
Description |
QAbstractSocket::UnconnectedState |
0 |
The socket is not connected. |
QAbstractSocket::HostLookupState |
1 |
The socket is performing a host name lookup. |
QAbstractSocket::ConnectingState |
2 |
The socket has started establishing a connection. |
QAbstractSocket::ConnectedState |
3 |
A connection is established. |
QAbstractSocket::BoundState |
4 |
The socket is bound to an address and port (for servers). |
QAbstractSocket::ClosingState |
6 |
The socket is about to close (data may still be waiting to be written). |
QAbstractSocket::ListeningState |
5 |
For internal use only. |
일반적으로 주로 사용하는 Constant는 굵게 표시된 위의 두 개입니다.
아무튼, 저 표를 통해서 유추할 수 있는 아주 간단한 사실은,
1 2 3 4 5 | // Normal QAbstractSocket::ConnectedState // Abnormal QAbstractSocket::UnconnectedState |
이겁니다.
그래서 아래와 같은 한 줄로 코드에서 분기가 가능합니다.
1 | tcp_socket_->state() == QAbstractSocket::UnconnectedState |
아래엔 실제 구현할 수 있는 소켓 프로그램의 전체 코드입니다.
(위와 이어지는 내용)
1 2 3 4 5 6 7 | void TcpClient::HandleStateChange(QAbstractSocket::SocketState state) { if (tcp_socket_->state() == QAbstractSocket::UnconnectedState) HandleDisconnected(); qWarning() << "State Changed : " << state; } |
1 2 3 4 5 6 7 8 9 10 11 | void TcpClient::HandleDisconnected() { if (timer_connecte_->isActive() == false) { tcp_socket_->close(); bla~ bla~ } emit ConnectionError(); qWarning() << "HandleDisconnected"; } |
1 2 3 4 5 | void TcpClient::HandleReadyRead() { recv_data_ = tcp_socket_->readAll(); CheckPacketID(); } |
자, 이제 몇 가지 케이스를 들어 Qt의 소켓이 여러 끊김 현상을 감지할 수 있는지 확인합니다.
물론 위에 나온 코드를 이용해 테스트를 진행할 겁니다.
(위의 코드만 복사하면 프로그램 하나가 만들어지니깐요)
Case1 : Unplugged ethernet
1 2 3 4 5 6 | QProcess p; p.start( /* whatever your command is, see the doc for param types */ ); p.waitForFinished(-1); QString p_stdout = p.readAllStandardOutput(); QString p_stderr = p.readAllStandardError(); |
1 2 3 4 5 6 7 8 9 | |
개인 블로그 http://yowon009.tistory.com/
관련링크
- http://yowon009.tistory.com/314 609회 연결
댓글목록
등록된 댓글이 없습니다.