《QT从基础到进阶·十六》QT实现客户端和服务端的简单交互

QT版本:5.15.2

VS版本:2019

客户端程序主要包含三块:连接服务器,发送消息,关闭客户端

服务端程序主要包含三块:打开消息监听,接收消息并反馈,关闭服务端

1、先打开服务端监听功能

cpp 复制代码
void TCPServer::listen()
{
    initWsaData();
    //创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);
    //创建地址簇对象
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9888);
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    //绑定套接字
    int bindStatus = ::bind(sock, (struct sockaddr*)&sin, sizeof(sin));
    if (bindStatus == -1) {
        qDebug() << "socket bind failed!" << endl;
        ui.textBrowser->setText("socket bind failed!");
        return;
    }
    else {
        qDebug() << "socket bind success!" << endl;
        ui.textBrowser->setText("socket bind success!");
    }
    //将套接字设为监听模式,等待客户端连接
    int listenStatus = ::listen(sock, 128);
    if (listenStatus == -1) {
        qDebug() << "listen failed" << endl;
        ui.textBrowser->setText("listen failed");
        return;
    }
    else {
        qDebug() << "set listen success, server is listening..." << endl;
        ui.textBrowser->setText("set listen success, server is listening...");
    }
    //收到请求主后,接收连接请求,返回一个对应此次连接的新套接字
    //接受连接请求
    sockaddr_in sinAccept;
    int len = sizeof(sin);
    newSock = accept(sock, (struct sockaddr*)&sinAccept, &len);
    if (newSock == SOCKET_ERROR) {
        qDebug() << "connect failed" << endl;
        ui.textBrowser->setText("connect failed");
        return;
    }
    else {
        qDebug() << "connect success, ready to recv data" << endl;
        ui.textBrowser->setText("connect success, ready to recv data");
    }
}

2、点击客户端connect连接服务端

cpp 复制代码
void TCPClient::Connect(const std::string ip, const int port)
{
    bool res = initWsaData(); //初始化套接字库
    if (!res) return;

    //常用协议族:AF_UNIX(本机通信)AF_INET(TCP/IP -- IPv4)AF_INET6(TCP/IP -- IPv6)
    //套接字类型:SOCK_STREAM(TCP流)SOCK_DGRAM(UDP数据报)SOCK_RAW(原始套接字)
    //protocol"一般设置为"0"
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == SOCKET_ERROR) {
        qDebug() << "Failed to create socket" << endl;
        ui.textBrowser->setText("Failed to create socket");
        return;
    }
    else {
        qDebug() << "Socket created successfully" << endl;
        ui.textBrowser->setText("Socket created successfully");
    }

    //设置地址
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = inet_addr(ip.c_str());

    //连接服务器
    int connStatus = ::connect(sock, (struct sockaddr*)&sin, sizeof(sin));
    if (connStatus == -1) {
        qDebug() << "Failed to connect to the server" << endl;
        ui.textBrowser->setText("Failed to connect to the server");
        return;
    }
}

3、在客户端输入消息点击send发送到服务端

cpp 复制代码
void TCPClient::DataTransmission()
{
    string msg = ui.lineEdit->text().toStdString();
    /*char sendBuf[MAX_MSG_SIZE];
    memset(sendBuf, 0, MAX_MSG_SIZE)*/;
    
    int sendStatus = send(sock, msg.c_str(), MAX_MSG_SIZE, 0);
    if (sendStatus == 0) {
        qDebug() << "Failed to send information" << endl;
        ui.textBrowser->setText("Failed to send information");

        //关闭套接字及套接字库
        closesocket(sock);
        WSACleanup();
        return;
    }

    char recvBuf[MAX_MSG_SIZE];
    memset(recvBuf, 0, MAX_MSG_SIZE);
    int recvStatus = recv(sock, recvBuf, MAX_MSG_SIZE, 0);
    if (recvStatus == -1) {
        qDebug() << "Failed to receive message" << endl;
        ui.textBrowser->setText("Failed to receive message");

        //关闭套接字及套接字库
       /* closesocket(sock);
        WSACleanup();*/
        return;
    }
    else {
        qDebug() << "Server information:" << recvBuf << endl;
        string msg = "---------Server information:" + string(recvBuf);
        ui.textBrowser->setText(QString::fromStdString(msg));
    }
}

4、在服务端点击send接收客户端消息并通知客户端已收到消息

cpp 复制代码
void TCPServer::DataTransmission()
{
    //用新建立的套接字和客户端进行通信
    char recvBuf[MAX_MSG_SIZE];
    char sendBuf[MAX_MSG_SIZE];
    memset(recvBuf, 0, MAX_MSG_SIZE);
    memset(sendBuf, 0, MAX_MSG_SIZE);
    if (true) {
        int recvStatus = recv(newSock, recvBuf, MAX_MSG_SIZE, 0);
        if (recvStatus == -1) {
            qDebug() << "recv data failed" << endl;
            ui.textBrowser->setText("recv data failed");
            closesocket(sock);
            closesocket(newSock);
            WSACleanup();
            return;
        }
        else {
            qDebug() << "recv client new msg:" << recvBuf << endl;
            string msg = "--------------recv client new msg:" + string(recvBuf);
            ui.textBrowser->setText(QString::fromStdString(msg));
        }
        /*qDebug() << "请输入回复消息:";
        cin >> sendBuf;*/
        string sendMsg = "has recv msg-------";
        int sendStatus = send(newSock, sendMsg.c_str(), sizeof(sendBuf), 0);
        if (sendStatus == -1) {
            qDebug() << "msg send failed" << endl;
            ui.textBrowser->setText("msg send failed");
            closesocket(sock);
            closesocket(newSock);
            WSACleanup();
            return;
        }
    }
}

=====================

完整源码下载

📢博客主页: 主页

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

📢本文由 梦回阑珊 原创,首发于 CSDN,转载注明出处🙉

📢代码改变世界,你来改变代码!✨

相关推荐
武子康12 分钟前
h3.c 的两个权重槽,怎样把内存压力换成 SSD 等待
c语言·人工智能·agent
bksczm1 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
春涧草茶1 小时前
慢就是快16-1协程
开发语言·前端·python
Dovis(誓平步青云)2 小时前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
做科研的周师兄2 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
闻缺陷则喜何志丹2 小时前
【C++特性】四种类型转
c++·算法·类型转换
.痞老板.3 小时前
java ee--计算机是如何工作的
java·开发语言·java-ee
奇树谦3 小时前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构
青梅味猪大肠3 小时前
【操作系统-60】临近适应算法
java·linux·开发语言·嵌入式硬件·算法·操作系统
starzy19904 小时前
深入理解Scala可变Map:动态构建场景下的性能与设计权衡
开发语言·scala