这里用Qt来简单设计实现一个场景,即:

(1)两端:服务器QtServer和客户端QtClient

(2)功能:服务端连接客户端,两者能够互相发送消息,传送文件,并且显示文件传送进度。

环境:VS20013 + Qt5.11.2 + Qt设计师

先看效果:

一、基本概念

客户端与服务器的基本概念不说了,关于TCP通信的三次握手等等,在《计算机网络》里都有详细介绍。这里说下两者是如何建立起通信连接的。

(1)IP地址:首先服务器和每一个客户端都有一个地址,即IP地址。(底层的MAC地址,不关心,因为TCP通信以及IP,是七层架构里面的网络层、传输层了,底层透明)。对于服务器来说,客户端的数量及地址是未知的,除非建立了连接。但是对于客户端来说,必须知道服务器的地址,因为两者之间的连接是由客户端主动发起的。

(1)端口号:软件层面的端口号,指的是 “应用层的各种协议进程与运输实体进行层间交互的一种地址”。简而言之,每一个TCP连接都是一个进程,操作系统需要为每个进程分配一个协议端口(即每一个客户端与服务端的连接,不是两台主机的连接,而是两个端口的连接)。但一台主机通常会有很多服务,很多进程,单靠一个IP地址不能标识某个具体的进程或者连接。所以用端口号来标识访问的目标服务器以及服务器的目标服务类型。端口号也有分类,但这不是本文的重点,详见教材。

(3)TCP连接:总的来说,TCP的连接管理分为单个阶段:建立连接 -> 数据传送 -> 连接释放。在(2)里说到,每个TCP连接的是具体IP地址的主机的两个端口,即TCP连接的两个端点由IP地址和端口号组成,这即是套接字(socket)的概念:套接字socket = IP + 端口号。

因此,我们要通过通过套接字来建立服务端与客户端的通信连接。

二、Qt相关类

QTcpSocket:提供套接字

QTcpServer:提供基于TCP的服务端,看官方文档的解释如下:

This class makes it possible to accept incoming TCP connections. You can specify the port or have QTcpServer pick one automatically. You can listen on a specific address or on all the machine’s addresses.

这个解释里面提到两点:

(1)指定端口:即开通哪一个端口用于建立TCP连接;

(2)监听:监听(1)中指定的端口是否有连接的请求。

三、写服务器和客户端的具体流程

(1)服务器:

创建并初始化 QTcpServer 对象;

启动服务器监听,通过调用成员函数 listen(QHostAddress::Any, 端口号);

连接 QTcpServer 对象的 newConnection 信号槽,当有客户端链接时,客户端会发送 newConnection 信号给服务器,触发槽函数接受链接(得到一个与客户端通信的套接字 QTcpSocket);

QTcpsocket 对象调用成员函数 write,发送数据给客户端;

当客户端有数据发送来,QTcpSocket 对象就会发送 readyRead 信号,关联槽函数读取数据;

连接 QTcpsocket 对象的 disconnected 信号槽,当客户端对象调用成员函数 close,会触发 QTcpsocket 对象的 disconnected 信号,进而触发槽函数进行相应处理。

(2)客户端:

创建并初始化 QTcpSocket 对象;

QTcpSocket 调用 connectToHost(QHostAddress("IP"), 端口号),连接服务器IP和端口号;

QTcpsocket 对象调用成员函数 write,发送数据给服务器;

连接QTcpsocket 对象的 connected() 信号槽,当客服端成功连接到服务器后触发 connected() 信号;

连接QTcpsocket 对象的 readyread() 信号槽,当客户端接收到服务端发来数据时触发 readyread() 信号;

连接 QTcpsocket 对象的 disconnected 信号槽,当客户端对象调用成员函数 close,会触发 QTcpsocket 对象的 disconnected 信号,进而触发槽函数进行相应处理。

四、UI设计

客户端:

服务端:

五、服务端实现

我们先要在工程文件中加入network

QT += core gui network

下面我们来看看服务器程序步骤:

1、初始化 QTcpServer 对象

