QTcpSocket QTcpServer
函数 | 作用 |
---|---|
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) | 监听 |
void setMaxPendingConnections(int numConnections) | 可以挂起的连接数量 |
QHostAddress serverAddress() const | 地址 |
quint16 serverPort() const | 端口 |
signalls:
void acceptError(QAbstractSocket::SocketError socketError)
void newConnection()
先来个小例子
/*
* 大致的过程如下:
* m_tcpserver=new QTcpServer(this);
* m_tcpserver->listen(QHostAddress::Any,30142);//监听所有ip的端口
*connect(m_tcpserver,SIGNAL(newConnection()),this,SLOT(newConnect()));
* m_tcpsocket = m_tcpserver->nextPendingConnection(); //得到每个连进来的socket
* connect(m_tcpsocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
* m_tcpsocket->write(strMesg.toUtf8()); //发送
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QPushButton>
#include<QTcpServer>
#include<QTcpSocket>
#include<QTextBrowser>
#include<QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void startTcpserver();
void sendMessage();
void newConnect();
void readMessage();
private:
QPushButton *start_bt,*send_bt;
QTextEdit *input_edit;
QTextBrowser *text_browser;
QTcpServer *m_tcpserver;
QTcpSocket *m_tcpsocket;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include<QDateTime>
#include<QAction>
#include<QHostAddress>
#include<QHBoxLayout>
#include<QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *wid=new QWidget;
this->setCentralWidget(wid);
QHBoxLayout *buttom_layout=new QHBoxLayout;
QVBoxLayout *main_layout=new QVBoxLayout(wid);
start_bt=new QPushButton("Start");
send_bt=new QPushButton("Send");
input_edit=new QTextEdit();
text_browser=new QTextBrowser();
buttom_layout->addStretch();
buttom_layout->addWidget(start_bt);
buttom_layout->addStretch();
buttom_layout->addWidget(send_bt);
buttom_layout->addStretch();
buttom_layout->setSpacing(100);
text_browser->setFixedHeight(300);
main_layout->addWidget(text_browser);
main_layout->addSpacing(30);
input_edit->setFixedHeight(70);
main_layout->addWidget(input_edit);
main_layout->addSpacing(30);
main_layout->addLayout(buttom_layout);
main_layout->addStretch();
main_layout->setContentsMargins(30,30,30,30);
this->resize(500,500);
this->setWindowTitle("My QQ Server");
send_bt->setShortcut(Qt::Key_Enter);
//=============以上为界面设置===========
m_tcpserver=new QTcpServer(this);
m_tcpsocket = new QTcpSocket;
connect(start_bt,SIGNAL(clicked(bool)),this,SLOT(startTcpserver()));
connect(send_bt,SIGNAL(clicked(bool)),this,SLOT(sendMessage()));
this->show();
}
MainWindow::~MainWindow()
{
}
void MainWindow::startTcpserver()
{
m_tcpserver->listen(QHostAddress::Any,30142);//监听所有ip的端口30142
qDebug()<<"start server";
//新连接信号触发,调用newConnect()槽函数,这个跟信号函数一样,其实你可以随便取。
connect(m_tcpserver,SIGNAL(newConnection()),this,SLOT(newConnect()));
}
void MainWindow::newConnect()
{
m_tcpsocket = m_tcpserver->nextPendingConnection(); //得到每个连进来的socket
qDebug()<<"new Connect";
text_browser->append(QString("%0").arg(m_tcpsocket->peerAddress().toIPv4Address())+" is connected");
connect(m_tcpsocket,SIGNAL(readyRead()),this,SLOT(readMessage())); //有可读的信息,触发读函数槽
}
void MainWindow::readMessage()
{
QByteArray qba= m_tcpsocket->readAll(); //读取
qDebug()<<qba;
QString ss=QVariant(qba).toString();
text_browser->append(QDateTime::currentDateTime().time().toString()+"\n"+ss);
}
void MainWindow::sendMessage()
{
QString strMesg= input_edit->toPlainText();
qDebug()<<strMesg;
input_edit->clear();
m_tcpsocket->write(strMesg.toUtf8()); //发送
text_browser->append(QDateTime::currentDateTime().time().toString()+"\n"+strMesg);
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QPushButton>
#include<QTextBrowser>
#include<QTcpSocket>
#include<QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void connectServer();
void readMessage();
void sendMessage();
private:
QPushButton *start_bt,*send_bt;
QTextEdit *input_edit;
QTextBrowser *text_browser;
QTcpSocket *m_tcpsocket;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include<QAction>
#include<QDateTime>
#include<QHBoxLayout>
#include<QVBoxLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *wid=new QWidget;
this->setCentralWidget(wid);
QHBoxLayout *buttom_layout=new QHBoxLayout;
QVBoxLayout *main_layout=new QVBoxLayout(wid);
start_bt=new QPushButton("Connect",wid);
send_bt=new QPushButton("Send",wid);
input_edit=new QTextEdit(wid);
text_browser=new QTextBrowser(wid);
buttom_layout->addStretch();
buttom_layout->addWidget(start_bt);
buttom_layout->addStretch();
buttom_layout->addWidget(send_bt);
buttom_layout->addStretch();
buttom_layout->setSpacing(100);
text_browser->setFixedHeight(300);
main_layout->addWidget(text_browser);
main_layout->addSpacing(30);
input_edit->setFixedHeight(70);
main_layout->addWidget(input_edit);
main_layout->addSpacing(30);
main_layout->addLayout(buttom_layout);
main_layout->addStretch();
main_layout->setContentsMargins(30,30,30,30);
this->resize(500,500);
m_tcpsocket = new QTcpSocket;
this->setWindowTitle("My QQ client");
send_bt->setShortcut(Qt::Key_Enter);
connect(start_bt,SIGNAL(clicked(bool)),this,SLOT(connectServer()));
connect(send_bt,SIGNAL(clicked(bool)),this,SLOT(sendMessage()));
}
MainWindow::~MainWindow()
{
}
void MainWindow::connectServer()
{
m_tcpsocket=new QTcpSocket(this);
m_tcpsocket->abort();
m_tcpsocket->connectToHost("192.168.252.128",30142);
connect(m_tcpsocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
}
void MainWindow::readMessage()
{
QByteArray qba =m_tcpsocket->readAll();
qDebug()<<qba;
QString ss=QVariant(qba).toString();
text_browser->append(QDateTime::currentDateTime().time().toString()+"\n"+ss);
}
void MainWindow::sendMessage()
{
QString ss= input_edit->toPlainText();
m_tcpsocket->write(ss.toStdString().c_str(),strlen(ss.toStdString().c_str()));
text_browser->append(QDateTime::currentDateTime().time().toString()+"\n"+ss);
input_edit->clear();
}
完整代码下载:https://download.csdn.net/download/qq_33564134/10849077
Tcp聊天室服务器构造
构造原理
/*
* ChatServer 构造原理
* 1.服务器界面有ChatServer构成,他有一个tecserver保证了服务器的启动(startServer()),同时服务器需要更新显示,
* 有了updateBrowser(QString msg,int)
* 2.服务器的启动,由TcpServer构成,他拥有
* (1)sendMsg(QString,int)给全部的tcpsocket发送信息同时发送信号void updateBrowser(QString msg,int)
* 给ChatServer 提醒更新界面
* (2)void socketDisconnect(int)去移除相关的tcpsocket
* (3)void incomingConnection(qintptr socketDescriptor)处理tcpsocket的接入
* 3.tcpsocket重构信号
* connect(this,SIGNAL(readyRead()),this,SLOT(receiveMsg()));//更改信号
* connect(this,SIGNAL(disconnected()),this,SLOT(socketDisconnect()));//更改信号
* (1)在receiveMsg()里面接收了msg,emit emit sendMsg(msg,len),此信号会被tcpserver接收到,然后群发信息
*(2)socketDisconnect() 将会给tcpserver一个socketDesconnect(this->socketDescriptor())的信号
*/
//chatserner.h
#ifndef CHATSERNER_H
#define CHATSERNER_H
#include<QListWidget>
#include<QLabel>
#include<QLineEdit>
#include<QPushButton>
#include <QWidget>
#include<QGridLayout>
#include<QString>
#include"tcpserver.h"
/*
* ChatServer 构造原理
* 1.服务器界面有ChatServer构成,他有一个tecserver保证了服务器的启动(startServer()),同时服务器需要更新显示,
* 有了updateBrowser(QString msg,int)
* 2.服务器的启动,由TcpServer构成,他拥有
* (1)sendMsg(QString,int)给全部的tcpsocket发送信息同时发送信号void updateBrowser(QString msg,int)
* 给ChatServer 提醒更新界面
* (2)void socketDisconnect(int)去移除相关的tcpsocket
* (3)void incomingConnection(qintptr socketDescriptor)处理tcpsocket的接入
* 3.tcpsocket重构信号
* connect(this,SIGNAL(readyRead()),this,SLOT(receiveMsg()));//更改信号
* connect(this,SIGNAL(disconnected()),this,SLOT(socketDisconnect()));//更改信号
* (1)在receiveMsg()里面接收了msg,emit emit sendMsg(msg,len),此信号会被tcpserver接收到,然后群发信息
*(2)socketDisconnect() 将会给tcpserver一个socketDesconnect(this->socketDescriptor())的信号
*
* 此文件用于界面的编写,然后调用自己重构的tcpserver进来
*/
class ChatSerner : public QWidget
{
Q_OBJECT
public:
ChatSerner(QWidget *parent = 0);
~ChatSerner();
void initWidget(); //初始化界面
public slots:
void startServer(); //当creat_bt点击时候调用,目的是创建QTcpServer
void updateBrowser(QString msg,int); //当socket有信息传递时候,更新服务器的显示
private:
QListWidget *server_widget;
QLabel *port_label;
QLineEdit *m_port;
QPushButton *creat_bt;
QGridLayout *main_layout;
TcpServer *tcp_server;
};
#endif // CHATSERNER_H
//chatserner.cpp
#include "chatserner.h"
#include<QDebug>
ChatSerner::ChatSerner(QWidget *parent)
: QWidget(parent)
{
initWidget();
}
ChatSerner::~ChatSerner()
{
}
void ChatSerner::initWidget()
{
setWindowTitle("TCP Server");
server_widget = new QListWidget;
port_label = new QLabel("接听端口:");
m_port = new QLineEdit;
m_port->setText("30142");
creat_bt = new QPushButton("创建聊天室");
main_layout = new QGridLayout(this);
main_layout->addWidget(server_widget,0,0,1,2);
main_layout->addWidget(port_label,1,0);
main_layout->addWidget(m_port,1,1);
main_layout->addWidget(creat_bt,2,0,1,2);
resize(400,400);
connect(creat_bt,SIGNAL(clicked(bool)),this,SLOT(startServer()));
}
void ChatSerner::startServer()//启动服务器
{
int port=m_port->text().toInt();
qDebug()<<"server start runing..."<<port;
//启动了服务器,接收请求交给tcp_server的 incomingCo....
tcp_server=new TcpServer(this,port);
//更新了服务器的显示界面
connect(tcp_server,SIGNAL(updateBrowser(QString,int)),this,SLOT(updateBrowser(QString,int)));
creat_bt->setEnabled(false);
}
void ChatSerner::updateBrowser(QString msg,int len)
{
server_widget->addItem(msg.left(len));
}
//tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include<QTcpServer>
#include"tcpsocket.h"
/*
* tcpserver 这个文件重构qtcpserver的信号,加入了QList<>这样保证了多个socket的开通
*/
class TcpServer:public QTcpServer
{
Q_OBJECT
public:
TcpServer(QObject *parent=0,int port=0);
QList<TcpSocket*> socket_list; //socket的list
signals:
void updateBrowser(QString msg,int); //发送个信号给服务器,更新显示界面
public slots:
void sendMsg(QString,int); //发送信息给客户端
void socketDisconnect(int); //发生了socket的退出
protected:
void incomingConnection(qintptr socketDescriptor); //socket的接入
};
#endif // TCPSERVER_H
//tcpserver.cpp
#include "tcpserver.h"
#include<QHostAddress>
int i=1;
TcpServer::TcpServer(QObject *parent,int port):QTcpServer(parent)
{
listen(QHostAddress::Any,port);//监听任何ip的请求
qDebug()<<"listen ....";
}
void TcpServer::incomingConnection(qintptr socketDescriptor)
{
qDebug()<<"incomingConnection"<<i;
TcpSocket *tcpsocket=new TcpSocket(this);
connect(tcpsocket,SIGNAL(sendMsg(QString,int)),this,SLOT(sendMsg(QString,int)));
connect(tcpsocket,SIGNAL(socketDesconnect(int)),this,SLOT(socketDisconnect(int)));
tcpsocket->setSocketDescriptor(socketDescriptor);
socket_list.append(tcpsocket);
i++;
}
void TcpServer::sendMsg(QString msg, int len)
{
emit updateBrowser(msg,len);//更新服务器的显示
for(int i=0;i<socket_list.count();i++)
{
QTcpSocket *item = socket_list.at(i);
if(item->write(msg.toLatin1(),len)!=len)
{
continue;
}
}
}
void TcpServer::socketDisconnect(int socketDescriptor)
{
for(int i=0;i<socket_list.count();i++)
{
QTcpSocket *item=socket_list.at(i);
if(item->socketDescriptor()==socketDescriptor)
{
socket_list.removeAt(i);
}
}
}
//tcpsocket.h
#ifndef TCPSOCKET_H
#define TCPSOCKET_H
#include<QTcpSocket>
/*
* 主要是完成信号的转换,用于接收客户端的信息
*/
class TcpSocket:public QTcpSocket
{
Q_OBJECT
public:
TcpSocket(QObject *parent=0);
public slots:
void receiveMsg();//接收客户端的信息
void socketDisconnect();//socket关闭
signals:
void sendMsg(QString,int);
void socketDesconnect(int);
};
#endif // TCPSOCKET_H
//tcpsocket.cpp
#include "tcpsocket.h"
TcpSocket::TcpSocket(QObject *parent)
{
qDebug()<<"socket create...";
connect(this,SIGNAL(readyRead()),this,SLOT(receiveMsg()));//更改信号
connect(this,SIGNAL(disconnected()),this,SLOT(socketDisconnect()));//更改信号
}
void TcpSocket::receiveMsg()
{
while(bytesAvailable()>0)//qtcpsocket自带的函数
{
int len=bytesAvailable();
char buf[1024];
read(buf,len);
QString msg=buf;
emit sendMsg(msg,len);
}
}
void TcpSocket::socketDisconnect()
{
emit socketDesconnect(this->socketDescriptor());
}
//客户端
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QDialog>
#include <QListWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QGridLayout>
#include <QHostAddress>
#include <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("发送"));
userNameLabel = new QLabel(tr("用户名:"));
userNameLineEdit = new QLineEdit;
userNameLineEdit->setText("zz");
serverIPLabel = new QLabel(tr("服务器地址:"));
serverIPLineEdit = new QLineEdit;
serverIPLineEdit->setText("192.169.252.128");
portLabel = new QLabel(tr("端口:"));
portLineEdit = new QLineEdit;
portLineEdit->setText("30142");
enterBtn= new QPushButton(tr("进入聊天室"));
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 = 30142;
portLineEdit->setText(QString::number(port));
// serverIP =new QHostAddress(QHostAddress::Any);
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("192.168.252.128"))
{
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("进入聊天室"));
}
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()).toUtf8());
}
}
完整代码下载:
https://download.csdn.net/download/qq_33564134/10851675