서론

QTcpServer 클래스와 QTcpSocket 클래스를 이용해 서버/클라이언트를 구현해보자

 

QTcpClient

 

그림과 같이 GUI 상에 위젯을 배치해 보도록 하자.

 

CMAKE 기반 프로젝트는 아래 코드를 추가하자

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network)

target_link_libraries(QTcpClient PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Network)

 

QMAKE 기반 프로젝트는 아래 코드를 추가하자

QT += network

 

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtNetwork/QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    QTcpSocket *tcpSocket;

    void initialize();

private slots:
    void connectButton();
    void readMessage();
    void disconnected();
};
#endif // WIDGET_H

 

connectButton() slot 함수는 [접속] 버튼 클릭 시 호출된다.

readMessage() slot 함수는 서버로부터 메시지를 받는 Signal이 발생하면 호출되는 함수이다.

disconnected() slot 함수는 서버로부터 접속이 종료된 Signal이 발생하면 호출되는 함수이다.

 

widget.cpp

#include "widget.h"
#include "./ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->connectButton, SIGNAL(clicked()), this, SLOT(connectButton()));
    initialize();
}

void Widget::initialize(){
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
}

void Widget::connectButton(){
    QString serverip = ui->lineEdit->text().trimmed();

    QHostAddress serverAddress(serverip);

    tcpSocket->connectToHost(serverAddress, 25000);
}

void Widget::readMessage(){
    if(tcpSocket->bytesAvailable() >= 0){
        QByteArray readData = tcpSocket->readAll();
        ui->textEdit->append(readData);
    }
}

void Widget::disconnected(){
    qDebug() << Q_FUNC_INFO << "서버 접속 종료.";
}

Widget::~Widget()
{
    delete ui;
}

 

코드를 살펴보자..

void Widget::initialize(){
	// tcpSocket 객체를 생성하고,
    // socket의 readyRead 시그널을 readMessage 슬롯과 연결
    // socket의 disconnected 시그널을 disconnected 슬롯과 연결
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
}
void Widget::connectButton(){

	// connectButton 슬롯은 사용자가 입력한 IP 주소를 가져와 
    // tcpSocket을 통해 해당 서버와 포트 25000으로 연결
    QString serverip = ui->lineEdit->text().trimmed();

    QHostAddress serverAddress(serverip);

    tcpSocket->connectToHost(serverAddress, 25000);
}
void Widget::readMessage(){
	// readMessage 슬롯은 소켓에 읽을 데이터가 있을 때 호출되며,
    // 데이터를 읽어와 textEdit 위젯에 추가한다.
    if(tcpSocket->bytesAvailable() >= 0){
        QByteArray readData = tcpSocket->readAll();
        ui->textEdit->append(readData);
    }
}
void Widget::disconnected(){
	// disconnected 슬롯은 소켓 연결이 끊어졌을 때 호출되며, 디버그 메시지를 출력
    qDebug() << Q_FUNC_INFO << "서버 접속 종료.";
}

 

initialize() 함수는 QTcpSocket 클래스의 tcpSocket 오브젝트를 선언하고 서버로부터 메시지를 받을 발생한 Signal을 readMessage() Slot 함수와 연결한다.

그리고 서버와 연결 종료 Signal을 받으면 disconnected() slot 함수와 연결한다.

따라서 서버로부터 메시지를 받으면 readMessage() 함수를 호출하고 서버와 연결이 종료되면 disconnect() Slot 함수가 호출된다.

readMessage() slot 함수에서 tcpSocket -> bytesAvailable() 함수는 서버가 보내온 메시지의 Bytes 수를 구할 수 있다.

그리고 readAll() 멤버 함수는 서버가 보내온 메시지를 읽어올 수 있는 기능을 제공한다.

'🌠Development > QT' 카테고리의 다른 글

QT project - QTimer 사용하기  (0) 2024.07.16
QT project - 응용 프로그램 만들어보기  (0) 2024.07.16
QT - TcpSocket 통신 Server  (0) 2024.07.15
QT - 네트워크 프로그래밍, socket  (0) 2024.07.12
QT - Dialog(QInputDialog)  (0) 2024.07.12