TCP_server = new QTcpServer();

2、启动服务器监听

TCP_server->listen(QHostAddress::Any,9988);//9988为端口号

3、连接 QTcpServer 对象的 newConnection 信号槽,当有客户端链接时,客户端会发送 newConnection 信号给服务器,触发槽函数接受链接(得到一个与客户端通信的套接字 QTcpSocket)

connect(TCP_server, SIGNAL(newConnection()), this, SLOT(slot_newconnect()));

// 在与 newConnection 信号连接的槽函数中,获取与相应客户端通信的套接字

TCP_connectSocket = mServer->nextPendingConnection();

4、QTcpsocket 对象调用成员函数 write,发送数据给客户端

TCP_connectSocket->write(msg.toUtf8());

5、当客户端有数据发送来,QTcpSocket 对象就会发送 readyRead 信号,关联槽函数读取数据

connect(mSocket,SIGNAL(readyRead()),this,SLOT(slot_recvmessage()));

6、连接 QTcpsocket 对象的 disconnected 信号槽,当客户端对象调用成员函数 close,会触发 QTcpsocket 对象的 disconnected 信号,进而触发槽函数进行相应处理

connect(mSocket,SIGNAL(disconnected()),this,SLOT(slot_disconnect()));

TCP_Server.h

#ifndef TCP_SERVER_H

#define TCP_SERVER_H

#include

#include

#include

namespace Ui {

class TCP_Server;

}

class TCP_Server : public QWidget

{

Q_OBJECT

public:

explicit TCP_Server(QWidget *parent = nullptr);

~TCP_Server();

private slots:

void slot_newconnect(); //建立新连接的槽

void slot_sendmessage(); //发送消息的槽

void slot_recvmessage(); //接收消息的槽

void slot_disconnect(); //取消连接的槽

private:

Ui::m_tcpServer *ui;

QTcpServer *TCP_server; //QTcpServer服务器

QTcpSocket *TCP_connectSocket; //与客户端连接套接字

};

#endif // TCP_SERVER_H

TCP_Server.cpp

#include "tcp_server.h"

#include "ui_tcp_server.h"

#include

#include

TCP_Server::TCP_Server(QWidget *parent) :

QWidget(parent),

ui(new Ui::TCP_Server)

{

ui->setupUi(this);

//初始化

TCP_server = new QTcpServer();

TCP_connectSocket = nullptr;

connect(ui->pushButton_send,SIGNAL(clicked()),this,SLOT(slot_sendmessage()));

//调用listen函数监听同时绑定IP和端口号

if(TCP_server->listen(QHostAddress::LocalHost,10000)) //判断listen是否成功,成功则继续执行,连接新接收信号槽

{

this->connect(TCP_server,SIGNAL(newConnection()),this,SLOT(slot_newconnect())); //将服务器的新连接信号连接到接收新连接的槽

}

else

{

QMessageBox::critical(this,"错误","IP绑定错误,请关闭其它服务端或更改绑定端口号");

}

}

TCP_Server::~TCP_Server()

{

delete ui;

}

//建立新连接的槽

void TCP_Server::slot_newconnect()

{

if(TCP_server->hasPendingConnections()) //查询是否有新连接

{

TCP_connectSocket = TCP_server->nextPendingConnection(); //获取与真实客户端相连的客户端套接字

ui->textBrowser->append("client login!"); //若有新连接,则提示

this->connect(TCP_connectSocket,SIGNAL(readyRead()),this,SLOT(slot_recvmessage())); //连接客户端的套接字的有新消息信号到接收消息的槽

this->connect(TCP_connectSocket,SIGNAL(disconnected()),this,SLOT(slot_disconnect())); //连接客户端的套接字取消连接信号到取消连接槽

}

}

//发送消息的槽

void TCP_Server::slot_sendmessage()

