• 为了保证你在浏览本网站时有着更好的体验,建议使用类似Chrome、Firefox之类的浏览器~~
    • 如果你喜欢本站的内容何不Ctrl+D收藏一下呢,与大家一起分享各种编程知识~
    • 本网站研究机器学习、计算机视觉、模式识别~当然不局限于此,生命在于折腾,何不年轻时多折腾一下

QT网络编程(0x01)-TCP

Qt admin 2年前 (2016-05-15) 1221次浏览 0个评论 扫描二维码

本来今天学习到多线程的一个实例,这个实例是基于多线程抓取服务器时间,这中间运用到 TCP 网络编程这块,之前看过 TCP 那块(其实忘记差不多了,现在回过头来看看)。

 

06de4e5

TCP 三次握手

20140410074734_35455

 

TCP 建立连接的三次握手就是这个样子了,其实这篇文章关注的并不是三次握手。


本篇文章主要是说建立 C/S 模型即客户端与服务端进行通信,通过一个小例子来说明

 

2012063014425557 2012063014430644

这两幅图其实是 COPY 过来的文件传递,别人是实现的服务端与客户端之间文件的传递,本文的例子通过发一些字符串来演示。


 

先看服务端的代码:

#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>
#include <QObject>
#include "tcpclientsocket.h"//这个是一个继承与 Tcpsocket 的类
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);//监听所有 IP 地址和端口
}

void Server::incomingConnection(int socketDescriptor)//socketDescriptor 来自客户端的 IP PORT 信息
{
    TcpClientSocket *tcpClientSocket=new TcpClientSocket(this);
    //前面的 updateClients(QString,int)是 tcpClientSocket 信号函数,有新的客户端就会激活,后面的槽函数是服务端重写的函数
    connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));
    //同上
    connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));
    //服务端绑定 socketDescriptor
    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;
}

客户端代码如下:

#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;

    serverIPLabel = new QLabel(tr("服务器地址:"));
    serverIPLineEdit = new QLineEdit;

    portLabel = new QLabel(tr("端口:"));
    portLineEdit = new QLineEdit;

    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 = 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)
    {
        //相关设置的正确性,需要检查服务器 IP 等
        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("进入聊天室"));
}

void TcpClient::dataReceived()
{
    //bytesAvailable 判定 socket I/O 中是否存在等待被读取的数据
    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()));
    }
}

 

 

 

 


Deeplearn, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明QT 网络编程(0x01)-TCP
喜欢 (0)
admin
关于作者:

您必须 登录 才能发表评论!