軟件環境: ubuntu
--------------------------------------------------------------------------------------------------------
最終效果圖:
--------------------------------------------------------------------------------------------------------
注意:此處只有服務端採用了多線程,即可以接收多個客戶端的訪問並進行相互
通信。這裏在使用時必須先啓動服務端再啓動客戶端,此時在服務端的左側方框
內會顯示與服務端連接的客戶端名。鼠標點擊你想要通信的客戶名然後在發送消
息即可。
--------------------------------------------------------------------------------------------------------
服務端:
GUI界面設計:
--------------------------------------------------------------------------------------------------------
實現代碼:
非線程部分:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include<QMainWindow>
#include<QtNetwork/QTcpServer>
#include<QStandardItemModel>
#include"socketthread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QStandardItemModel *model;
protected:
void init();
void newListen();
private:
Ui::MainWindow *ui;
QTcpServer *tcpServer;
signals:
void sendToSocketThrd(QString client,QString datas);
private slots:
void createSocketThread();
void revFromThrd(bool isClient,QString datas);
void removeClient(QString client);
//void addSocketDescription(int socketdescription);
//void removeSocketDescription(int socketdescription);
void on_send_clicked();
void on_friendlist_clicked(QModelIndex index);
};
#endif // MAINWINDOW_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "ui_mainwindow.h"
int Des[256] = {0};
int clientNum = 0;
QString currentClient;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
tcpServer = new QTcpServer;
model = new QStandardItemModel();
model->setColumnCount(2);
model->setHeaderData(0,Qt::Horizontal,"NAME");
model->setHeaderData(1,Qt::Horizontal,"IP");
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(createSocketThread()));
ui->friendlist->setModel(model);
ui->friendlist->hideColumn(1);
ui->friendlist->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
ui->friendlist->setEditTriggers(QAbstractItemView::NoEditTriggers);
newListen();
}
void MainWindow::newListen()
{
if(!tcpServer->listen(QHostAddress::Any,6666))
{
qDebug()<<tcpServer->errorString();
tcpServer->close();
return ;
}
}
void MainWindow::createSocketThread()
{
socketThread *SThread = new socketThread(tcpServer->nextPendingConnection());
connect(SThread,SIGNAL(sendToMainWin(bool,QString)),this,SLOT(revFromThrd(bool,QString)));
connect(SThread,SIGNAL(closeClient(QString)),this,SLOT(removeClient(QString)));
//connect(SThread,SIGNAL(sendSocketDescription(int)),this,SLOT(addSocketDescription(int)));
//connect(SThread,SIGNAL(closeSocketDescription(int)),this,SLOT(removeSocketDescription(int)));
connect(this,SIGNAL(sendToSocketThrd(QString,QString)),SThread,SLOT(revFromMainWin(QString,QString)));
SThread->start();
}
void MainWindow::on_send_clicked()
{
QString message;
message = "SERVER\n"+ui->message->document()->toPlainText();
ui->message->clear();
emit sendToSocketThrd(currentClient,message);
}
/*
void MainWindow::addSocketDescription(int socketdescription)
{
for(int i = 0; i < 256; i++)
{
if(Des[i] == 0)
{
Des[i] = socketdescription;
break;
}
}
}
void MainWindow::removeSocketDescription(int socketdescription)
{
for(int i = 0; i < 256; i++)
{
if(Des[i] == socketdescription)
{
Des[i] = 0;
break;
}
}
}
*/
void MainWindow::revFromThrd(bool isClient,QString datas)
{
if(isClient)
{
QString tmp;
tmp = QString(strtok(datas.toLatin1().data(),"\n"));
model->setItem(clientNum,0,new QStandardItem(tmp));
tmp = QString(strstr(datas.toLatin1().data(),"\n")).mid(1);
model->setItem(clientNum,1,new QStandardItem(tmp));
clientNum++;
}
else
{
ui->displaymessage->append(datas);
}
}
void MainWindow::removeClient(QString client)
{
for(int i = 0; i < clientNum;i++)
{
if(model->item(i)->text().operator ==(client))
{
model->removeRow(i);
clientNum--;
break;
}
}
}
void MainWindow::on_friendlist_clicked(QModelIndex index)
{
currentClient = index.data().toString()+"\n";
currentClient += index.sibling(index.row(),1).data().toString();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
線程部分:
#ifndef SOCKETTHREAD_H
#define SOCKETTHREAD_H
#include<QThread>
#include<QtNetwork/QTcpSocket>
#include<QtNetwork/QHostAddress>
class socketThread : public QThread
{
Q_OBJECT
public:
explicit socketThread(QObject *parent = 0);
socketThread(QTcpSocket *socket);
QString ip;
QString clientName;
bool isClient;
int description;
protected:
void run();
signals:
void sendToMainWin(bool isClient,QString datas);
void sendSocketDescription(int socketDescription);
void closeClient(QString client);
private slots:
void revFromMainWin(QString client,QString datas);
void closeSocket();
void revDatas();
private:
QTcpSocket * tcpSocket;
};
#endif // SOCKETTHREAD_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "socketthread.h"
socketThread::socketThread(QObject *parent) :
QThread(parent)
{
}
socketThread::socketThread(QTcpSocket *socket)
{
tcpSocket = socket;
isClient = true;
description = tcpSocket->socketDescriptor();
ip = tcpSocket->peerAddress().toString();
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revDatas()));
}
void socketThread::run()
{
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(closeSocket()));
}
void socketThread::revDatas()
{
if(isClient)
{
clientName = tcpSocket->readAll();
emit sendToMainWin(isClient,clientName+"\n"+ip);
isClient = false;
}
else
{
emit sendToMainWin(isClient,clientName+"\n"+tcpSocket->readAll());
}
}
void socketThread::revFromMainWin(QString client,QString datas)
{
QString tmp = clientName+"\n"+ip;
if(tmp.operator ==(client))
{
tcpSocket->write(datas.toLatin1().data());
}
}
void socketThread::closeSocket()
{
emit closeClient(clientName);
tcpSocket->close();
}
--------------------------------------------------------------------------------------------------------
服務端:
GUI界面設計:
--------------------------------------------------------------------------------------------------------
實現代碼:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QtNetwork>
#include<QtNetwork/QTcpSocket>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString myName;
protected:
void init();
void newTCPConnect();
private:
Ui::MainWindow *ui;
QTcpSocket *tcpSocket;
private slots:
void revData();
void sendMyName();
void displayError(QAbstractSocket::SocketError);
void on_send_clicked();
};
#endif // MAINWINDOW_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
init();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
this->tcpSocket = new QTcpSocket(this);
myName = "PK";
newTCPConnect();
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(revData()));
connect(tcpSocket,SIGNAL(connected()),this,SLOT(sendMyName()));
connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),
this,SLOT(displayError(QAbstractSocket::SocketError)));
}
void MainWindow::revData()
{
QString datas = tcpSocket->readAll();
ui->displaymessage->append(datas);
}
void MainWindow::newTCPConnect()
{
tcpSocket->abort();
tcpSocket->connectToHost(QHostAddress::Any,6666);
}
void MainWindow::displayError(QAbstractSocket::SocketError)
{
qDebug()<<tcpSocket->errorString();
tcpSocket->close();
}
void MainWindow::on_send_clicked()
{
QString message;
message = ui->message->document()->toPlainText();
ui->message->clear();
tcpSocket->write(message.toLatin1().data());
}
void MainWindow::sendMyName()
{
tcpSocket->write(myName.toLatin1().data());
}