{

QString sendMessage = ui->lineEdit->text(); //获取单行文本框内要发送的内容

if(TCP_connectSocket != nullptr && !sendMessage.isEmpty()) //确保有客户端连接,并且发送内容不为空

{

TCP_connectSocket->write(sendMessage.toLatin1()); //发送消息到客户端

QString localDispalyMessage = "send to client: " + sendMessage \

+ QDateTime::currentDateTime().toString(" yyyy-M-dd hh:mm:ss") + tr("\n");

ui->textBrowser->append(localDispalyMessage); //将要发送的内容显示在listwidget

}

ui->lineEdit->clear();

}

//接收消息的槽

void TCP_Server::slot_recvmessage()

{

if(TCP_connectSocket != nullptr) //与客户端连接的socket,不是nullptr,则说明有客户端存在

{

QByteArray array = TCP_connectSocket->readAll(); //接收消息

QHostAddress clientaddr = TCP_connectSocket->peerAddress(); //获得IP

int port = TCP_connectSocket->peerPort(); //获得端口号

QDateTime datetime = QDateTime::currentDateTime();

QString sendMessage = tr("recv from :") + clientaddr.toString() + tr(" : ") \

+ QString::number(port) + tr(" ") + datetime.toString("yyyy-M-dd hh:mm:ss") + tr("\n");

sendMessage += array;

ui->textBrowser->append(sendMessage); //将接收到的内容加入到listwidget

}

}

//取消连接的槽

void TCP_Server::slot_disconnect()

{

if(TCP_connectSocket != nullptr)

{

ui->textBrowser->append("client logout!");

TCP_connectSocket->close(); //关闭客户端

TCP_connectSocket->deleteLater();

}

}

六、客户端实现

下面我们来看看客户端程序步骤:

1、初始化 QTcpSocket 对象

TCP_server = new QTcpSocket();

2、QTcpSocket 调用 connectToHost(QHostAddress("IP"), 端口号),连接服务器IP和端口号

TCP_sendMesSocket->connectToHost("127.0.0.1",10000);

3、QTcpsocket 对象调用成员函数 write,发送数据给服务器

//取发送信息编辑框内容

QString msg = ui->sendEdit->toPlainText();

TCP_sendMesSocket->write(msg.toUtf8());//转编码

4、连接QTcpsocket 对象的 connected() 信号槽,当客服端成功连接到服务器后触发 connected() 信号

connect(TCP_sendMesSocket,SIGNAL(connected()),this,SLOT(slot_connected()));

5、连接QTcpsocket 对象的 readyread() 信号槽,当客户端接收到服务端发来数据时触发 readyread() 信号

connect(TCP_sendMesSocket,SIGNAL(readyRead()),this,SLOT(slot_recvmessage()));

6、连接 QTcpsocket 对象的 disconnected 信号槽,当客户端对象调用成员函数 close,会触发 QTcpsocket 对象的 disconnected 信号,进而触发槽函数进行相应处理

connect(TCP_sendMesSocket, SIGNAL(disconnected()), this, SLOT(slot_disconnect()));

TCP_Client.h

#ifndef TCP_CLIENT_H

#define TCP_CLIENT_H

#include

#include

namespace Ui {

class TCP_Client;

}

class TCP_Client : public QWidget

{

Q_OBJECT

public:

explicit TCP_Client(QWidget *parent = nullptr);

~TCP_Client();

//与按钮交互,故函数都设置为槽函数

private slots:

void slot_connected(); //处理成功连接到服务器的槽

void slot_sendmessage(); //发送消息到服务器的槽

void slot_recvmessage(); //接收来自服务器的消息的槽

void slot_disconnect(); //取消与服务器连接的槽

private:

Ui::TCP_Client *ui;

bool isconnetion; //判断是否连接到服务器的标志位

QTcpSocket *TCP_sendMesSocket; //发送消息套接字

};

#endif // TCP_CLIENT_H

TCP_Client.cpp

#include "tcp_client.h"

#include "ui_tcp_client.h"

#include

#include

#include

TCP_Client::TCP_Client(QWidget *parent) :

QWidget(parent),

ui(new Ui::TCP_Client)

