QT tcp Socket 通信开发

这篇博客详细介绍了如何使用QT框架实现TCP Socket通信,包括服务器端和客户端的代码实现。作者通过一个聊天室软件的例子,展示了如何处理TCP连接、数据接收和发送,以及如何维护客户端列表。在服务器端,每当有新的连接请求时,会创建一个新的TCPClientSocket对象并保存其指针,以保持TCP链路。客户端则负责连接到服务器并发送请求。博客还提到,保持TCP连接的关键在于保存QTcpSocket的指针,而非套接字描述符。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

 

转自:http://blog.csdn.net/demowolf/archive/2010/05/17/5598879.aspx

 

折腾了很久TCP IP通信机制。

 

以前虽然看过bsd tcp/ip的so called 基础通信代码。什么bind, listen ,accept , receive, write, read,但是一直没真正理解。

 

这次由于公司需求,我狠狠地读了代码,并且搬出QT老本行,开始了QT For windows的编程。

 

这个大体构架是做一个聊天室软件。

 

每个client都可以给服务器TCP发消息,服务器通过TCP给各个客户端转发消息。

 

服务器端代码:

 

Server.cpp   继承 QTcpServer  主要用来listen to some port , 侦听到端口后, 继承重写了incomingConnection函数,来new 如下的一个

 

代码

 

tcpClientSocket.cpp 这个继承QTcpSocket ,用来 server.cpp里被 New 出来,接受各种请求

 

它重写了函数dataReceived , 即各种客户端发来的请求数据,(注意,这个不是第一步的connect状态,这个是业务逻辑上得请求,比如我给

 

server发送了“你好” ) 。

 

这一步处理好后,便开始给各个客户端分发同样的消息“你好” 。使用方法,很简单,QTcpSocket的write方法即可。

 

这里的细节重点是,在server.cpp里,每个new出来的TcpClientSocket的指针,我放到一个QLIST< TcpClientSocket * >模板里。这样,只要

 

你不删去这个节点,这个TCP链接就一直存在,嘿嘿,神奇吧。

 

刚开始我看QT自带example ,fortuneclient and threaded fortune server;我试图着在example的基础上修改代码,一步步达到目的。结果

 

发现他的业务逻辑,总是write后就自动disconnected, 我以为不disconnected,就能长链接,结果总是出错。

 

我一直纳闷,这是为什么呢?我用了个List保存了socket的descriptor,以为留着套接字的描述符,就可以下次再调出来用用。实际呢,必须

 

创建链路的时刻,就保存指针。TCP链接,指针在,链路在。指针亡,链路亡。

 

这也验证了我的想法,所谓一个真正的通信链路SOCKET的创建,是这样执行下去的。在APP层,我们调用了connect,实际OS对网卡发送了连接

 

对方的信号,这个电子,一路走过去,直到accept , 这一个链路创建了,在网卡开辟了区域了,在系统OS也开辟了内存,两方都为此一直保持

 

着这段数据的存在,指针即维系一个网络TCP链路的关键。

 

这就意味着,客户端无需写什么侦听代码来接受服务器端的消息,直接保持那个链路,消息自然就可以发过来,触发dataReceived信号。

 

写完代码后,我测试了一下,3个客户端同时链接TCP服务器端的5566端口,全部成功。

 

曾经很纠结我的所谓端口只能被一个占用。看来,理论远不如实际来的直接。

 

最后,我还是贴个代码吧。我知道,当一个人寻找各类消息的时候,代码总是最先看得,谁喜欢看人家博客唠叨半天,不讲大道理啊!

 

服务器端:

  1. chatserver.h  
  2. *********************  
  3. #ifndef CHATSERVER_H  
  4. #define CHATSERVER_H  
  5. #include <QTcpServer>  
  6. #include <QStringList>  
  7. #include "tcpclientsocket.h"  
  8. class ChatServer : public QTcpServer  
  9. {  
  10.     Q_OBJECT  
  11. public:  
  12.     ChatServer(QObject *parent = 0,int port=0);  
  13.     void PushMessage();  
  14.     QList<TcpClientSocket*> tcpClientSocketList;  
  15. signals:  
  16.     void updateServer(QString,int);  
  17. public slots:  
  18.     void updateClients(QString,int);  
  19.     void slotDisconnected(int);  
  20. protected:  
  21.     void incomingConnection(int socketDescriptor);  
  22. private:  
  23.     QStringList fortunes;  
  24.     int onlineDescriptor;  
  25. };  
  26. #endif // CHATSERVER_H  
  27. *********************  
  28. chatserver.cpp  
  29. *********************  
  30. #include "chatserver.h"  
  31. #include "chatthread.h"  
  32. #include <stdlib.h>  
  33. ChatServer::ChatServer(QObject *parent,int port)  
  34.         : QTcpServer(parent)  
  35. {  
  36.     fortunes << tr("Searching for people...")  
  37.              << tr("You've find a people. Try say hello!")  
  38.              << tr("You've disconnected.");  
  39.     listen(QHostAddress::Any,port);  
  40. }  
  41. void ChatServer::incomingConnection(int socketDescriptor)  
  42. {  
  43.     TcpClientSocket *tcpClientSocket=new TcpClientSocket(this);  
  44.     connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));  
  45.     connect(tcpClientSocket,SIGNAL(disconnect(int)),this,SLOT(slotDisconnected(int)));  
  46.     tcpClientSocket->setSocketDescriptor(socketDescriptor);  
  47.     tcpClientSocketList.append(tcpClientSocket);  
  48. /* 
  49.     onlineDescriptor=socketDescriptor; 
  50.     QString fortune = fortunes.at(qrand() % fortunes.size()); 
  51. //    QString fortune = fortunes.at(0); 
  52.     ChatThread *thread = new ChatThread(socketDescriptor, fortune, this); 
  53.     connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
  54.     thread->start(); 
  55. */  
  56. }  
  57. void ChatServer::updateClients(QString msg, int length)  
  58. {  
  59.  //   emit updateServer(msg,length);  
  60.     for(int i=0;i<tcpClientSocketList.count();i++)  
  61.     {  
  62.         QTcpSocket *item=tcpClientSocketList.at(i);  
  63.         if(item->write(msg.toLatin1(),length)!=length)  
  64.         {  
  65.             continue;  
  66.         }  
  67.     }  
  68. }  
  69. void ChatServer::slotDisconnected(int descriptor)  
  70. {  
  71.     for (int i=0;i<tcpClientSocketList.count();i++)  
  72.     {  
  73.         QTcpSocket *item=tcpClientSocketList.at(i);  
  74.         if(item->socketDescriptor()==descriptor)  
  75.         {  
  76.             tcpClientSocketList.removeAt(i);  
  77.             return;  
  78.         }  
  79.     }  
  80.     return;  
  81. }  
  82. void ChatServer::PushMessage()  
  83. {  
  84.     QString testString;  
  85.     testString=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值