如何使用QT5编写一个利用TCP协议的聊天室 (一)编写一个TCP的服务器端

关于TCP协议的知识点

TCP协议是一种基于传输层的协议,具有可靠性,需要连接,工作方式为全双工,传输速度相较于UPD更慢的特点,一般用于传输大量的数据,传输过程不允许丢包的情况.一般情况下聊天类软件均采用UDP协议,此处采用TCP是为了了解TCP的特点,以及保证实验过程不因为丢包影响实验结果.

实验思路

我将服务器端分为三个部分,每个部分分别实现不同的功能.

第一部分:服务器端的外形设计,服务器端应有一个对话框显示客户端的登入登出以及在登入期间所发送的信息,一个文本框显示端口号,一个按钮来开启服务器

第二部分:服务器功能,服务器需要监听一个固定的端口,当有客户端接入该端口时,创建一个TCP套接字对象来为该客户服务(以便在服务端实现与客户端的通信),服务器还需要能存储每一个接入的客户端的信息

第三部分:一个TCP套接字对象的功能,该对象需要能读取套接字中的数据,将其传输给服务器,

具体实现

以下代码为.cpp中的部分代码,代码参考<<Qt5开发及实例(第三版)>>,若内容有错误理解希望能提出指正

第一部分:

 1 Tcpserver::Tcpserver(QWidget *parent,Qt::WindowFlags f)//构造函数
 2     : QDialog(parent,f)
 3 {
 4     setWindowTitle(tr("TCP Server"));//更改名称
 5     ContentListWidget = new QListWidget;//初始化一个对话框,显示相应的信息
 6     PortLabel = new QLabel(tr("端口"));初始化一个标签,让其显示相应的内容
 7     PortLineEdit = new QLineEdit;//初始化一个对话框显示固定的端口号
 8     CreateBtn = new QPushButton(tr("create chat room"));//初始化一个按钮,让其显示相应的内容
 9     mainLayout = new QGridLayout(this);//初始化一个QGridLayout的布局,并将所有部件塞进布局
10     mainLayout->addWidget(ContentListWidget,0,0,1,2);
11     mainLayout->addWidget(PortLabel,1,0);
12     mainLayout->addWidget(PortLineEdit,1,1);
13     mainLayout->addWidget(CreateBtn,2,0,1,2);
14     port = 8010;//监听8010端口
15     PortLineEdit->setText(QString::number(port));//将端口号显示
16     connect(CreateBtn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));//按下按钮发送信号,触发槽函数,该槽函数功能为创建一个服务器
17 }
18 Tcpserver::~Tcpserver()//析构函数
19 {
20 }
21 void Tcpserver::slotCreateServer()//槽函数的实现
22 {
23     server = new Server(this,port);//创建一个Server对象,并将端口号传给该对象,是其对该端口进行监听
24     connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));//若server发送updateServer信号,触发tcpserver的槽函数updateServer
25     //使其更新对话框内容
26     CreateBtn->setEnabled(false);//创建服务器之后 无法再点击该按钮
27 }
28 void Tcpserver::updateServer(QString msg,int length)//更新内容的槽函数
29 {
30     ContentListWidget->addItem(msg.left(length));
31 }
第二部分:
 1 Server::Server(QObject *parent,int port) : QTcpServer(parent)
 2 {
 3     listen(QHostAddress::Any,port);//在指定的端口对任意地址监听
 4 }
 5 void Server::incomingConnection(qintptr socketDescriptor)//当出现一个新的连接的时候,TcpServer便会触发incomingConnection()函数,每有一个新的连接都会触发一次,即都创建一个新的对象
 6 {
 7     TcpClientSocket *tcpClientSocket = new TcpClientSocket(this);//创建一个新的TcpClientSocket与客户端通信
 8     //出现一个新连接才会创建一个 TcpClientSocket 的对象,如果连接后有数据传入,该对象将其读下来 通过updateClient信号来发送
 9     connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));//连接TcpClientSocket的updateClients信号
10     //当有新数据传入后,TcpClientSocket便会发出updateClients的信号,此时触发Server中的updateClients的槽函数,将信号中的msg与length传入该槽函数
11     connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));//连接TcpClientSocket中的disconnected信号
12     //当TcpClientSocket的对象断开连接后,发出disconnected的信号,此时触发Server中的slotDisconnected的槽函数
13     tcpClientSocket->setSocketDescriptor(socketDescriptor);//将新创建的TcpClientSocket的套接字描述符指定为参数socketDescriptor
14     tcpClientSocketList.append(tcpClientSocket);//将tcpClientSocket这个对象添加入tcpClientSocketList这个列表中
15 }
16 void Server::updateClients(QString msg,int length)
17 {
18     emit updateServer(msg,length);//发出updateServer的信号,通知服务器对话框更新相应的显示状态
19     for(int i = 0;i<tcpClientSocketList.count();i++)//实现广播,即将新发送到服务器中的数据进行广播,发送到每一个连接的对象,进行同步更新对话框
20     {
21         QTcpSocket *item = tcpClientSocketList.at(i);//
22         if(item->write(msg.toLatin1(),length)!=length)
23         {
24             continue;
25         }
26     }
27 }
28 void Server::slotDisconnected(int descriptor)//从tcpClientSocketList列表中将断开连接的TcpClientSocket对象删除
29 {
30     for (int i  = 0;i<tcpClientSocketList.count();i++) {
31         QTcpSocket *item = tcpClientSocketList.at(i);
32         if(item->socketDescriptor()==descriptor)
33         {
34             tcpClientSocketList.removeAt(i);
35             return;
36         }
37     }
38     return;
39 }
第三部分:


 1 TcpClientSocket::TcpClientSocket(QObject *parent)
 2 {
 3     connect(this,SIGNAL(readyRead()),this,SLOT(dateReceived()));//readyRead()是QIODevice的一个信号函数,由QTcpSocket继承而来,在有数据来时发出信号
 4     connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));//disconnected()是QIODevice的一个信号函数,由QTcpSocket,断开连接时发出信号
 5 }
 6 void TcpClientSocket::dateReceived()
 7 {
 8     while(bytesAvailable()>0)//当有数据来时,bytesAvailable()从套接字中检测所来的数据,返回等待读取的传入字节数
 9     {
10         int length = bytesAvailable();
11         char buf[1024];
12         read(buf,length);//将套接字中的数据读取到buf中,读取长度为length
13         QString msg = buf;
14         emit updateClients(msg,length);//发出信号
15     }
16 }
17 void TcpClientSocket::slotDisconnected()
18 {
19     emit disconnected(this->socketDescriptor());//发出disconnected信号
20 }

