QT网络编程Tcp下C/S架构的即时通信
先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面。
#ifndef TCPCLIENT_H
#define TCPCLIENT_H #include <QDialog>
#include <QListWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QGridLayout>
#include <QtNetWork/QHostAddress>
#include <QtNetWork/QTcpSocket> class TcpClient : public QDialog
{
Q_OBJECT public:
TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
~TcpClient();
private:
QListWidget *contentListWidget;
QLineEdit *sendLineEdit;
QPushButton *sendBtn;
QLabel *userNameLabel;
QLineEdit *userNameLineEdit;
QLabel *serverIPLabel;
QLineEdit *serverIPLineEdit;
QLabel *portLabel;
QLineEdit *portLineEdit;
QPushButton *enterBtn;
QGridLayout *mainLayout;
bool status;
int port;
QHostAddress *serverIP;
QString userName;
QTcpSocket *tcpSocket;
public slots:
void slotEnter();
void slotConnected();
void slotDisconnected();
void dataReceived();
void slotSend();
}; #endif // TCPCLIENT_H
有一个加入服务器的按钮,还有一个发送消息的按钮,在头文件,先定义两个函数。
#include "tcpclient.h"
#include <QMessageBox>
#include <QHostInfo> TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(tr("TCP Client")); contentListWidget = new QListWidget; sendLineEdit = new QLineEdit;
sendBtn = new QPushButton(tr("send")); userNameLabel = new QLabel(tr("name"));
userNameLineEdit = new QLineEdit; serverIPLabel = new QLabel(tr("server"));
serverIPLineEdit = new QLineEdit; portLabel = new QLabel(tr("port"));
portLineEdit = new QLineEdit; enterBtn= new QPushButton(tr("join chat")); mainLayout = new QGridLayout(this);
mainLayout->addWidget(contentListWidget,0,0,1,2);
mainLayout->addWidget(sendLineEdit,1,0);
mainLayout->addWidget(sendBtn,1,1);
mainLayout->addWidget(userNameLabel,2,0);
mainLayout->addWidget(userNameLineEdit,2,1);
mainLayout->addWidget(serverIPLabel,3,0);
mainLayout->addWidget(serverIPLineEdit,3,1);
mainLayout->addWidget(portLabel,4,0);
mainLayout->addWidget(portLineEdit,4,1);
mainLayout->addWidget(enterBtn,5,0,1,2); status = false; port = 8010;
portLineEdit->setText(QString::number(port)); serverIP =new QHostAddress(); connect(enterBtn,SIGNAL(clicked()),this,SLOT(slotEnter()));
connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend())); sendBtn->setEnabled(false);
} TcpClient::~TcpClient()
{ } void TcpClient::slotEnter()
{
if(!status)
{
QString ip = serverIPLineEdit->text();
if(!serverIP->setAddress(ip))
{
QMessageBox::information(this,tr("error"),tr("server ip address error!"));
return;
} if(userNameLineEdit->text()=="")
{
QMessageBox::information(this,tr("error"),tr("User name error!"));
return;
} userName=userNameLineEdit->text(); tcpSocket = new QTcpSocket(this);
connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived())); tcpSocket->connectToHost(*serverIP,port); status=true;
}
else
{
int length=0;
QString msg=userName+tr(":Leave Chat Room");
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg. length())
{
return;
} tcpSocket->disconnectFromHost(); status=false;
}
} void TcpClient::slotConnected()
{
sendBtn->setEnabled(true);
enterBtn->setText(tr("离开")); int length=0;
QString msg=userName+tr(":Enter Chat Room");
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())
{
return;
}
} void TcpClient::slotSend()
{
if(sendLineEdit->text()=="")
{
return ;
} QString msg=userName+":"+sendLineEdit->text(); tcpSocket->write(msg.toLatin1(),msg.length());
sendLineEdit->clear();
} void TcpClient::slotDisconnected()
{
sendBtn->setEnabled(false);
enterBtn->setText(tr("join chat"));
} void TcpClient::dataReceived()
{
while(tcpSocket->bytesAvailable()>0)
{
QByteArray datagram;
datagram.resize(tcpSocket->bytesAvailable()); tcpSocket->read(datagram.data(),datagram.size()); QString msg=datagram.data();
contentListWidget->addItem(msg.left(datagram.size()));
}
}
实现界面布局。在Enter槽函数中,确定加入还是离开的服务器的功能。如果加入了,就将消息,写到tcpsocket中,构造消。
服务端的头文件:
#ifndef TCPSERVER_H
#define TCPSERVER_H #include <QDialog>
#include <QListWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>
#include "server.h" class TcpServer : public QDialog
{
Q_OBJECT public:
TcpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
~TcpServer();
private:
QListWidget *ContentListWidget;
QLabel *PortLabel;
QLineEdit *PortLineEdit;
QPushButton *CreateBtn;
QGridLayout *mainLayout;
int port;
Server *server;
public slots:
void slotCreateServer();
void updateServer(QString,int);
}; #endif // TCPSERVER_H
这是服务端的界面的,把消息显示而已。实现这个布局。
#include "tcpserver.h" TcpServer::TcpServer(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(tr("TCP Server")); ContentListWidget = new QListWidget; PortLabel = new QLabel(tr(" port"));
PortLineEdit = new QLineEdit; CreateBtn = new QPushButton(tr("create chat"));
mainLayout = new QGridLayout(this);
mainLayout->addWidget(ContentListWidget,0,0,1,2);
mainLayout->addWidget(PortLabel,1,0);
mainLayout->addWidget(PortLineEdit,1,1);
mainLayout->addWidget(CreateBtn,2,0,1,2); port=8010;
PortLineEdit->setText(QString::number(port)); connect(CreateBtn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));
} TcpServer::~TcpServer()
{ } void TcpServer::slotCreateServer()
{
server = new Server(this,port);
connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int))); CreateBtn->setEnabled(false);
} void TcpServer::updateServer(QString msg,int length)
{
ContentListWidget->addItem(msg.left(length));
}
创建TCP的套接字,以便实现服务端和客户端的通信。
#ifndef TCPCLIENTSOCKET_H
#define TCPCLIENTSOCKET_H #include <QtNetWork/QTcpSocket>
#include <QObject> class TcpClientSocket : public QTcpSocket
{
Q_OBJECT
public:
TcpClientSocket();
signals:
void updateClients(QString,int);
void disconnected(int);
protected slots:
void dataReceived();
void slotDisconnected();
}; #endif // TCPCLIENTSOCKET_H
以上是头文件,具体的是:
#include "tcpclientsocket.h" TcpClientSocket::TcpClientSocket()
{
connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
} void TcpClientSocket::dataReceived()
{
while(bytesAvailable()>0)
{
int length = bytesAvailable();
char buf[1024];
read(buf,length); QString msg=buf;
emit updateClients(msg,length);
}
} void TcpClientSocket::slotDisconnected()
{
emit disconnected(this->socketDescriptor());
}
实现服务器,头文件:
#ifndef SERVER_H
#define SERVER_H #include <QtNetWork/QTcpServer>
#include <QObject>
#include "tcpclientsocket.h" class Server : public QTcpServer
{
Q_OBJECT
public:
Server(QObject *parent=0,int port=0);
QList<TcpClientSocket*> tcpClientSocketList;
signals:
void updateServer(QString,int);
public slots:
void updateClients(QString,int);
void slotDisconnected(int);
protected:
void incomingConnection(int socketDescriptor);
}; #endif // SERVER_H
#include "server.h" Server::Server(QObject *parent,int port)
:QTcpServer(parent)
{
listen(QHostAddress::Any,port);
} void Server::incomingConnection(int socketDescriptor)
{
TcpClientSocket *tcpClientSocket = new TcpClientSocket;
connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));
connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int))); tcpClientSocket->setSocketDescriptor(socketDescriptor); tcpClientSocketList.append(tcpClientSocket);
} void Server::updateClients(QString msg,int length)
{
emit updateServer(msg,length);
for(int i=0;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item = tcpClientSocketList.at(i);
if(item->write(msg.toLatin1(),length)!=length)
{
continue;
}
}
} void Server::slotDisconnected(int descriptor)
{
for(int i=0;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item = tcpClientSocketList.at(i);
if(item->socketDescriptor()==descriptor)
{
tcpClientSocketList.removeAt(i);
return;
}
}
return;
}
实现后的界面:

QT网络编程Tcp下C/S架构的即时通信的更多相关文章
- QT网络编程UDP下C/S架构广播通信
QT有封装好的UDP协议的类,QUdpSocket,里面有我们想要的函数接口.感兴趣的话,可以看看. 先搞服务端吧,写一个子类,继承QDialog类,起名为UdpServer类.头文件要引用我们上边说 ...
- 详解C# 网络编程系列:实现类似QQ的即时通信程序
https://www.jb51.net/article/101289.htm 引言: 前面专题中介绍了UDP.TCP和P2P编程,并且通过一些小的示例来让大家更好的理解它们的工作原理以及怎样.Net ...
- Socket网络编程(TCP/IP/端口/类)和实例
Socket网络编程(TCP/IP/端口/类)和实例 原文:C# Socket网络编程精华篇 转自:微冷的雨 我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: TCP/IP层次 ...
- python 网络编程 TCP/IP socket UDP
TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...
- 网络编程——TCP协议、UDP协议、socket套接字、粘包问题以及解决方法
网络编程--TCP协议.UDP协议.socket套接字.粘包问题以及解决方法 TCP协议(流式协议) 当应用程序想通过TCP协议实现远程通信时,彼此之间必须先建立双向通信通道,基于该双向通道实现数 ...
- Socket网络编程-TCP编程
Socket网络编程-TCP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.socket介绍 1>.TCP/IP协议 2>.跨网络的主机间通讯 在建立通信连接的 ...
- 网络编程TCP/IP详解
网络编程TCP/IP详解 1. 网络通信 中继器:信号放大器 集线器(hub):是中继器的一种形式,区别在于集线器能够提供多端口服务,多口中继器,每个数据包的发送都是以广播的形式进行的,容易阻塞网络. ...
- GO语言练习:网络编程 TCP 示例
1.代码 2.编译及运行 1.网络编程 TCP 示例 simplehttp.go 代码 package main import ( "net" "os" &qu ...
- 网络编程TCP协议-聊天室
网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...
随机推荐
- 3dsmax2015卸载/安装失败/如何彻底卸载清除干净3dsmax2015注册表和文件的方法
3dsmax2015提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dsmax2015失败提示3dsmax2015安装未完成,某些产品无法安装,也有时候想重新 ...
- (转)tune2fs命令详解
tune2fs命令详解(原创) 原文:http://czmmiao.iteye.com/blog/1749232 tune2fs简介 tune2fs是调整和查看ext2/ext3文件系统的文件系统参数 ...
- 【Css】一个简单的选项卡
这次来做一个简单的选项卡. 选项卡其实就分3个部分:html代码,用于显示的内容:css代码,用于显示的样式:javascript代码,用于点击事件. 老规矩,先写一个html坯子. <!DOC ...
- React.js 小书 Lesson25 - 实战分析:评论功能(四)
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson25 转载请注明出处,保留原文链接和作者信息. (本文未审核) 目前为止,第二阶段知识已经基本 ...
- [Git & GitHub] 利用Git Bash进行第一次提交文件
转载:https://blog.csdn.net/dietime1943/article/details/72420042 利用Git Bash进行第一次提交文件 快下班的时候,MD群里有人问怎么向g ...
- IE9 和IE10 兼容性判断及效果
仅IE9可识别 .d1{ width:100px; height:100px; background:blue; } IE9及一下使用<!--[if IE 8]><![endif]- ...
- 设置固定ip后无法上公网
把电脑ip设置成固定ip后,发现其不能上公网,突然想到要设置DNS. 运行cmd程序,输入命令ipconfig /all查看此网络的DNS,设置固定ip 时添加此DNS地址即可.
- 解决github无法访问的问题
gitbub是外网,经常会遇到访问不了的问题,并且有时能访问也网速好慢. 解决这个问题的方法是 更改hosts文件,地址: C:\Windows\System32\Drivers\etc 我在hos ...
- 十、集成使用redis
一.简介 redis是一种非关系型数据库,它的数据结构是key-value的存储形式:能够支持多种类型的数据存储,如:string/list/map/object...等.springboot自然也对 ...
- Excel批量生成条形码
项目要求需要将信息做成条形码的形式,以便通过手持设备直接查看信息,因本次项目信息为固定信息,不需随机生成,故采用本方法: 代码随机生成二维码暂时没有接触,后续有时间会研究 步骤: 1.新建 Excel ...