{

ui->setupUi(this);

/*** 初始化TCP ***/

this->setWindowTitle("TCP客户端");

this->isconnetion = false;

//初始化sendMesSocket

this->TCP_sendMesSocket = new QTcpSocket();

//终止之前的连接,重置套接字

TCP_sendMesSocket->abort();

//给定IP和端口号,连接服务器

this->TCP_sendMesSocket->connectToHost("127.0.0.1",10000); //QHostAddress::LocalHost等于127.0.0.1,所以两者都可以互相替换

//成功连接服务器的connected()信号连接到slot_connected() (注意:不是connect()信号)

connect(TCP_sendMesSocket,SIGNAL(connected()),this,SLOT(slot_connected()));

//发送按钮的clicked()信号连接到slot_sendmessage()

connect(ui->pushButton_send,SIGNAL(clicked()),this,SLOT(slot_sendmessage()));

//有新数据到达时的readyread()信号连接到slot_recvmessage()

connect(TCP_sendMesSocket,SIGNAL(readyRead()),this,SLOT(slot_recvmessage()));

//与服务器断开连接的disconnected()信号连接到slot_disconnect()

connect(TCP_sendMesSocket,SIGNAL(disconnected()),this,SLOT(slot_disconnect()));

}

TCP_Client::~TCP_Client()

{

delete ui;

}

//处理成功连接到服务器的槽

void TCP_Client::slot_connected()

{

this->isconnetion = true;

ui->textBrowser->append(tr("与服务器连接成功:") + QDateTime::currentDateTime().toString("yyyy-M-dd hh:mm:ss"));

}

//发送消息到服务器的槽

void TCP_Client::slot_sendmessage()

{

if(this->isconnetion)

{

QString sendMessage = ui->lineEdit->text(); //从单行文本框获得要发送消息

if(!sendMessage.isEmpty())

{

//发送消息到服务器

this->TCP_sendMesSocket->write(sendMessage.toLatin1());

//本地显示发送的消息

QString localDispalyMessage = tr("send to server: ") + sendMessage \

+ QDateTime::currentDateTime().toString(" yyyy-M-dd hh:mm:ss") + tr("\n");

ui->textBrowser->append(localDispalyMessage);

}

else

QMessageBox::warning(this,"错误","消息不能为空!",QMessageBox::Ok);

}

else

QMessageBox::warning(this,"错误","未连接到服务器!",QMessageBox::Ok);

ui->lineEdit->clear();

}

//接收来自服务器的消息的槽

void TCP_Client::slot_recvmessage()

{

//接收来自服务器的消息

QByteArray byteArray = this->TCP_sendMesSocket->readAll();

QString recvMessage = tr("recv from server: ") + byteArray + QDateTime::currentDateTime().toString(" yyyy-M-dd hh:mm:ss") + tr("\n");

ui->textBrowser->append(recvMessage);

}

//取消与服务器连接的槽

void TCP_Client::slot_disconnect()

{

QMessageBox::warning(this,"警告","与服务器的连接中断",QMessageBox::Ok);

//关闭并随后删除socket

TCP_sendMesSocket->close();

TCP_sendMesSocket->deleteLater();

}

参考:

