2021 시작

왜 이건 스레드가 아니냐고? 그냥 한번 스레드 적용안하고만들어봤는데 세상 편하더라 와......

서버와 연결된 모습

닉네임이나 UID가 없으니까 누가 무슨메시지 친지를 모르겠더라고 그래서 나아아~중에 추가해봐야지

서버가 꺼지면 연결된 클라 다 꺼짐

//input_widget.h

#ifndef INPUT_WIDGET_H
#define INPUT_WIDGET_H
#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTcpSocket>
#include <QHostAddress>
#include <QtNetwork>
#include <QtEvents>
#include <QMessageBox>

class InputDialog : public QDialog
{
    Q_OBJECT
private:
    //
    //GUI 버튼
    //



    //IP 입력 부분
    QSharedPointer<QLabel>ip_label;
    QSharedPointer<QLineEdit>ip_edit;
    QSharedPointer<QHBoxLayout>ip_layout;

    //PORT 입력부분
    QSharedPointer<QLabel>port_label;
    QSharedPointer<QLineEdit>port_edit;
    QSharedPointer<QHBoxLayout>port_layout;

    //연결할지 말지 선택 버튼
    QSharedPointer<QPushButton>connect_btn;
    QSharedPointer<QPushButton>exit_btn;
    QSharedPointer<QHBoxLayout>btn_layout;


    //최종 레이아웃 설정
    QSharedPointer<QVBoxLayout>layout;

    //
    QSharedPointer<QTcpSocket>tcp_socket;

    //키눌림 이벤트 처리
    virtual void keyPressEvent(QKeyEvent *);

public:
    InputDialog(QSharedPointer<QTcpSocket>&,
                QDialog* dialog = nullptr);

    ~InputDialog();

signals:
    void Press_Enter();


public slots:
    void Click_Connect_Btn();
    void Click_Exit_Btn();


};

#endif // INPUT_WIDGET_H
//input_widget.cpp

#include "input_widget.h"

InputDialog::InputDialog(QSharedPointer<QTcpSocket>& tcp_socket,
                         QDialog* dialog)
    :tcp_socket(tcp_socket)

{


    //
    //GUI 설정
    //

    //ip 입력 및 레이아웃 설정
    ip_label.reset(new QLabel("연결할 IP "));

    ip_edit.reset(new QLineEdit);

    ip_layout.reset(new QHBoxLayout);
    ip_layout->addWidget(ip_label.get());
    ip_layout->addWidget(ip_edit.get());


    //port입력 및 레이아웃 설정
    port_label.reset(new QLabel("연결할 PORT"));

    port_edit.reset(new QLineEdit);

    port_layout.reset(new QHBoxLayout);
    port_layout->addWidget(port_label.get());
    port_layout->addWidget(port_edit.get());


    //연결, 종료 버튼 및 레이아웃 설정
    connect_btn.reset(new QPushButton("연결"));

    exit_btn.reset(new QPushButton("종료"));

    btn_layout.reset(new QHBoxLayout);
    btn_layout->addWidget(connect_btn.get());
    btn_layout->addWidget(exit_btn.get());


    //최종 레이아웃 설정
    layout.reset(new QVBoxLayout(this));
    layout->addLayout(ip_layout.get());
    layout->addLayout(port_layout.get());
    layout->addLayout(btn_layout.get());

    setLayout(layout.get());


    //
    //connect
    //

    //연결 버튼
    connect(connect_btn.get(),&QPushButton::clicked,
            this,&InputDialog::Click_Connect_Btn);

    //Enter누르면 연결 버튼 누른거랑 똑같음
    connect(this,SIGNAL(Press_Enter()),
            this,SLOT(Click_Connect_Btn()));


    //닫기 버튼
    connect(exit_btn.get(),&QPushButton::clicked,
            this,&InputDialog::Click_Exit_Btn);



}

InputDialog::~InputDialog(){}

void InputDialog::Click_Connect_Btn()
{
    QString ip = ip_edit->text();
    quint16 port = port_edit->text().toUShort();

    tcp_socket->connectToHost(ip,port);

    //10초동안 연결이 되길 기다린다.
    if(!tcp_socket->waitForConnected(10000)){
        QMessageBox::critical(this,
                              "Connect Error!",
                              tcp_socket->errorString());
        exit(-1);
    }


    close();
}

