精华内容
下载资源
问答
  • 2021-03-17 22:27:41

    windows平台

    一:非阻塞

    TCP设置非阻塞

    #include <WinSock2.h>
    #include <QHostAddress>
    #include <QUdpSocket>
    #include <WS2tcpip.h>
    WSAStartup(MAKEWORD(2,2),&mWasData);
    
        SOCKET m_client_tcp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (m_client_tcp == INVALID_SOCKET)
        {
            printf("socket function failed with error: %ld\n", WSAGetLastError());
            return 1;
        }
        //socket设置为非阻塞
        unsigned long on = 1;
        if (ioctlsocket(m_client_tcp, FIONBIO, &on) < 0)
        {
           printf("ioctlsocket failed\n");
           return 1;
        }
        //向服务器发起请求
        sockaddr_in sockAddr;
        memset(&sockAddr, 0, sizeof(sockAddr));  //每个字节都用0填充
        sockAddr.sin_family = AF_INET ;
        sockAddr.sin_addr.s_addr = inet_addr(qStrEncoderIp.toStdString().c_str());
        sockAddr.sin_port = htons(usEncoderPort);
        nRet = ::connect(m_client_tcp, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
        if( nRet == 0)
        {
            printf("tcp connect %s:%hd sucess \n",qStrEncoderIp.toStdString().c_str(),usEncoderPort);
        }
        //因为是非阻塞的,这个时候错误码应该是WSAEWOULDBLOCK,Linux下是EINPROGRESS
        if (nRet < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
            printf("connect failed with error: %ld\n", WSAGetLastError());
            return 1;
        }
        fd_set writeset;
        FD_ZERO(&writeset);
        FD_SET(m_client_tcp, &writeset);
        timeval tv;
        tv.tv_sec = 0;//秒
        tv.tv_usec = 81920;///微妙
        nRet = select(m_client_tcp + 1, NULL, &writeset, NULL, &tv);
        if (nRet == 0)
        {
            printf("connect timeout\n");
            return 1;
        }
        else if (nRet < 0)
        {
            printf("connect failed with error: %ld\n", WSAGetLastError());
            return 1;
        }
        else
        {
            printf("connect success2\n");
        }
    

    https://blog.csdn.net/u010871058/article/details/76147082
    https://blog.csdn.net/xiongya8888/article/details/96996236
    UDP设置非阻塞

    SOCKET  udp= socket(AF_INET, SOCK_DGRAM, 0);
    unsigned long on = 1;
    if (ioctlsocket(udp, FIONBIO, &on) < 0)
    {
       printf("ioctlsocket failed\n");
       return 1;
    }
    

    二:设置超时

    SOCKET socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int nNetTimeout = 500; //500ms
    setsockopt( socket ,SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
    

    设置缓冲区

    int rcvBufSize = 1024*3000;
    setsockopt(m_client_rtp, SOL_SOCKET, SO_RCVBUF, ( char * )&rcvBufSize, sizeof (int));
    

    三:QT的socket加入组播

    #include <WinSock2.h>
    #include <WS2tcpip.h>
    WSAStartup(MAKEWORD(2,2),&mWasData);
    
    int nNetTimeout = 500; //5秒。设置超时函数防止无效的组播地址加入组播的时候阻塞
    setsockopt( m_client_udp,SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof( int ) );
    // 加入组播
    ip_mreq multiCast;
    multiCast.imr_interface.S_un.S_addr = INADDR_ANY;
    multiCast.imr_multiaddr.S_un.S_addr = inet_addr(multicastIP.toStdString().c_str());
    setsockopt(m_client_udp, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multiCast, sizeof(multiCast));
    

    题外:
    假设有一个组播地址224.1.1.1。这个地址是没有流的
    如果有一个非阻塞socket,把这个组播地址加入组播GROUP的时候就会卡死,这个时候可以把socket设置成 阻塞或者设置超时

    1.closesocket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket:

    BOOL bReuseaddr=TRUE;
    setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
    

    2. 如果要已经处于连接状态的soket在调用closesocket后强制关闭,不经历 TIME_WAIT的过程:

    BOOL bDontLinger = FALSE;
    setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));
    

    3.在send(),recv()过程中有时由于网络状况等原因,发收不能预期进行,而设置收发时限:

    int nNetTimeout=1000;//1秒
    //发送时限
    setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
    //接收时限
    setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));
    

    4.在send()的时候,返回的是实际发送出去的字节(同步)或发送到socket缓冲区的字节 (异步);系统默认的状态发送和接收一次为8688字节(约为8.5K);在实际的过程中发送数据 和接收数据量比较大,可以设置socket缓冲区,而避免了send(),recv()不断的循环收发:

    // 接收缓冲区
    int nRecvBuf=32*1024;//设置为32K
    setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
    //发送缓冲区
    int nSendBuf=32*1024;//设置为32K
    setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));
    

    5. 如果在发送数据的时,希望不经历由系统缓冲区到socket缓冲区的拷贝而影响程序的性能:

    int nZero=0;
    setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));
    

    6.同上在recv()完成上述功能(默认情况是将socket缓冲区的内容拷贝到系统缓冲区):

    int nZero=0;
    setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));
    

    7.一般在发送UDP数据报的时候,希望该socket发送的数据具有广播特性:

    BOOL bBroadcast=TRUE;
    setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));
    

    8.在client连接服务器过程中,如果处于非阻塞模式下的socket在connect()的过程中可 以设置connect()延时,直到accpet()被呼叫(本函数设置只有在非阻塞的过程中有显著的 作用,在阻塞的函数调用中作用不大)

    BOOL bConditionalAccept=TRUE;
    setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));
    

    9.如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们 一般采取的措施是"从容关闭"shutdown(s,SD_BOTH),但是数据是肯定丢失了,如何设置让程序满足具体应用的要求(即让没发完的数据发送出去后在关闭socket)?

    struct linger {
    u_short l_onoff;
    u_short l_linger;
    };
    linger m_sLinger;
    m_sLinger.l_onoff=1;//(在closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
    // 如果m_sLinger.l_onoff=0;则功能和2.)作用相同;
    m_sLinger.l_linger=5;//(容许逗留的时间为5秒)
    setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));
    

    设置套接口的选项。

       #include <winsock.h>
       int PASCAL FAR setsockopt( SOCKET s, int level, int optname,
       const char FAR* optval, int optlen);
    

    s:标识一个套接口的描述字。
    level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。
    optname:需设置的选项。
    optval:指针,指向存放选项值的缓冲区。
    optlen:optval缓冲区的长度。
    注释:
    setsockopt()函数用于任意类型、任意状态套接口的设置选项值。尽管在不同协议层上存在选项,但本函数仅定义了最高的“套接口”层次上的选项。选项影响套接口的操作,诸如加急数据是否在普通数据流中接收,广播数据是否可以从套接口发送等等。
    有两种套接口的选项:一种是布尔型选项,允许或禁止一种特性;另一种是整形或结构选项。允许一个布尔型选项,则将optval指向非零整形数;禁止一个选项optval指向一个等于零的整形数。对于布尔型选项,optlen应等于sizeof(int);对其他选项,optval指向包含所需选项的整形数或结构,而optlen则为整形数或结构的长度。SO_LINGER选项用于控制下述情况的行动:套接口上有排队的待发送数据,且 closesocket()调用已执行。参见closesocket()函数中关于SO_LINGER选项对closesocket()语义的影响。应用程序通过创建一个linger结构来设置相应的操作特性:
    struct linger {
    int l_onoff;
    int l_linger;
    };
    为了允许SO_LINGER,应用程序应将l_onoff设为非零,将l_linger设为零或需要的超时值(以秒为单位),然后调用setsockopt()。为了允许SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff应设为零,然后调用setsockopt()。
    缺省条件下,一个套接口不能与一个已在使用中的本地地址捆绑(参见bind())。但有时会需要“重用”地址。因为每一个连接都由本地地址和远端地址的组合唯一确定,所以只要远端地址不同,两个套接口与一个地址捆绑并无大碍。为了通知WINDOWS套接口实现不要因为一个地址已被一个套接口使用就不让它与另一个套接口捆绑,应用程序可在bind()调用前先设置SO_REUSEADDR选项。请注意仅在bind()调用时该选项才被解释;故此无需(但也无害)将一个不会共用地址的套接口设置该选项,或者在bind()对这个或其他套接口无影响情况下设置或清除这一选项。
    一个应用程序可以通过打开SO_KEEPALIVE选项,使得WINDOWS套接口实现在TCP连接情况下允许使用“保持活动”包。一个WINDOWS套接口实现并不是必需支持“保持活动”,但是如果支持的话,具体的语义将与实现有关,应遵守RFC1122“Internet主机要求-通讯层”中第 4.2.3.6节的规范。如果有关连接由于“保持活动”而失效,则进行中的任何对该套接口的调用都将以WSAENETRESET错误返回,后续的任何调用将以WSAENOTCONN错误返回。
    TCP_NODELAY选项禁止Nagle算法。Nagle算法通过将未确认的数据存入缓冲区直到蓄足一个包一起发送的方法,来减少主机发送的零碎小数据包的数目。但对于某些应用来说,这种算法将降低系统性能。所以TCP_NODELAY可用来将此算法关闭。应用程序编写者只有在确切了解它的效果并确实需要的情况下,才设置TCP_NODELAY选项,因为设置后对网络性能有明显的负面影响。TCP_NODELAY是唯一使用IPPROTO_TCP层的选项,其他所有选项都使用SOL_SOCKET层。
    如果设置了SO_DEBUG选项,WINDOWS套接口供应商被鼓励(但不是必需)提供输出相应的调试信息。但产生调试信息的机制以及调试信息的形式已超出本规范的讨论范围。
    setsockopt()支持下列选项。其中“类型”表明optval所指数据的类型。
    选项 类型 意义
    SO_BROADCAST BOOL 允许套接口传送广播信息。
    SO_DEBUG BOOL 记录调试信息。
    SO_DONTLINER BOOL 不要因为数据未发送就阻塞关闭操作。设置本选项相当于将SO_LINGER的l_onoff元素置为零。
    SO_DONTROUTE BOOL 禁止选径;直接传送。
    SO_KEEPALIVE BOOL 发送“保持活动”包。
    SO_LINGER struct linger FAR* 如关闭时有未发送数据,则逗留。
    SO_OOBINLINE BOOL 在常规数据流中接收带外数据。
    SO_RCVBUF int 为接收确定缓冲区大小。
    SO_REUSEADDR BOOL 允许套接口和一个已在使用中的地址捆绑(参见bind())。
    SO_SNDBUF int 指定发送缓冲区大小。
    TCP_NODELAY BOOL 禁止发送合并的Nagle算法。
    setsockopt()不支持的BSD选项有:
    选项名 类型 意义
    SO_ACCEPTCONN BOOL 套接口在监听。
    SO_ERROR int 获取错误状态并清除。
    SO_RCVLOWAT int 接收低级水印。
    SO_RCVTIMEO int 接收超时。
    SO_SNDLOWAT int 发送低级水印。
    SO_SNDTIMEO int 发送超时。
    SO_TYPE int 套接口类型。
    IP_OPTIONS 在IP头中设置选项。
    返回值:
    若无错误发生,setsockopt()返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。
    错误代码:
    WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
    WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
    WSAEFAULT:optval不是进程地址空间中的一个有效部分。
    WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
    WSAEINVAL:level值非法,或optval中的信息非法。
    WSAENETRESET:当SO_KEEPALIVE设置后连接超时。
    WSAENOPROTOOPT:未知或不支持选项。其中,SOCK_STREAM类型的套接口不支持SO_BROADCAST选项,SOCK_DGRAM 类型的套接口不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE选项。
    WSAENOTCONN:当设置SO_KEEPALIVE后连接被复位。
    WSAENOTSOCK:描述字不是一个套接口。

    更多相关内容
  • QtSocket.rar

    2021-05-06 23:23:57
    Qt Socket存在不能一次接收到完整数据的问题,需多次拼接数据;若是复杂的场景,需要较好的处理数据方法,才可接收到完整的数据。本方法可以较好的提取出完整的数据。
  • Qt socket demo

    2016-12-06 14:53:00
    qt4 socket demo
  • Qt里利用TCP/IP协议,socket套接字设计实现结构体数据的收发,类似实现简单的自定义通信协议。发送的结构体包含帧头(占两字节)、数据长度(占一字节)、数据(不多于64字节)、校验和(占一个字节)。
  • 自已用Qt写的多线程服务器实现功能,用QtcpSocket进行通讯,可以正常编译运行,很适合初学者学习使用;
  • QTSocket.zip

    2021-09-25 13:28:17
    Qt Tcp 通信例子,分为服务器和客户端,例子较详细,对C++ qt网络编程人员帮助较大
  • QT Socket 多线程
  • QtSocket QtSocket

    2022-06-08 06:14:26
  • QT socket tcp 通讯Demo

    2021-03-05 10:20:17
    简单示例。
  • Qt socket的文件传输

    2018-12-19 14:15:56
    关于------------------ qt tcpSocket的文件传输,包含客户端和服务端两个程序,实现文件传输通信
  • QTSocket编程

    2013-04-23 17:58:16
    QTSocket编程,实现简单的服务端与客户端进行通信,可以作为QTSocket编程入门。
  • 这是一个QT的socke及时通信代码,里面有数据库(MYSQL)文件,和服务端,客户端,等,客户端外边像一个QQ,客户端实现了,多客户端群聊,添加好友,添加分组,一对一聊天,服务端采用异步通信。
  • qt socket 一对多-多线程

    热门讨论 2011-09-19 16:33:46
    接着刚才上传的qt socket one by one ,并程,多线程,最终完善了容错,和中英文,基本实现qt 局域网通信小程序。。。注意,阅读readme ,我编写的server 要用我的client 端接收(有设计字符格式问题)。。然后完事...
  • Qt Socket网络编程

    2021-08-20 16:10:21
    利用Qt包的情况下,客户端所作无非连接,发送,接收。 链接服务器代码 实现多客户端单服务器通信 客户端 利用Qt包的情况下,客户端所作无非连接,发送,接收。 链接服务器代码 客户端使用 QTcpSocket *tcpClient; 在...

    实现多客户端单服务器通信

    客户端

    利用Qt包的情况下,客户端所作无非连接,发送,接收。

    链接服务器代码

    实现多客户端单服务器通信

    客户端

    利用Qt包的情况下,客户端所作无非连接,发送,接收。

    链接服务器代码

    客户端使用 QTcpSocket *tcpClient;
    在QTcpSocket 下
    函数connectToHost(服务器IP,端口) 链接服务器
    disconnectFromHost() 断开与服务器的连接

    if(ui->btn_connect->text()=="连接")
        {
            tcpClient->connectToHost(ui->edit_IP->text(),ui->edit_Port->text().toInt());
            if(tcpClient->waitForConnected(3000))
            {
                ui->recev_edit->append("成功连接!");
                ui->btn_connect->setText("断开");
                ui->btn_send->setEnabled(true);
            }
            connect(tcpClient,&QTcpSocket::disconnected,[=](){
                ui->btn_connect->setText("连接");
                ui->btn_send->setEnabled(false);
            });
        }
        else
        {
            tcpClient->disconnectFromHost();
            ui->btn_connect->setText("连接");
            ui->btn_send->setEnabled(false);
        }
    

    发送消息
    QTcpSocket 下write函数将发送内容发送到连接好的服务器,utf8则可以传输中文。

    tcpClient->write(data.toUtf8());
    

    接收消息使用信号槽,readAll()将服务器的消息全部读取

    connect(tcpClient,&QTcpSocket::readyRead,this,&MyClient::ReadDate);
    void MyClient::ReadDate()
    {
        QByteArray buffer = tcpClient->readAll();
        if(!buffer.isEmpty())
        {
            ui->recev_edit->append("接收 : "+buffer);
        }
    }
    

    服务端

    服务端的简单操作是监听,得到新链接,再与客户端进行信息交互,断开链接。
    QTcpServer* TCPServer ;
    QTcpSocket* TCPSocket;
    QList<QTcpSocket*> tcpClient ;
    监听 所有地址,与port端口,端口必须为int类型

    TCPServer->listen(QHostAddress::Any, port))
    

    监听单一地址则在,地址参数上填入QHostAddress(一个QString类型的地址参数,可使用QNetworkInterface::allAddresses()的信息遍历而得)

    得到与客户端的新链接

    connect(TCPServer,&QTcpServer::newConnection,this,&MyServer::newCilent);
    
    TCPSocket = TCPServer->nextPendingConnection();
    

    可将新连接添加到我们的列表中,后续可对指定链接操控

    tcpClient<<TCPSocket;
    

    并且,使用peerAddress(),peerPort()函数将地址端口,输入到前端复选框,供前端选择,后端作为信息交互的发送给谁的依据。

    根据新的TCPSocket进行信息交互

    connect(TCPSocket,&QTcpSocket::readyRead,this,&MyServer::socket_Read_Data);
    

    将收到的信息,根据列表中的端口ip进行输出。

    void MyServer::socket_Read_Data()
    {
        QByteArray buffer;
        QString Ip_Port_buffer;
    
        for(int i=0;i<tcpClient.length();i++)
        {
            buffer = tcpClient[i]->readAll();
            if(buffer.isEmpty()) continue;
    
            Ip_Port_buffer =tr("[%1:%2]接收:%3\n").arg(tcpClient[i]->peerAddress().toString().remove("::ffff:"))
                    .arg(tcpClient[i]->peerPort())
                    .arg(QString(buffer));
            Updata("recv",Ip_Port_buffer);
        }
    }
    

    发送代码,核心依旧是write函数

    void MyServer::on_send_btn_clicked()
    {
        QString data = ui->sendText->toPlainText();
        if(data!="")
        {
            QString clientIp = ui->client_comboBox->currentText().split(":")[0];
            int clientPort = ui->client_comboBox->currentText().split(":")[1].toInt();
            for(int i=0;i<tcpClient.length();i++)
            {
                if(tcpClient[i]->peerAddress().toString().remove("::ffff:")==clientIp&&tcpClient[i]->peerPort()==clientPort)
                {
                    tcpClient[i]->write(data.toUtf8());
                    Updata("send","发送["+clientIp+"]:"+data.toUtf8());
                }
            }
        }
        ui->sendText->clear();
    }
    

    最终实现效果
    客户端
    在这里插入图片描述
    服务器
    在这里插入图片描述

    这是源代码,免费下载 0 C币。Qt本次网络编程源码资源

    展开全文
  • QT socket通信.zip

    2020-07-18 01:09:27
    通过Qt提供的QtNetwork模块实现进程间通信,效果可见https://blog.csdn.net/Sakuya__/article/details/89521100
  • Qt socket使用实例

    热门讨论 2012-06-12 22:05:49
    Qt:用socket实现网络编程,使用tcp协议;
  • QT socket服务器

    2014-08-21 16:52:02
    qt搭建的socket服务器,包含server端和client端
  • qtsocket协议互发数据

    2021-05-13 13:12:35
    Qt编写的tcp socket通信的小例子,里面两个程序,可以进行互相发送数据
  • Pipo 的 QT socket的进程间通信
  • Qt Socket 通信 Qt UDP 核心步骤和接口: pro文件中添加 QT += network h头文件中添加 #include <QUdpSocket> #include <QHostAddress> h头文件的类中添加两个套接字(分别用于发送和接收) ...

    Qt Socket 通信

    Qt UDP

    核心步骤和接口:

    1. pro文件中添加

      QT += network
      
    2. h头文件中添加

    #include <QUdpSocket>
    
    #include <QHostAddress>
    
    1. h头文件的类中添加两个套接字(分别用于发送和接收)

      class xx : public xx
      
      {
      
      private:
      
      ​	QUdpSocket *pSocketRecvFd;
      
      ​	QUdpSocket *pSocketSendFd;
      
      };
      
    2. cpp文件中

      1. 构造函数中添加Recv();函数

      2. Recv()函数实现内容:

        pSocketRecvFd = new QUdpSocket(this);
        
        pScocketRecvFd->bind(port);
        
        connect(pSocketRecvFd, SIGNAL(readyRead()), this, SLOT(RecvMsg()));
        
      3. RecvMsg()函数实现内容:

        while(pSocketRecvFd->hasPendingDatagrams()){
        
        ​	QByteArray qbRecvBuff;
        
        ​	qbRecvBuff.resize(pSocketRecvFd->pendingDatagramSize());
        
        ​	pSocketRecvFd->readDatagram(qbRecvBuff.data(), qbRecvBuff.size());
        
        }
        
      4. 发送按钮的响应函数

           {
        
        ​	pSocketSendFd = new QUdpSocket(this);
        
        ​	QByteArray qbSendBuff;
        
        ​	qbSendBuff = ui->textEdit->toPlainText().toUtf8();
        
        ​	pSocketSendFd->writeDatagram(qbSendBuff.data(), qbSendBuff.size(), QHostAddress("127.0.0.1"), port);
        
        }
        

    Qt TCP

    核心步骤和接口:

    1. pro文件中添加

      QT += network
      
    2. h头文件中添加

      #include <QTcpSocket>
      #include <QTcpServer>
      #include <QHostAddress>
      
    3. h头文件的类中添加两个套接字(分别用于建立TCP连接、监听和TCP通信

      class xx : public xx
      
      {
      
      private:
      
      ​	QTcpServer *pTcpServer;
      
      ​	QTcpSocket *pTcpSocketFd;
      
      };
      
    4. cpp文件中(b建立Tcp连接套接字,a监听,c、d接受Tcp通信,e发送Tcp通信)

      1. 创建按钮监听函数

        void MainWindow::on_pushButton_StrListen_clicked()
        {
            pTcpServer->listen(QHostAddress::Any, D_NSP_TDYTH_REMOTE_PORT);
        
            if(pTcpServer->isListening()){
                ui->textEdit_Recv->append("TcpServer 正处于监听状态...");
                ui->textEdit_Recv->append("TcpServer 监听IP是:");
                ui->textEdit_Recv->append(pTcpServer->serverAddress().toString());
                ui->textEdit_Recv->append("TcpServer 监听端口是:");
                ui->textEdit_Recv->append(QString::number(pTcpServer->serverPort()));
            
                ui->pushButton_StrListen->setEnabled(false);
                ui->pushButton_StpListen->setEnabled(true);
            }
        
        }
        
        void MainWindow::on_pushButton_StpListen_clicked()
        {
            if(pTcpServer->isListening()){
                pTcpServer->close();
                ui->pushButton_StrListen->setEnabled(true);
                ui->pushButton_StpListen->setEnabled(false);
                ui->textEdit_Recv->append("服务器关闭连接");
            }
        }
        
      2. 构造函数中定义套接字

        pTcpServer = new QTcpServer(this);
        connect(pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
        
      3. onNewConnection()函数实现

        void MainWindow::onNewConnection()
        {
            // 创建通信socketFd
            pTcpSocketFd = pTcpServer->nextPendingConnection();
        
            connect(pTcpSocketFd, SIGNAL(connected()), this, SLOT(onClientConnected()));
            connect(pTcpSocketFd, SIGNAL(disconnected()), this, SLOT(onClientDisConnected()));
            
            connect(pTcpSocketFd, SIGNAL(readyRead()), this, SLOT(onSocketRecvMs()));
        
        }
        
      4. 三个槽函数的实现

        void MainWindow::onClientConnected()
        {
            ui->textEdit_Recv->append("*******和客户端已建立连接");
            ui->textEdit_Recv->append("*******" + pTcpSocketFd->peerAddress().toString());
            ui->textEdit_Recv->append(QString::number(pTcpSocketFd->peerPort()));
        }
        
        void MainWindow::onClientDisConnected()
        {
            ui->textEdit_Recv->append("和客户端连接断开");
            pTcpSocketFd->deleteLater();
        }
        
        void MainWindow::onSocketRecvMsg()
        {
            // 按行读取
            while (pTcpSocketFd->canReadLine()) {
                ui->textEdit_Recv->append("[in]:" + pTcpSocketFd->readLine());
            }
        }
        
      5. 发送按钮槽函数实现

        void MainWindow::on_pushButton_Send_clicked()
        {
            QString qsSendBuff = ui->lineEdit_SendMsg->text();
            QByteArray qbSendBuff = qsSendBuff.toUtf8();
            qbSendBuff.append('\n');
        
            ui->textEdit_Send->append("[out]:" + qsSendBuff);
            ui->lineEdit_SendMsg->clear();
            ui->lineEdit_SendMsg->setFocus();
            
            pTcpSocketFd->write(qbSendBuff);
        
        }
        
      6. 关闭Tcp连接

        void MainWindow::on_pushButton_Exit_clicked()
        {
            if(pTcpServer->isListening()){
                pTcpServer->close();
            }
            exit(0);
        }
        
        void MainWindow::closeEvent(QCloseEvent *event)
        {
            if(pTcpServer->isListening()){
                pTcpServer->close();
            }
            event->accept();
        
        }
        

    演示的截图如下:

    QUDP

    在这里插入图片描述QTCP
    在这里插入图片描述

    注:Qt 提供的接口通信函数能与基于linux的socket通信函数相互通信!!!
    项目实现下载地址:【点击这里】

    展开全文
  • Qt Socket Server 收发JSON

    2020-06-24 23:14:19
    点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点点击下文末的广告,感谢~之前文章写过Linux C Socket 收发Json数据,最近用Qt Server实现了一遍。给我自...

    点击上方蓝字可直接关注!方便下次阅读。如果对你有帮助,麻烦点点击下文末的广告,感谢~

    之前文章写过Linux C Socket 收发Json数据,最近用Qt Server实现了一遍。给我自己的感觉就是cJSON接口与Qt封装的一些接口是共通的:Qt 封装了QJsonObject来对Json对象操作,如增删改查;封装了QJsonDocument来进行一些序列化与反序列化的操作(可能不准确)。

    重要消息:虽然明天是端午节,但是还是要去公司学习。。。

    后续可能会在公众号中写一点儿理财相关的知识,待定中......

     

    程序中用到了Qt 的Socket Server,但主要介绍下Qt中如何操作Json数据,将接收到的字节流转换为Json对象,又如何将Json对象转换为字节流。

     

    一、 程序介绍

     

    1. Json 操作相关函数

     

    为了与C语言写的对比,同样写了3个函数:

    Qt :

    int ParseRecvJsonData(const  QByteArray &recvdata, int *outLogLevel);
    int WriteLogLevelToFileJson(const QString &filePathName, const int logLevel);
    int CreateRespondInfoJson(QByteArray *respondInfoJson, 
                              const  QByteArray &recvJsonData,
                              const int writeFileRet);
    

          C:

    int ParseRecvJsonData(const char * recvdata, int *outLogLevel);
    int WriteLogLevelToFileJson(const char *filePathName, int logLevel);
    int CreateRespondInfoJson(char *respondInfoJson, 
                              const char* recvJsonData,
                              const int writeFileRet);
    

    解析Json字节流为Json对象,提取所需信息

    将所需信息组装成Json对象写入配置文件

    将字节流转换为Json对象并添加数据,组装成响应信息

    2. Qt 中对Json操作的具体实现

    直接加注释进行说明

    int TcpServerRecvImage::CreateRespondInfoJson(QByteArray *respondInfoJson,
                   const QByteArray &recvJsonData, const int writeFileRet)
    {
    //使用QJsonDocument判断字节流能否转成Json对象
        QJsonParseError jsonError;
        QJsonDocument jsonRecvData(QJsonDocument::fromJson(recvJsonData, &jsonError));
    
    
        if(jsonError.error != QJsonParseError::NoError)
        {
            qDebug() << "parse json error!";
            return -1;
        }
    //通过QsonDocument将字节流转为Json对象
        QJsonObject rootObject = jsonRecvData.object();
    //向Json对象中追加数据
        rootObject.insert("Result","FAIL");
    
    
        if(0 == writeFileRet)
        {
    //修改对应数据;可以思考下是如何实现修改前与修改后数据所占空间不同
            rootObject["Result"] = "SUCCESS";
        }
    //将Json对象转换为字节流
        QJsonDocument documentJson;
        documentJson.setObject(rootObject);
        QByteArray bytearrayJson = documentJson.toJson();
    
    
        respondInfoJson->clear();
        respondInfoJson->append(bytearrayJson);
    
    
        return 0;
    }
    
    
    int TcpServerRecvImage::WriteLogLevelToFileJson(const QString &filePathName,
                               const int logLevel)
    {
    //Qt文件操作
        QFile f(filePathName);
        if(!f.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            qDebug() << "Open failed.";
            return -1;
        }
    
    
        // create JSON Object
        QJsonObject logLevelJson;
        logLevelJson.insert("logLevel",QString::number(logLevel));
    
    
        QJsonDocument documentJson;
        documentJson.setObject(logLevelJson);
        QByteArray bytearrayJson = documentJson.toJson();
    //使用QTextStream,简化文件操作
        QTextStream txtWrite(&f);
        txtWrite << bytearrayJson;
    
    
        f.close();
    
    
        return 0;
    }
    

    3. 程序效果

    客户端程序是之前的C语言写的

    4. 一点感想

    最近一段时间的状态就是不断看书,写Demo程序,并将以前看的一些知识结合起来,不断提炼总结,有一种这就是我想要的生活的错觉;

     

    数据结构如何应用在程序中呢?

    应用程序如何变得更强壮呢?

     

    如需完整工程可在公众号后台留言:

    展开全文
  • 最近在开发im服务器,需要大并发链接。QT默认的是使用select...修改了QTsocket notify内核,不需要修改原来编写的代码,直接设置QT的事件转发方式就行了。支持qt4.0和5.0 csdn博客:http://blog.csdn.net/rushroom
  • qt socket通信

    千次阅读 2019-07-04 13:03:19
    Qt学习之路七——TCP/IP网络编程 2018年05月22日 00:26:25 技术小白yhx 阅读数 5426 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/y____xiang/article/details/80398913 在qt中...
  • QT Socket

    千次阅读 2018-11-09 13:56:37
    TCP通信 TCP的话要复杂点,必须先建立连接才能传输数据,分为...QtNetwork&gt; QTcpSocket *client; char *data="hello qt!"; client = new QTcpSocket(this); client-&gt;connectToHos...
  • Qt Socket TCP通信Demo.rar

    2021-03-23 16:06:44
    适合初学者,简单易懂带注释,分好几个小版本逐步提升难度。
  • Qt socket传送自定义结构体数据

    千次阅读 2020-07-05 22:14:27
    Socket中,数据一般是char型(一般情况下,其实最好是用uchar来传输,避免莫名其妙的错误,但用char也是可以的),而在Qt里面可以使用QByteArray,这个在QSocket里面,是一个神器,根据C++中char*数据与结构体之间...
  • 南航计算机网络实验课的小项目,模拟实现四个主机和基站间的冲突避免过程,每个主机有单独的线程(界面),C/S模式,TCP协议,Qtcreator运行,注释较为详细
  • 利用QT图形编程弄出聊天室界面,可以选择IP,通过socket将客户端和服务端连接起来,支持实时发送接收中文。
  • qt的官方文档里说,调用了flush()方法后,可以把缓冲的数据立刻发送出去。 估计QTcpSocket中的write()方法是带有缓冲的。 void WorkerThread::run() { m_pTcpSocket = new QTcpSocket(); while (1) { …; m_...
  • QT socket清空缓存区

    千次阅读 2019-09-21 14:49:33
    笨方法:readAll 西门子读(port102) 03 00 00 16 11 E0 00 00 00 01 00 C1 02 01 00 C2 02 01 02 C0 01 09 (22)---02 03 00 00 16 11 E0 00 00 00 01 00 C1 02 01 00 C2 02 01 01 C0 01 09 (22)----01 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,315
精华内容 8,126
关键字:

qtsocket