原文地址:https://www.cnblogs.com/Emiya-Shirou/p/11261508.html

时间: 2024-10-08 10:57:16

如何使用QT5编写一个利用TCP协议的聊天室 (一)编写一个TCP的服务器端的相关文章

15.基于UDP协议的聊天室程序

使用UDP协议完成一个聊天室程序的小项目,大部分代码都有注释,一看就能看到的. 实现的功能:               (1)查看/显示已经登陆的用户信息               (2)向已登陆的用户发送消息               (3)输出错误消息,给予提示               (4)退出 共有三个文件: chat_public.h #ifndef _CHAT_PUB_H_ #define _CHAT_PUB_H_ //chat_public.h #include <lis

利用netty简单实现聊天室

1.导入依赖包 <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha1</version> </dependency> 2.netty服务端代码 public class NettyServer { public static void main(String[] args

基于UDP协议的聊天室(java实现)

主要思路很简单: 1.设置自己的接收端口 2.设置对方IP和端口 3.发送数据和接收数据 下面是主要代码: import java.net.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; public class QQFrame extends JFrame implements Runnable { private JTextArea sendArea = new JT

TCP协议疑难杂症全景解析

说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人.因为本文不会解析TCP头里面的每一个字段或者3次握手的细节,也不会解释慢启动和快速重传的定义4).除了<TCP/IP详解>(卷一,卷二)以及<Unix网络编程>以及Linux源代码之外,学习网络更好的资源是RFC 5).本文给出一个提纲,如果想了解细节,请直接查阅RFC 6).翻来覆去

TCP协议要点和难点全解

说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面 2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的 3).针对对象:对TCP已经有了全面了解的人.因为本文不会解析TCP头里面的每一个字段或者3次握手的细节,也不会解释慢启动和快速重传的定义 4).除了<TCP/IP详解>(卷一,卷二)以及<Unix网络编程>以及Linux源代码之外,学习网络更好的资源是RFC 5).本文给出一个提纲,如果想了解细节,请直接查阅RFC 6).翻

【转载】TCP协议疑难杂症全景解析

说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人.因为本文不会解析TCP头里面的每一个字段或者3次握手的细节,也不会解释慢启动和快速重传的定义4).除了<TCP/IP详解>(卷一,卷二)以及<Unix网络编程>以及Linux源代码之外,学习网络更好的资源是RFC 5).本文给出一个提纲,如果想了解细节,请直接查阅RFC 6).翻来覆去

协议系列之TCP协议

3.TCP协议 从上一节我们了解了什么是IP协议,以及IP协议的一些特性,利用IP协议传输都是单向的,不可靠的,无连接状态的.正是这些特性,于是便产生了TCP协议.TCP协议属于传输层,在IP协议网络层之上,竟然IP协议不可靠,那就必须要在其上多一个TCP协议以实现传输的可靠性.就像我们寄出一封信,如果对方不回信,不通过别的渠道告诉你,你永远都无法保证这封信能准确送到对方手上.同样,TCP协议采取了类似的措施来保证数据包的准确送达,它规定接收端发送一个确认数据包回来. 严格地说,TCP协议提供了

网络协议及tcp协议详解

问题来源:面试中面试官会看到你的简历上写着熟悉网络.http.tcp协议等,那你真的了解他吗?今天它来了 一.网络协议: 层次说明: 第七层:应用层(http) 为操作系统或网络应用程序提供访问网络服务的接口. 第六层:表示层 处理两个通信系统中交换信息的表示方式.为上层用户解决用户信息的语法问题.包括数据格式交换.数据加密与解密.数据压缩与终端类型的转换. 第五层:会话层 在两个节点之间建立端连接.为端系统的应用程序之间提供了对话控制机制.会话层不参与具体的传输,它提供包括访问验证和会话管理在

TCP协议的三次握手+四次断开

TCP协议的三次握手 1.TCP/IP协议概述 TCP/IP协议(Transmission Control Protocol/Internet Protocol)叫做传输控制/网际协议,又叫网络通讯协议,这个协议是Internet国际互联网络的基础.TCP/IP是网络中使用的基本的通信协议.虽然从名字上看TCP/IP包括两个协议,传输控制协议(TCP)和网际协议(IP),但TCP/IP实际上是一组协议,它包括上百个各种功能的协议,如:远程登录.文件传输和电子邮件等,而TCP协议和IP协议是保证数