《学习笔记》

QTcpSever用于监听,QTcpSocket用于连接客户端和服务端。

客户端连接服务端很简单,connectToHost(QHostAddress("IP", 666);,填写IP和端口就可以,连接成功后,再关联信号readyRead()就可以读取服务端发送过来的数据了

服务端首先监听某个端口,看是否有连接到该端口的机器,然后获取客户端连接的socket有两种方法:

1:关联信号newConnection(),在接受连接的过程中,应当是有一个队列,等待的连接都将放入连接队列中,在相应的槽函数中通过nextPendingConnection 函数可以得到该socket,进而可以进行通信,通信还是通过readyRead()信号,注意:这种方式返回的socket不可以用于另一个线程

2:另一种方法是继承QTcpSocket类重写incomingConnection (qintptr socketDescriptor) 函数 ,再有连接时这个函数会被系统调用,socketDescriptor  为套接字描述符,用这个描述符创建一个socket就可以了,即setSocketDescriptor  这个函数,描述符传给这个函数参数即可。

下面是我参照网上写的测试代码,可以同时有多个客户端连接到服务的同一个端口进行相互之间通信

服务端:

chatSever.h

#include <QObject>
#include <qtcpserver.h>
#include <QList>
#include <tcpsocket.h>
class chatSever : public QTcpServer
{
    Q_OBJECT
public:
    explicit chatSever(QObject *parent = 0, int port = 0);
    //重载
    void incomingConnection(int handle);
    void sendMsgToClient(QString strMsg, int nLength);
private:
    QList<tcpSocket*> m_clientSocketLst;    //用于保存客户端链表
signals:
public slots:
    void updateClientsData(QString msg, int length);
    void slotDisconnected(int descriptor);
};

chatSever.cpp

#include "chatsever.h"
chatSever::chatSever(QObject *parent, int port) : QTcpServer(parent)
{
    //监听
    listen(QHostAddress::Any, port);
}
void chatSever::incomingConnection(int handle)
{
    tcpSocket* clientSocket = new tcpSocket(this);
    clientSocket->setSocketDescriptor(handle);
    m_clientSocketLst.append(clientSocket);
    connect(clientSocket, SIGNAL(updateClientsData(QString,int)), this, SLOT(updateClientsData(QString,int)));
    //一个socket断开连接就从底层链表中删除对应的对象
    connect(clientSocket, SIGNAL(disconed(int)), this, SLOT(slotDisconnected(int)));
}
void chatSever::sendMsgToClient(QString strMsg, int nLength)
{
    updateClientsData(strMsg, nLength);
}
void chatSever::updateClientsData(QString msg, int length)
{
    for(int i = 0; i < m_clientSocketLst.count(); ++i)
    {
        QTcpSocket* itemClient = m_clientSocketLst.at(i);
        if(itemClient->write(msg.toLatin1().data(), length) != length)
        {
            qDebug() << "存在数据丢失";
            continue;
        }
    }
}
//删除指定的socket对象
void chatSever::slotDisconnected(int descriptor)
{
    qDebug() << "slotDisconnected";
    for(int i = 0; i < m_clientSocketLst.count(); ++i)
    {
        QTcpSocket* item = m_clientSocketLst.at(i);
        if(item->socketDescriptor() == descriptor)
        {
            m_clientSocketLst.removeAt(i);
            qDebug() << QString("socket列表 = : %1").arg(m_clientSocketLst.count());
            return;
        }
    }
}

tcpSocket.h

#include <QObject>
#include <QTcpSocket>
class tcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit tcpSocket(QObject *parent = 0);
signals:
    void updateClientsData(QString, int);
    void disconed(int);
public slots:
    void dataRecived();
    void slotDisconnected();
};

tcpSocket.cpp

