版权声明:若无来源注明,Techie亮博客文章均为原创。 转载请以链接形式标明本文标题和地址:
本文标题:QTcpSocket-Qt使用Tcp通讯实现服务端和客户端     本文地址:https://www.techieliang.com/2017/12/530/

1. 基本功能

详细说明请见官方文档

1.1. pro文件配置

使用Qt网络功能需要在pro文件增加网络库

  1. QT += network

1.2. QTcpServer服务端建立

  1. QTcpServer server = new QTcpServer();
  2. connect(server,
  3. &QTcpServer::newConnection,
  4. this,
  5. &MainWindow::server_New_Connect);//监听
  6. if(!server->listen(QHostAddress::Any, 8000)) {
  7. qDebug()<<server->errorString(); //错误信息
  8. }

创建server对象以后首先要监听客户端的连接,通过listen函数可以开启监听,需要指定监听的ip和端口号,ip可使用QHostAddress::Any

QTcpServer当有新客户端连接时会发出QTcpServer::newConnection的信号,只需要关联到自定义的槽即可。

  1. void MainWindow::server_New_Connect() {
  2. //获取客户端连接
  3. auto socket_temp = server->nextPendingConnection();//根据当前新连接创建一个QTepSocket
  4. m_socket=socket_temp;//记录此连接用于后续数据读写
  5. //连接QTcpSocket的信号槽,以读取新数据
  6. QObject::connect(socket_temp, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
  7. //当断开连接时发出的信号
  8. QObject::connect(socket_temp, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
  9. }

上述为一个新连接到来的槽函数范例,利用nextPendingConnection获取到新连接的socket,存储此socket,并关联对应的信号

主要有两个:接收到新数据的信号以及连接断开的信号。

当连接断开可以通过响应信号槽机制实现断开后的操作。

1.3. 客户端建立

客户端为主动连接方,不需要监听,直接建立QTcpSocket即可

  1. m_socket = new QTcpSocket;
  2. m_socket->connectToHost("127.0.0.1",80100,QTcpSocket::ReadWrite);
  3. connect(m_socket,SIGNAL(connected()),this,SLOT(connected()));

上述例子使用的是信号槽方式等待连接成功,也可以使用阻塞方式:waitForConnected,等到连接成功才会执行后续代码,不需要建立新的槽函数。

通过connectToHost连接指定ip和端口,同时将socket的连接成功的信号与对应槽连接,当连接成功可以将自定义的标记位置为true,可进行相应的收发。

  1. void MainWindow::connected() {
  2. m_is_connected = true;
  3. connect(this->socket,SIGNAL(readyRead()),this,SLOT(readyread())); //连接接收消息槽
  4. QObject::connect(socket_temp,?&QTcpSocket::disconnected,?this,?&MainWindow::socket_Disconnected);//断开连接
  5. }

当连接成功建议将接收和断开连接的信号进行connect

1.4. 消息收发

  • 不阻塞收发:

无论客户端还是服务端只有在建立连接时有差异,后续的消息收发都相同。

首先通过QTcpSocket::close()可以主动断开连接,无论客户端服务端都可以执行主动断开

通过readyRead()信号可以在接到信息后进行信息操作,在槽中执行QTcpSocket::readAll()可以读取缓冲区所有数据

QTcpSocket::send()可发送信息,调用flush可立即发送缓冲区的数据,不需等待。

  • 阻塞收发:

Qt同时提供了阻塞收发及连接、断开连接的函数:

virtual bool waitForConnected(int msecs = 30000)
virtual bool waitForDisconnected(int msecs = 30000)
virtual bool waitForBytesWritten(int msecs = 30000)
virtual bool waitForReadyRead(int msecs = 30000)

通过上述函数可以实现阻塞连接、断开连接、发送、接收数据内容

2. 其他

2.1. 实现单服务器多客户端通讯

网上大部分例子都是单服务器通讯,若不做修改连接多个客户端,会出现只有最后一个通讯有效的情况。

主要原因是在监听到新连接时的处理方式不当:

  1. connect(server, &QTcpServer::newConnection, this, &MainWindow::server_New_Connect);//监听
  2. if(!server->listen(QHostAddress::Any, 8000)) {
  3. qDebug()<<server->errorString(); //错误信息
  4. }

注意上述代码在服务端收到信连接时会固定的调用一个槽函数,而槽函数往往写成下述样式:

  1. void MainWindow::server_New_Connect() {
  2. //获取客户端连接
  3. auto socket_temp = server->nextPendingConnection();//根据当前新连接创建一个QTepSocket
  4. m_socket=socket_temp;//记录此连接用于后续数据读写
  5. //连接QTcpSocket的信号槽,以读取新数据
  6. QObject::connect(socket_temp, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
  7. //当断开连接时发出的信号
  8. QObject::connect(socket_temp, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
  9. }

m_socket=socket_temp;//记录此连接用于后续数据读写

这一行等于是每次有一个新的连接都替换了旧的连接记录,自然之友最后一个客户端连接有效,正确的可以建立list存储所有连接的socket,当收发数据时根据需要指定socket进行收发。这时将disconnected信号进行connect就具有了作用,当某个连接断开时应该从所有连接链表中删除此记录。

由nextPendingConnection创建的QTcpSocket,会有QTcpServer维护,当QTcpServer销毁是会自动销毁所有创建的socket,若想提前释放内容可以在disconnected信号发生时主动delete

2.2. 关于QTcpServer

可能考虑到跨平台问题,Qt使用select实现io多路复用,连接数量限制是1024,若需要poll,epoll等可使用其他库,比如libevent

2.3. 关于数据收发

可以通过setReadBufferSize设置接收缓冲区大小(Qt内部缓冲区大小)

当发送端发送的数据超过buffer大小时会触发readyread信号,需要注意对此情况的处理方法,可以考虑在消息头增加消息长度

未验证:Qt有自己内部的缓冲区,消息发送到系统缓冲区,Qt会读取出来,而调用的Qt函数readall等实际上读取的是Qt内部缓冲区而非系统缓冲区

QTcpSocket-Qt使用Tcp通讯实现服务端和客户端的更多相关文章

  1. QUdpSocket-Qt使用Udp通讯实现服务端和客户端

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QUdpSocket-Qt使用Udp通讯实现服务端和客户端     本文地址:https:// ...

  2. TCP中的服务端与客户端的实现

    TCP中首先要在服务端开启监听,这样才可以从客户端链接 using System; using System.Collections.Generic; using System.Linq; using ...

  3. Unity使用C#实现简单Scoket连接及服务端与客户端通讯

    简介: 网络编程是个很有意思的事情,偶然翻出来很久之前刚开始看Socket的时候写的一个实例,贴出来吧 Unity中实现简单的Socket连接,c#中提供了丰富的API,直接上代码. 服务端代码: [ ...

  4. 从零开始开发IM(即时通讯)服务端(二)

    好消息:IM1.0.0版本已经上线啦,支持特性: 私聊发送文本/文件 已发送/已送达/已读回执 支持使用ldap登录 支持接入外部的登录认证系统 提供客户端jar包,方便客户端开发 github链接: ...

  5. [C语言]一个很实用的服务端和客户端进行TCP通信的实例

    本文给出一个很实用的服务端和客户端进行TCP通信的小例子.具体实现上非常简单,只是平时编写类似程序,具体步骤经常忘记,还要总是查,暂且将其记下来,方便以后参考. (1)客户端程序,编写一个文件clie ...

  6. Java TCP服务端向客户端发送图片

    /** * 1.创建TCP服务端,TCP客户端 * 2.服务端等待客户端连接,客户端连接后,服务端向客户端写入图片 * 3.客户端收到后进行文件保存 * @author Administrator * ...

  7. 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端

    [转]TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端).UDP客户端 目录 说明 TCP/UDP通信主要结构 管理多个Socket的解决方案 框架中TCP部分的使用 框架中UDP ...

  8. vertx 从Tcp服务端和客户端开始翻译

    写TCP 服务器和客户端 vert.x能够使你很容易写出非阻塞的TCP客户端和服务器 创建一个TCP服务 最简单的创建TCP服务的方法是使用默认的配置:如下 NetServer server = ve ...

  9. C#Winform窗体实现服务端和客户端通信例子(TCP/IP)

    Winform窗体实现服务端和客户端通信的例子,是参考这个地址 http://www.cnblogs.com/longwu/archive/2011/08/25/2153636.html 进行了一些异 ...

随机推荐

  1. MAC远程桌面连接问题

    如图,始终提示“证书或相关链无效.” 点击“取消” 点击“编辑连接...” 点击“打开” 点击“安全性” 选择“即使验证失败,也始终连接” OK

  2. python3 scrapy 使用selenium 模拟浏览器操作

    零. 在用scrapy爬取数据中,有写是通过js返回的数据,如果我们每个都要获取,那就会相当麻烦,而且查看源码也看不到数据的,所以能不能像浏览器一样去操作他呢? 所以有了-> Selenium ...

  3. 设置Nginx日志

    在nginx.conf文件或vhosts/*.conf文件中的access_log日志中指定级别为main. http { include mime.types; default_type appli ...

  4. 使用ksync 加速基于k8s 的应用开发

      ksync 实际上实现了类似 docker docker run -v /foo:/bar 的功能,可以加速我们应用的开发&&运行 安装 mac os curl https://v ...

  5. 从 Excel 表格粘贴到 浏览器表格中

    从 Excel 表格粘贴到 浏览器表格中 由于 Excel 用途广泛,所以在导入时用到很多. 但是更多人的喜欢使用复制粘贴. 在网上找了一圈有找到一个开源项目,可以将 Excel 粘贴到 HTML 中 ...

  6. emacs之配置之初始目录设置

    emacsConfig/dir-setting.el (setq default-directory "~/" )

  7. 黄聪:Navicat for MySQL的1577错误解决

    今天尝试使用了Windows下的可视化mysql数据库管理工具Navicat,界面清爽,易操作上手,感觉还不错. 不过当连接上mysql后,无论打开任何一个数据库,都会提示:1577 – Cannot ...

  8. find 和 find_all 用法

    soup = BeautifulSoup(requests.get(url).text, 'html.parser') soup.find('span', class_='item_hot_topic ...

  9. Linux下添加php的zip模块

    今天早上开发的人员过来跟我说,测试机上的XX项目报了个错: include(ZipArchive.php): failed to open stream: No such file or direct ...

  10. http://bbs.csdn.net/topics/392028373

    博客 学院http://bbs.csdn.net/topics/392028373 下载 GitChat 更多 登录注册   首页 精选版块 论坛牛人 论坛地图 专家问答 我要发贴 论坛帮助     ...