이전 글에서 Tab1DeviceControl 클래스를 구현하였습니다.
이번 글에서는 TCP 소켓 통신을 담당하는 SocketClient 클래스와, 이를 UI로 감싸는 Tab2SocketClient 클래스를 구현하는 과정을 정리하겠습니다.

iot_server는 클라이언트 접속 시 ID/PW를 검증합니다.
서버 코드의 CLIENT_INFO 배열에서 KYM_QT가 등록되어 있는지 먼저 확인합니다.

KYM_QT로 등록이 확인되었으므로, 클라이언트에서 [KYM_QT:PASSWD] 형식으로 접속하면 됩니다.
Qt의 소켓 통신 예제를 참고합니다.
Qt Creator 상단 메뉴에서 Examples를 열고 socket으로 검색하면 관련 샘플을 확인할 수 있습니다.

샘플 코드를 재구성한 예제
SocketClient 클래스는 QTcpSocket을 래핑하여 소켓 통신만 전담합니다.
Tab2SocketClient는 UI만 담당하고, 실제 소켓 동작은 SocketClient에 위임하는 구조입니다.
프로젝트에 일반 C++ 클래스로 파일을 추가합니다.
AiotClient 프로젝트 우클릭 → Add New → C++ → C++ Class

socketclient.hsocketclient.cppsocketclient.h에 서버 IP, 포트, 로그인 정보를 멤버 변수로 정의합니다.

QString SERVERIP = "10.10.16.35";
int SERVERPORT = 5000;
QString LOGID = "KYM_QT";
QString LOGPW = "PASSWD";
QTcpSocket의 시그널을 SocketClient의 슬롯으로 연결합니다.
connect(pQTcpSocket, SIGNAL(connected()), this, SLOT(socketConnectServerSlot()));
connect(pQTcpSocket, SIGNAL(disconnected()), this, SLOT(socketClosedServerSlot()));
connect(pQTcpSocket, SIGNAL(readyRead()), this, SLOT(socketReadDataSlot()));
Qt 버전에 따라 에러 시그널 이름이 다릅니다.
#if QT_VERSION전처리기로 분기 처리합니다.
- Qt6 :
errorOccurred(QAbstractSocket::SocketError)- Qt5 :
error(QAbstractSocket::SocketError)
연결이 완료되면 [KYM_QT:PASSWD] 형식으로 서버에 로그인 메시지를 전송합니다.
![]
데이터 수신 시 socketRecvDataSig 시그널로 상위 클래스에 전달합니다.
데이터 송신 시 문자열 끝에 \n을 추가하여 전송합니다.
Tab2에 배치할 위젯 클래스를 생성합니다.
AiotClient 프로젝트 우클릭 → Add New → Qt → Qt Widgets Designer Form Class → Widget 선택
Class name을 Tab2SocketClient로 입력하면 아래 파일이 자동 생성됩니다.
tab2socketclient.htab2socketclient.cpptab2socketclient.uitab2socketclient.ui를 Qt Designer에서 열고 위젯을 배치합니다.
=============================================
| 수신 데이터 | pPBrecvClear | pPBserverConnect |
| |
| pTErecvData |
| |
| pLErecvid | pLEsendData | pPBsend |
=============================================

| 위젯 | objectName | 역할 |
|---|---|---|
| QLabel | label | "수신 데이터" 텍스트 |
| QPushButton | pPBrecvClear | 수신창 초기화 |
| QPushButton | pPBserverConnect | 서버 연결/해제 (Checkable) |
| QTextEdit | pTErecvData | 수신 메시지 표시 |
| QLineEdit | pLErecvid | 수신 대상 ID 입력 |
| QLineEdit | pLEsendData | 송신 메시지 입력 |
| QPushButton | pPBsend | 메시지 송신 |
pPBserverConnect는 Property Editor에서checkable을 체크해야 토글 버튼으로 동작합니다.
Qt Designer의 Signals and Slots Editor에서 수신 삭제 버튼을 연결합니다.

| Sender | Signal | Receiver | Slot |
|---|---|---|---|
| pPBrecvClear | clicked() | pTErecvData | clear() |
SocketClient 포인터를 멤버 변수로 선언하고, 서버 연결 버튼 슬롯과 수신 슬롯을 정의합니다.

SocketClient 객체를 생성하고, 수신 시그널을 슬롯에 연결합니다.
pSocketClient = new SocketClient(this);
connect(pSocketClient, SIGNAL(socketRecvDataSig(QString)), this, SLOT(updateRecvDataSlot(QString)));
pPBserverConnect는 checkable 버튼으로, 연결/해제 상태를 토글합니다.
연결 성공 시 버튼 텍스트를 "서버 종료"로 변경합니다.
수신된 문자열 끝의 \n을 제거하고 현재 시각과 함께 pTErecvData에 추가합니다.
strRecvData.chop(1); // '\n' 제거
QTime time = QTime::currentTime();
QString strTime = time.toString() + " " + strRecvData;
ui->pTErecvData->append(strTime);
tab2socketclient.h를 include하고 Tab2SocketClient 포인터를 선언합니다.
Tab2SocketClient *pTab2SocketClient;
Tab2SocketClient 객체를 생성하여 pTab2에 배치합니다.
pTab2SocketClient = new Tab2SocketClient(ui->pTab2);
ui->pTab2->setLayout(pTab2SocketClient->layout());
빌드 후 실행하면 Tab2 UI가 정상적으로 나타납니다.

서버 연결 버튼을 클릭하면 QInputDialog에서 IP를 입력받습니다.
입력 없이 확인하면 기본 IP(10.10.16.35)로 접속합니다.
연결 성공 시 수신창에 서버 메시지가 표시됩니다.

[KYM_QT] New connected!
(ip:10.10.16.35,fd:7,sockcnt:2)
pLEsendData에서 엔터 입력 시 송신 버튼 클릭과 동일하게 동작하도록 연결합니다.
| Sender | Signal | Receiver | Slot |
|---|---|---|---|
| pLEsendData | returnPressed() | pPBsend | click() |
수신 ID 입력 여부에 따라 메시지 형식이 달라집니다.
[ALLMSG]메시지[입력 아이디]메시지메시지를 입력하고 송신하면 수신창에 에코 메시지가 표시됩니다.
서버 측에서도 메시지 수신을 확인할 수 있습니다.

KYM_LIN 클라이언트가 접속한 경우, 해당 클라이언트가 보낸 메시지도 수신창에 표시됩니다.

서버에 KYM_QT ID 등록 확인
↓
SocketClient 클래스 파일 추가 (QTcpSocket 래핑)
↓
Tab2SocketClient 클래스 생성 (Qt Widgets Designer Form Class)
↓
tab2socketclient.ui에서 위젯 배치
↓
Qt Designer에서 Signal/Slot 연결 (수신 삭제, 엔터→송신)
↓
생성자에서 SocketClient 생성 및 Signal/Slot 연결
↓
서버 연결/해제, 수신 표시, 메시지 송신 Slot 구현
↓
mainwidget에서 Tab2SocketClient 객체 생성 및 pTab2에 배치
↓
서버 연결 및 송수신 동작 확인