#include "tcpsocket.h"
tcpSocket::tcpSocket(QObject *parent) : QTcpSocket(parent)
{
    //建立处理客户端的槽函数
    connect(this, SIGNAL(readyRead()), this, SLOT(dataRecived()));
    connect(this, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
}
//读取客户端信息
void tcpSocket::dataRecived()
{
    while (bytesAvailable() > 0) {//貌似解决了发送方粘包的问题,加上还是好
        char buf[1024] = {0};
        int nLength = bytesAvailable(); //返回可用字节数
        read(buf, nLength);
        QString str = buf;
        emit updateClientsData(str, nLength);
    }
}
void tcpSocket::slotDisconnected()
{
    qDebug() << "slotDisconnected";
    emit disconed(socketDescriptor());
}

chatSeverUI.h

#include <QWidget>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>
#include "chatsever.h"
namespace Ui {
class socketSever;
}
class chatSeverUI : public QWidget
{
    Q_OBJECT
public:
    explicit chatSeverUI(QWidget *parent = 0);
    ~chatSeverUI();
    void initSocket();
public slots:
//    void acceptConnection();
//    void readClient();
private slots:
    void on_pushButton_clicked();
private:
    Ui::socketSever *ui;
    QTcpServer* m_sever;
    QTcpSocket* m_clientConet;
    chatSever*  m_chatSever;
};

chatSeverUI.cpp

#include "chatseverUI.h"
#include "ui_socketsever.h"
#include <QtNetwork/qhostaddress.h>
chatSeverUI::chatSeverUI(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::socketSever)
{
    ui->setupUi(this);
    m_sever = NULL;
    m_clientConet = NULL;
    m_chatSever = NULL;
    initSocket();
}
chatSeverUI::~chatSeverUI()
{
    delete ui;
}
void chatSeverUI::initSocket()
{
    /*
     *  方法1
    m_sever = new QTcpServer(this);
    m_sever->listen(QHostAddress::Any, 6666);
    connect(m_sever, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
*/
    //方法2
    m_chatSever = new chatSever(this, 6666);
    if(!m_chatSever->isListening())
    {
        qDebug() << QString("unable to start the sever : %1").arg(m_chatSever->errorString());
    }
}
/*
void chatSeverUI::acceptConnection()
{
    m_clientConet = m_sever->nextPendingConnection();
    connect(m_clientConet, SIGNAL(readyRead()), this, SLOT(readClient()));
}
void chatSeverUI::readClient()
{
    QString str = m_clientConet->readAll();
    ui->severLabel->setText(str);
}
*/
void chatSeverUI::on_pushButton_clicked()
{
    QString str = ui->severEdit->text();
    //m_clientConet->write(str.toLatin1().data());
    m_chatSever->sendMsgToClient(str.toLatin1().data(), str.length());
}

main函数就很简单了,只是显示了各个窗口而已

    chatClientUI client1;
    client1.setWindowTitle("client");
    client1.show();
    chatClientUI client2;
    client2.setWindowTitle("client");
    client2.show();
    chatClientUI client3;
    client3.setWindowTitle("client");
    client3.show();
    chatSeverUI sever;
    sever.setWindowTitle("sever");
    sever.show();

界面是用QTDesign设计的,这里就不再多说了,初学笔记,如果有错误的地方欢迎指正,共同进步

Qt tcp socket编程相关推荐

  1. 转Go语言TCP Socket编程

    授权转载: Tony Bai 原文连接: https://tonybai.com/2015/11/17/tcp-programming-in-golang/ Golang的主要 设计目标之一就是面向大 ...

  2. golang TCP Socket编程

    Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不可少也是至关重要的一部分.在日常应用中,我们也可以看到Go中的net以及其subdirectories下的包均 ...

  3. Go语言TCP Socket编程

    2019独角兽企业重金招聘Python工程师标准>>> Go语言TCP Socket编程 Golang的 主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不 ...

  4. 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具。QQ_Chat

    代码下载地址 原博客地址 QQ_Chat 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具. (内含报告) 工具: Eclipse.Navicat for MySQL ...

  5. TCP socket 编程示例

    本代码为老师提供的示例程序 一.TCP socket 编程模型 二.使用TCP协议实现一个简单的通讯程序 1.服务器端 #include<stdlib.h> #include<std ...

  6. TCP socket编程记录(C语言)

    最近使用到TCP的socket编程,记录一下思路. TCP Socket 服务器编程思路 0.初始化套接字库 1.创建套接字----------2个(服务器本身需要一个套接字,客户端要返回一个套接字) ...

  7. TCP/IP详解 第十二章(10) TCP Socket 编程

    前言 不管面试 Java .C/C++.Python 等开发岗位, TCP 的知识点可以说是的必问的了. 任 TCP 虐我千百遍,我仍待 TCP 如初恋. 遥想小林当年校招时常因 TCP 面试题被刷, ...

  8. qt中socket编程

    1 文章概括 在qt中借助designer设计通信界面,然后使用QTcpServer,QTcpSocket编写服务器和客户端的程序. 首先建立两个工程,一个是客户端client,另一个是服务器端ser ...

  9. linux网络编程IPv6socket,简单的IPv6 UDP/TCP socket编程 -- 两台Linux实现简单的ipv6通信...

    配置: 1.两台linux用网线直接相连 2.手动配置两台linux的ipv6地址为: ifconfig eth0 add 2001:da8:e000::1:1:1 ifconfig eth0 add ...

最新文章

  1. 计算机二级vlookup引用怎么操作,VLOOKUP函数怎样引用二个条件
  2. K8S调度之pod亲和性
  3. linux mysql数据库定时备份
  4. Hollis原创|深入分析Java的编译原理
  5. OpenGL 视图和颜色的概念
  6. 在教学中利用计算机软件,计算机软件技术教学方法研究
  7. 【kafka】服务器上Kafka启动 Cannot allocate memory
  8. mysql存储过程 begin_MySQL存储过程的BEGIN和END
  9. 40个非常有创意的国外LOGO欣赏(上)
  10. 三枪手决斗问题的计算机解答
  11. STC学习:振动传感器
  12. linux内核nvme驱动程序,Linux中nvme驱动详解
  13. Python巨型文字游戏开发(带源码(1))
  14. 高仿TIMI页面易语言源码-已对接易游网络验证
  15. VOC检测格式数据分析和处理
  16. QNX Hypervisor —— 设备
  17. centos 安装virt-mannager
  18. LibreOJ 2060 食物链
  19. 关系网络lbs的应用_冒泡网王江:熟人关系将成LBS最重要商业模式
  20. U盘安装ubuntu20.04并优化

热门文章

  1. 天龙八部服务器端---共享内存的设计
  2. html 原型图片,可视化的JavaScript:原型继承(动图演示)
  3. JavaScript - Echarts经典教程-李游Leo-专题视频课程
  4. RPGMakerMV-事件页的出现条件和触发条件
  5. java-php-python-ssm-学生考勤管理系统-计算机毕业设计
  6. 帧同步 java_游戏同步方案——帧锁定同步
  7. 关于双通道,三通道,四通道内存体系结构你需要知道的事
  8. 使用jquery jcrop插件进行图片的截取与保存
  9. 【数据原理及应用 学习总结】第二章 关系数据库标准语言SQL(1)
  10. 什么是xml解析?xml解析的有几种常用的解析方式?