qt向服务器传输文字_Qt实现客户端与服务器消息发送相关推荐

  1. qt向服务器传输文字_Qt 模拟 HTTP 表单提交文字或文件到服务器

    传统通过 HTTP 表单的方式来上传文件在 Web 中实现是非常简单的,一个表单中加几个域填写上对应的内容提交就可以了,但如果通过 Qt 来实现就相对麻烦一点,不过我都总结好了代码,直接使用就可以了. ...

  2. bs客户端跨服务器管理文件,bs架构客户端和服务器

    bs架构客户端和服务器 内容精选 换一换 SSL(安全套接层,Secure Sockets Layer)是一种安全协议,目的是为互联网通信,提供安全及数据完整性保障.云容器实例支持上传SSL证书,在使 ...

  3. qt调用mysql加密接口_Qt实现客户端/服务器端登录验证|数据传输使用md5加密 | 学步园...

    要完成两个模块:客户端和服务器端.即实现通过客户端向远程服务器段发送数据来验证,以此来实现简单的认证功能.同时,客户端在向服务器段发送的数据通过md5加密后再传送. 开发环境与工具 开发操作系统:Wi ...

  4. 客户端与服务器信息交互的流程,客户端与服务器的交互流程

    客户端与服务器的交互流程 内容精选 换一换 ecFlow是一个工作流管理器,使用户可以在受控环境中运行大量程序,彼此之间以及时间上相互依赖.它提供了对硬件和软件故障的容忍度,并具有良好的重启功能.ec ...

  5. 天正服务器不显示,天正软件客户端修改服务器地址

    天正软件客户端修改服务器地址 内容精选 换一换 如果IP经过NAT/WAF,则只能获取到NAT/WAF转化后的IP地址,无法获取到NAT/WAF前的IP地址.如果客户端为容器,只能获取到容器所在主机的 ...

  6. 用友t3 虚拟服务器设置,用友t3客户端与服务器设置

    用友t3客户端与服务器设置 内容精选 换一换 本章节指导您使用MongoDB客户端和Robo 3T工具,通过公网连接GaussDB(for Mongo)集群实例.操作系统使用场景:弹性云服务器的操作系 ...

  7. 安卓模拟器获取服务器信息出错,安卓模拟器客户端与服务器不同步

    安卓模拟器客户端与服务器不同步 内容精选 换一换 目前从本地或虚拟机通过DRS备份迁移功能直接迁移到本云RDS for SQL Server实例上,在迁移完成后还需要针对Login账号,DBLink, ...

  8. udp服务器php代码例子,Java客户端PHP服务器UDP穿孔示例代码

    我正在一个需要pe2p服务器的项目中工作,但是我还没有找到任何Java客户端php服务器示例代码.我了解udp打孔工作原理的概念,但是我无法在代码中工作. 我尝试过的 TheSocket.java p ...

  9. 服务器提取用户信息,获取客户端和服务器信息

    运行效果: 前台设计界面: 前台代码: 无标题页 服务器端环境 服务器名称: 服务器的IIS: 服务器的IP地址: 服务器的域名: 服务器的操作系统: 服务器的端口: 服务器的路径: 域名主机: 服务 ...

最新文章

  1. Numpy入门教程:10. 统计相关
  2. np.concatenate
  3. 利用序列化与反序列化对Java对象进行深度复制
  4. jsp 中forward 和 Redirect 的用法区别
  5. 两款开源Web功能测试工具
  6. Java学习笔记(基本数据类型和变量命名规则)
  7. Creating a Pager Control for ASP.NET以及Dino Esposito 分页组件的一个 Bug
  8. python 列表有没有顺序_python-如何获取列表的所有顺序,以使该列表等于另一个列表?...
  9. Eclipse JaveEE版本
  10. 基于node.js和Vue的音乐管理系统 /音乐网站的设计与实现
  11. 安装前端插件 FeHelper
  12. SEO助手-免费万能SEO网站优化小助手
  13. matlab fig 字体,关于.fig文件的font,请教达人,多谢
  14. 数据库事务的四大特性 AICD
  15. linux操作系统adsl 上网设置,Linux操作系统上ADSL拨号上网的方法详解
  16. 关于TIdTCPClient的几种方法
  17. 软件测试技术什么是分支覆盖,分支覆盖率测试是什么?
  18. IT人的架构书单:如何赋予软件以灵魂
  19. 黑科技教程——伪装 sn
  20. html的颜色有多少种?

热门文章

  1. Hive高阶分析函数
  2. Web作业:specific word count (index of )
  3. Linux_CentOS 7下Nginx服务器的安装配置
  4. 网络通信协议八之UDP协议详解
  5. fcn+caffe+siftflow实验记录
  6. 【ESP8266】发送HTTP请求
  7. firebug js版
  8. JavaScript 的 defer 与 async
  9. [hdu1242]优先队列
  10. 小组站立会议之冲次会议2