专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Qt开发TCPIP网络通信

  TCPIP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISOOSI模型的四层层级构架的基础上通过TCPIP协议建立的通讯。控制器可以设置为服务器端或客户端。
  关于TCPIP协议可详看:TCPIP协议详解知乎(zhihu。com)
  总的来说,TCPIP通讯有两个部分:客户端和服务器QTcpServer(监听套接字)和QTcpSocket(通讯套接字)
  监听套接字,顾名思义,监听关于各种通讯的状态,一旦进行通讯,监听套接字会启动通讯套接字,进行通讯
  客户端使用connectToHost函数主动连接服务器后,服务器会触发newConnectio这个槽函数,并进行取出QTcpServer(监听套接字),将相关内容取出并赋给QTcpSocket(通讯套接字)。
  客户端向服务器发送数据,触发readyRead(),进行处理,彼此传递时,原理都是这样的。
  对双方来说都起作用的部分:一旦建立连接,就会触发connected,服务器特殊一点,触发的是newConnectio互传数据也是一样的,一旦接受到,就会触发readyread
  服务器中,需要监听套接字以及通讯套接字,监听套接字用于监听客户端是否给服务器发送请求
  本篇博文做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信以及文件传输的小例程。一,客户端
  客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:
  (1)创建QTcpSocket套接字对象socketnewQTcpSocket(this);
  (2)使用这个对象连接服务器QStringipui。lineEditiptext();获取ipintportui。lineEdit2text()。toInt();获取端口数据socketconnectToHost(ip,port);
  (3)使用write函数向服务器发送数据QByteArraydataui。lineEdit3text()。toUtf8();获取lineEdit控件中的数据并发送给服务器socketwrite(data);
  (4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据connect(socket,QTcpSocket::readyRead,this,QTcpClinet::ReadData);voidQTcpClinet::ReadData(){QByteArraybufsocketreadAll();ui。textEditappend(buf);}
  (5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)socketdisconnectFromHost();
  客户端例程:(新建一个qt项目QTcpClinet(客户机))ui界面
  本地回路ip:127。0。0。1可以连接到本地ip(电脑内部循环的ip)
  如果要和局域网其他ip连接在运行(winR)cmdipconfigipv4地址查看本机ip
  点击领取Qt学习资料视频教程链接
  QTcpClinet。hincludeQtWidgetsQWidgetincludeuiQTcpClinet。hincludeQTcpSocket。hpragmaexecutioncharacterset(utf8)classQTcpClinet:publicQWidget{QOBJECTpublic:QTcpClinet(QWidgetparentQNULLPTR);QTcpClinet();publicslots:voidonbtnconnectclicked();voidReadData();voidonbtnpushclicked();private:Ui::QTcpClinetClassui;QTcpSocketsocket;创建socket指针};QTcpClinet。cppincludeQTcpClinet。hQTcpClinet::QTcpClinet(QWidgetparent):QWidget(parent){ui。setupUi(this);socketnewQTcpSocket(this);}QTcpClinet::QTcpClinet(){deletethissocket;回收内存}voidQTcpClinet::onbtnconnectclicked(){if(ui。btnconnecttext()tr(连接服务器)){QStringipui。lineEditiptext();获取ipintportui。lineEdit2text()。toInt();获取端口数据取消已有的连接socketabort();连接服务器socketconnectToHost(ip,port);boolisconnectsocketwaitForConnected();等待直到连接成功如果连接成功if(isconnect){ui。textEditappend(Theconnectionwassuccessful!!);ui。btnpushsetEnabled(true);按钮使能修改按键文字ui。btnconnectsetText(断开服务器连接);接收缓冲区(服务器)信息connect(socket,QTcpSocket::readyRead,this,QTcpClinet::ReadData);}else{ui。textEditappend(Theconnectionfalied!!);}}else{断开连接socketdisconnectFromHost();ui。btnconnectsetText(连接服务器);ui。btnpushsetEnabled(false);关闭发送按钮使能}}接收缓冲区信息函数voidQTcpClinet::ReadData(){QByteArraybufsocketreadAll();ui。textEditappend(buf);}发送按钮事件voidQTcpClinet::onbtnpushclicked(){QByteArraydataui。lineEdit3text()。toUtf8();获取lineEdit控件中的数据并发送给服务器socketwrite(data);判断是否写入成功booliswritesocketwaitForBytesWritten();if(iswrite){写入成功}else{没有写入成功}}二,服务器(需要一直运行哦)
  服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:
  (1)创建QTcpSever对象servernewQTcpServer(this);
  (2)侦听一个端口,使得客户端可以使用这个端口访问服务器serverlisten(QHostAddress::Any,6677);监听所有ip和6677端口
  (3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问connect(server,QTcpServer::newConnection,this,TcpServer::ClientConnect);voidTcpServer::ClientConnect(){解析所有客户连接while(serverhasPendingConnections()){连接上后通过socket(QTcpSocket对象)获取连接信息socketservernextPendingConnection();QStringstrQString(〔ip:1,port:2〕)。arg(socketpeerAddress()。toString())。arg(socketpeerPort());监听客户端是否有消息发送connect(socket,QTcpSocket::readyRead,this,TcpServer::ReadData1);}}
  (4)使用socket的write函数向客户端发送数据socketwrite(data);
  (5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据监听客户端是否有消息发送connect(socket,QTcpSocket::readyRead,this,TcpServer::ReadData1);获取客户端向服务器发送的信息voidTcpServer::ReadData1(){QByteArraybufsocketreadAll();readAll最多接收65532的数据QStringstrQString(〔ip:1,port:2〕)。arg(socketpeerAddress()。toString())。arg(socketpeerPort());ui。textEditserverappend(strQString(buf));socketwrite(ok);服务器接收到信息后返回一个ok}
  (6)取消侦听serverclose();
  服务器例程:(添加一个新的qt项目TcpServer(服务器))ui界面TcpServer。hincludeQtWidgetsQWidgetincludeuiTcpServer。hincludeqtcpserver。hincludeqtcpsocket。hclassTcpServer:publicQWidget{QOBJECTpublic:TcpServer(QWidgetparentQNULLPTR);TcpServer();publicslots:voidonbtnserverclicked();voidonbtnlistenclicked();private:Ui::TcpServerClassui;QTcpServerserver;QTcpSocketsocket;一个客户端对应一个socketvoidClientConnect();voidReadData1();};TcpServer。cppincludeTcpServer。hincludeqstring。hincludeqdebug。hpragmaexecutioncharacterset(utf8)TcpServer::TcpServer(QWidgetparent):QWidget(parent){ui。setupUi(this);servernewQTcpServer(this);客户机连接信号槽connect(server,QTcpServer::newConnection,this,TcpServer::ClientConnect);}TcpServer::TcpServer(){serverclose();serverdeleteLater();}voidTcpServer::onbtnlistenclicked(){if(ui。btnlistentext()侦听){从输入框获取端口号intportui。lineEditporttext()。toInt();侦听指定端口的所有ipif(!serverlisten(QHostAddress::Any,port)){若出错,则输出错误信息qDebug()servererrorString();return;}修改按键文字ui。btnlistensetText(取消侦听);}else{socketabort();取消侦听serverclose();修改按键文字ui。btnlistensetText(侦听);}}voidTcpServer::ClientConnect(){解析所有客户连接while(serverhasPendingConnections()){连接上后通过socket获取连接信息socketservernextPendingConnection();QStringstrQString(〔ip:1,port:2〕)。arg(socketpeerAddress()。toString())。arg(socketpeerPort());提示连接成功ui。textEditserverappend(strConnecttotheserver);复选框选项为连接服务器的ipui。comboBoxaddItem(str);将socket地址放入combobox属性内ui。comboBoxsetItemData(ui。comboBoxcount()1,QVariant((int)socket));监听客户端是否有消息发送connect(socket,QTcpSocket::readyRead,this,TcpServer::ReadData1);}}获取客户端向服务器发送的信息voidTcpServer::ReadData1(){QByteArraybufsocketreadAll();readAll最多接收65532的数据QStringstrQString(〔ip:1,port:2〕)。arg(socketpeerAddress()。toString())。arg(socketpeerPort());ui。textEditserverappend(strQString(buf));}服务器向客户端发送信息voidTcpServer::onbtnserverclicked(){if(ui。comboBoxcount()0)return;QTcpSocketskt(QTcpSocket)ui。comboBoxitemData(ui。comboBoxcurrentIndex())。valueint();socketwrite(ui。lineEdit1text()。toUtf8());}
  注意:write中需要写入char类型的元素或QByteArray类型的元素
  效果展示:
  三,TCPIP文件传输
  上文实现了消息的传输,由于socketreadAll();(readAll最多接收65532的数据),因此对于大文件的传输用此方法是不可取的。
  点击领取Qt学习资料视频教程链接
  TCPIP文件传输的思路:客户端和服务器连接客户端选择文件,并发送文件给服务器(发送的是文件的帧头,格式:文件名大小)服务器触发readyRead,然后解析文件帧头(获取文件名和大小),并返回客户端一个ok消息客户端触发readyRead,然后发送文件数据,通过progressBar显示进度服务器再次触发readyRead,接收文件数据,并保存(通过ishead判断接收的是文件帧头还是文件数据)
  代码实现:
  新建服务器项目(TcpServer)TcpServer。hpragmaonceincludeQtWidgetsQWidgetincludeuiTcpServer。hincludeqtcpserver。hincludeqtcpsocket。hpragmaexecutioncharacterset(utf8)classTcpServer:publicQWidget{QOBJECTpublic:TcpServer(QWidgetparentQNULLPTR);voidhasConnect();private:Ui::TcpServerClassui;QTcpServerserver;QTcpSocketsocket;boolishead;QStringfileName;intfileSize;接收文件的总大小intrecvSize;当前接收文件的大小QByteArrayfilebuf;当前接收的文件数据};TcpServer。cppincludeTcpServer。hincludeqfile。hTcpServer::TcpServer(QWidgetparent):QWidget(parent){isheadtrue;ui。setupUi(this);servernewQTcpServer(this);监听1122端口的ipserverlisten(QHostAddress::Any,1122);如果有用户连接触发槽函数connect(server,QTcpServer::newConnection,this,TcpServer::hasConnect);}voidTcpServer::hasConnect(){while(serverhasPendingConnections()0)判断当前连接了多少人{用socket和我们的客户端连接,一个客户端对应一个套接字socketsocketservernextPendingConnection();服务器界面上输出客户端信息ui。textEditappend(QString(1:新用户连接)。arg(socketpeerPort()));如果客户端发送信息过来了,触发匿名函数connect(socket,QTcpSocket::readyRead,〔〕(){QByteArraybufsocketreadAll();用一个标志位ishead判断是头还是数据位if(ishead){如果是头,解析头(文件名,文件大小)QStringstrQString(buf);ui。textEditappend(str);QStringListstrliststr。split();fileNamestrlist。at(0);解析帧头文件名fileSizestrlist。at(1)。toInt();解析帧头文件大小isheadfalse;下次接收到的文件就是我们的数据recvSize0;filebuf。clear();socketwrite(ok);}else{根据文件名和文件大小接收和保存文件filebuf。append(buf);recvSizebuf。size();每接收一次文件,当前文件大小1当接收文件大小等于总文件大小,即文件数据接收完毕if(recvSizefileSize){保存文件QFilefile(ui。lineEdittext()fileName);file。open(QIODevice::WriteOnly);file。write(filebuf);file。close();isheadtrue;}}});}}
  新建客户端项目(QTcpClient)QTcpClient。hincludeQtWidgetsQWidgetincludeuiQTcpClient。hincludeqtcpsocket。hpragmaexecutioncharacterset(utf8)classQTcpClient:publicQWidget{QOBJECTpublic:QTcpClient(QWidgetparentQNULLPTR);publicslots:voidonbtnconnectclicked();voidonbtnchooseclicked();voidonbtnopenclicked();private:Ui::QTcpClientClassui;QTcpSocketsocket;};QTcpClient。cppincludeQTcpClient。hincludeqfiledialog。hincludeqfileinfo。hQTcpClient::QTcpClient(QWidgetparent):QWidget(parent){ui。setupUi(this);socketnewQTcpSocket(this);}voidQTcpClient::onbtnconnectclicked(){QStringipui。lineEditiptext();获取ipintportui。lineEditporttext()。toInt();获取端口数据socketconnectToHost(ip,port);连接服务器等待连接成功if(socketwaitForConnected()){ui。textEditappend(fontcolorgreen连接服务器成功!font);ui。btnopensetEnabled(true);如果服务器发送信息到客户端,触发匿名函数connect(socket,QTcpSocket::readyRead,〔〕(){读取服务器发送的信息(即缓冲区信息)QByteArraybufsocketreadAll();if(bufok){QFilefile(ui。labelpathtext());if(!file。open(QIODevice::ReadWrite)){读取文件失败return;}qint64currentlen0;当前已经发送的大小qint64allLengthfile。size();总文件大小do{chardata〔1024〕;qint64msizefile。read(data,1024);读文件放入打他数组中,返回读取到的大小socketwrite(data,msize);把读取到的data数据发送给服务器currentlenmsize;实时获取当前发送的文件大小ui。progressBarsetValue(currentlen100allLength);更新界面进度条}while(currentlenallLength);当发送文件等于文件大小时,发送完毕,循环结束}});}else{ui。textEditappend(fontcolorred连接服务器失败!font);}}选择文件事件voidQTcpClient::onbtnchooseclicked(){QStringpathQFileDialog::getOpenFileName(this,打开文件,,(。));ui。labelpathsetText(path);}发送文件事件voidQTcpClient::onbtnopenclicked(){QFileInfoinfo(ui。labelpathtext());用QFileInfo::fileName,size获取文件名和大小格式:文件名大小服务器用该格式解析文件名和大小QStringheadQString(12)。arg(info。fileName())。arg(info。size());将该格式发送给服务器toUtf8:QString转QByteArray或char类型socketwrite(head。toUtf8());}
  效果展示:

你觉得洪金宝和梁小龙谁的功夫更厉害?梁小龙的功夫会更高一筹,因为梁小龙从小接受的就是武术名家的指导,有北派的功夫,练习过咏春拳,练习过空手道,其综合能力是非常强大的。如果不是在街头打架,也想也是不会有现在的影视演员梁如果我要发起成立发扬祭祖传统文化协会,你赞成吗?不赞成,未经批准的任何协会都是非法的。一,祭祖传统各地区习惯不同差异很大不能统一,以何为标准?二,不能以传统的幌子,贩卖封建迷信,获取经济历益大开绿灯。三,任何以传统为噱头推销落后为什么很多人喜欢机械键盘?机械键盘的几个贵的和普通的价格相差几乎510倍。机械键盘成本真的很贵吗?我们先来看看机械键盘的诞生,这种键盘其实就是最原始的键盘,1951年,计算机开始使用键盘作为录入设备时就采用为什么年轻人多次强调汉服是传统服装,但在街上看到还是怪怪的?太花里乎哨,不好搭配,多为所谓唐装配西裤皮鞋,定议为休闲,个人观点习以为常,不习惯当然不能为常。汉服是个从天上掉下来的传统,它当前仍然只是个打着传统招牌的新兴潮流事物罢了。其实这几功夫巨星李小龙创造了9大世界纪录,你对李小龙猝然离世怎么看?李小龙创造九大世界纪录,我不了解,对他的去世,没有其它特殊的看法,本人认为人总是要死的,黄泉路上不分大小富贵贫贱,任何人都应一视同仁才是,切勿把一个凡人捧为圣人来崇拜,这样是会让自在DNF中,对于红眼来说是铁马好还是万世套好?就目前来说,讨论铁马还是万世其实挺没意义的,因为可能你都带不了几天然后几天升级b套了,然后b套又带不了几个月,又升级95aa套了,所以如果是现在打算升级,那么我们还是从长计议,看看你被网络诈骗后过得怎样?被网络诈骗起因是在小红书上搜搜副业,因为自己也有负债。然后就有人私信问需不需要资金的,不上征信,然后大晚上脑子糊糊涂涂的觉得还挺好,就加了QQ。QQ认证还是私人借款官方账户当时还以网络游戏里的鬼服村服官服分别是什么意思?官服就是官方正版授权的平台,一般都是大平台,人相对比较多,当然,目前的页游都是一两天开个服,甚至一天开两个服务器,所以人也多不到哪去了,但是相比鬼服和村服还是要多不少,当然,里面托为什么和平精英刚枪的玩家越来越少,LYB越来越多了?关于和平精英中,越来越多的人喜欢阴人而不刚枪,令那些走着走着突然暴毙的玩家,心中反感至极。为什么会有这种现象呢?实力不足很多白金钻石的玩家,渴望上分,但又刚不过高分段的玩家,于是只在游戏三国志11中,哪个谋士的控制效果最强?为什么?大家好,欢迎乘坐游戏探索机!说到游戏三国志11里面的控制,我们可以把它分为硬控和软控两种,其中硬控指的是物理攻击附带的控制效果,而软控则是指谋士用计谋控制敌军部队。游戏里最常见的控如美国新太空武器可破坏卫星发射,中国会重新考虑美加入空间站么?卫星太空发射,指的是卫星从装到载具上做好准备到进入到预定轨道的全过程,如果在这一过程中进行破坏,那就可以说具备了破坏卫星发射的能力。那美国具备了这一能力吗?当然具备了。不仅仅是美国
站洋币是属于哪个国家的钱币目前站洋币收藏空间如何在清代时期除了有属于我们本国铸造的货币以外还有一部分国外的钱币,这批钱币是当时联军侵华时留下来的一些钱币,我们今天把这种钱叫做外贸币。外贸币当时的主要作用就是为了促进我们国家的贸易罕见历史老照片一希特勒画的狗狗。如果希特勒没有参军可能是位画家,毕竟艺术生啊。二硬核投喂,战斗民族开坦克投喂北极熊。三大才女林徽因,那时的她只有3岁。四还是幼师的戴安娜王妃。五人类首次登上珠穆朗匈奴帝国盛极一时的匈奴帝国,最后人都去了哪里匈奴是我国北方一个古老民族,分布在蒙古高原一带,过着游牧生活,以强悍和善骑射著称。据史记中记载,匈奴人的先祖是夏王朝遗民,在西迁的过程中融合了月豪雄刘邦以汉命名汉朝其实深有玄机编者按一字一文化,一字一历史。每个汉字都有生命的温度,都有文化之美,横竖撇捺之间,都饱含先人智慧。解读汉字密码,感受历史沉浮,揭示王朝名称用字背后的玄机。秦王朝统一六国之后在政策措山西运城一家族历代出超150名丞相将军尚书,因这12条家训江山代有才人出,各领风骚数百年。这个世界美就美在它具有多样性,让我们总能见到各色各样优秀的人。但有的时候我们仍不免发现,有些优秀的人还真是来自于同一家族,就比如著名的一门三父子都是4场轰99分!不愧是中国男篮新帅的免检球员!最强大前锋王者归来我们知道,中国男篮新帅乔尔杰维奇考察队员时有个习惯,就是喜欢根据球员表现,随时在球员花名册上标星。用乔帅的话说,标星评价只是他考察队员的一个方式。在乔帅观赛期间,现场画面经常捕捉到2022年10大排名最强护照国和8大最差护照国世界各国护照2022年,总部位于英国伦敦的亨利公司(HenleyPartners),根据其亨利护照指数评分方案,显示指数评级最高的是日本和新加坡,可以免签证前往192个地方。这比阿卖得越多亏损越厉害造车新势力能不能找到良方?2022年马上结束,对大多数的主流新能源汽车厂商来说,这又是收获颇丰的一年。但需要注意的是,收获也分很多种。以蔚来理想小鹏为代表的造车新势力现阶段的收获主要体现在销量上,然而作为汽鹈鹕5换1报价2710后卫!锡安迎来最强帮手的辅佐,鹈鹕起飞了?报价背景鹈鹕在锡安的强势带领下,一路高歌猛进,登顶西部第一,但由于最近的一波2连败,又跌到了西部第三,最关键的是锡安还遭遇了腿筋拉伤,至少要缺席三周以上,并且英格拉姆一直都在养伤,华为P60Pro硬件配置曝光,有望成为小米13Ultra的最强对手说到国产手机厂商旗舰机的巅峰对决,当属要看华为和小米的旗舰大战。前不久小米发布了小米13系列数字旗舰,而最新消息则曝光华为P60Pro硬件配置,从硬件配置来看,华为P60Pro定义1947年,一老太到部队找儿子,被哨兵拦住,没想到她儿子是司令员1947年,一老太到部队找儿子,被哨兵拦住,没想到她儿子是司令员1947年12月,几名解放军推着一名老太太,来到晋冀鲁豫野战军第三纵队司令部驻地湖北麻城新田铺村。司令部并不是想进就
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网