void InputDialog::Click_Exit_Btn()
{
    exit(-1);
}

void InputDialog::keyPressEvent(QKeyEvent* event)
{
    Q_UNUSED(event);

    switch(event->key())
    {
     case Qt::Key_Return:
        emit(Press_Enter());
        break;

    }
}

//////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include "input_widget.h"
#include <QStringList>
#include <QStringListModel>
#include <QListView>
#include <QWidget>





class Widget : public QWidget
{
    Q_OBJECT
private:
    //////////////GUI 부분///////////////////////
    QSharedPointer<QStringListModel>chat_list_model;
    QSharedPointer<QListView>chat_list_view;
    QSharedPointer<QStringList>str_list;


    QSharedPointer<QLineEdit>chat_edit;
    QSharedPointer<QPushButton>send_btn;
    QSharedPointer<QHBoxLayout>chat_send_line;

    QSharedPointer<QVBoxLayout>layout;
    ////////////////////////////////////////////////

    QSharedPointer<QTcpSocket>tcp_socket;
    QSharedPointer<InputDialog>input_dialog;


    virtual void keyPressEvent(QKeyEvent *event);

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

signals:
    void Press_Enter();


public slots:
    void Click_Btn();
    void Ready_Read();
    void disconnected();

};
#endif // WIDGET_H
//widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //
    //Network설정 및 다이얼로그 호출
    //

    //tcp_socket 할당
    tcp_socket.reset(new QTcpSocket);

    //Dialog 초기화 및 호출
    input_dialog.reset(new InputDialog(tcp_socket));

    input_dialog->exec();


    //
    //GUI 부분
    //

    //List View 부분
    chat_list_model.reset(new QStringListModel);

    chat_list_view.reset(new QListView(this));

    chat_list_view->setModel(chat_list_model.get());

    str_list.reset(new QStringList);

    //Chat edit부분
    chat_edit.reset(new QLineEdit);

    send_btn.reset(new QPushButton("전송"));

    chat_send_line.reset(new QHBoxLayout());

    chat_send_line->addWidget(chat_edit.get());

    chat_send_line->addWidget(send_btn.get());

    //레이아웃
    layout.reset(new QVBoxLayout(this));
    layout->addWidget(chat_list_view.get());
    layout->addLayout(chat_send_line.get());

    setLayout(layout.get());

    ////////////////////////////////////////////////////

    //전송 버튼 클릭하면 호출
    connect(send_btn.get(),&QPushButton::clicked,
            this,&Widget::Click_Btn);

    //엔터키 누르면 호출
    connect(this,SIGNAL(Press_Enter()),
            this,SLOT(Click_Btn()));

    //데이터 들어오면 호출
    connect(tcp_socket.get(),SIGNAL(readyRead()),
            this,SLOT(Ready_Read()));


    connect(tcp_socket.get(),SIGNAL(disconnected()),
            this,SLOT(disconnected()));



}

Widget::~Widget()
{
}

//전송 버튼 클릭하면 호출
//엔터키 누르면 호출
void Widget::Click_Btn()
{
    QString message = chat_edit->text();

    //예외가 일어나면 다시 보내기 쉽게 하기위해 setText를 위에 올려놓음
    chat_edit->setText("");


    tcp_socket->write(message.toStdString().c_str());

}

//데이터 들어오면 호출
void Widget::Ready_Read()
{
    if(tcp_socket->bytesAvailable()>=0)
    {
        QByteArray array = tcp_socket->readAll();
        *str_list<<array;

        chat_list_model->setStringList(*str_list);
    }

}

void Widget::disconnected()
{
    QMessageBox::critical(this,
                          "Critical Error",
                          "서버와 연결이 끊겼습니다.");

    tcp_socket->deleteLater();
    close();

}

//
void Widget::keyPressEvent(QKeyEvent *event)
{
    Q_UNUSED(event);

    switch(event->key())
    {
     case Qt::Key_Return:
        emit(Press_Enter());
        break;

    }
}



 

 

 

tcp_client_chat1.zip
0.01MB

 

공유하기

facebook twitter kakaoTalk kakaostory naver band
loading