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

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地址查看本机ipQTcpClinet。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的数据),因此对于大文件的传输用此方法是不可取的。
  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());}
  效果展示:
  点击领取Qt学习资料视频教程链接

男女之间,出现这些情况,一定是动了真情爱上一个人,都希望心有灵犀。每个内心深处都向往着,那些一见钟情,而相互倾心的人。能让彼此感受到心跳,和那份许久的宁静然而,那种美好的感情似乎只有电视剧里才会有,平常生活中似乎并不常世界杯四强浮出水面!极端情况5大洲或全军覆没,4年前神迹重现2022世界杯在北京时间12月9日晚间,世界杯四分之一决赛将拉开帷幕,当4场比赛结束后,本届世界杯的半决赛对阵形势就将产生。根据现在的情况来看,世界杯四强浮出水面!极端情况5大洲或职场耳机使用情况调查显示六成受访者会在上班时戴耳机耳机作为当代年轻人工作娱乐必不可少的数码产品,常常出现在人们工作和生活的各个场景中,随时随地使用耳机不仅成为一种习惯,也是一种互不干扰的社交礼仪。在有109位职场人参与的职场耳机使改善皮肤暗黄干燥护肤方法让你越来越美丽正所谓一白遮百丑,但是不难发现,我们平时生活当中,大多数人的肤色都是偏黄的,只有少数人的皮肤白里透红,这种黄指的是不健康的黄,有些是可以通过调理祛黄美白的。因此,当发现近期面部出现7分险胜活塞,哈姆差点又玩砸!苏群赛后5字形容湖人,杀人诛心啊客场作战的湖人队,刚刚以124比117击败活塞。这场比赛,紫金军团赢得并不轻松。上半场持续取得领先优势的情况下,湖人第三节突然遭遇崩盘。在防守方面,他们让活塞队的老将博扬单节轰下2适合孩子吃的4种水果,宝宝更聪明,还更容易拥有一双大长腿经常吃这4种水果,不仅可以让宝宝更聪明,还更容易拥有一双大长腿!苹果园里有苹果的女孩。果园里吃有机苹果的美丽女孩。收获概念。花园,GirlwithApple多吃蔬菜水果,让孩子的身天天清淡饮食,为何还是血脂异常?健康食物中也有高脂陷阱,很多人却忽视了在我们的血管中存在一个头号垃圾,若其含量超标,会直接导致心血管疾病的发生,而且即便化验单上的数值在标注范围,也并不代表万无一失它就是低密度脂蛋白胆固醇。低密度脂蛋白胆固醇以颗粒的形微信密码忘记了,怎么登录?分享4个方法,总有一个适合你因为微信在手机上登录过后,只要不特地去退出,永远都是保持登录状态的,即使关掉手机再开机后,进入微信依然不用再次输入密码。也因为如此,久而久之,连密码也不再记得了。当某一天不小心退了高血压,病根在于中气不足,一张方子补气降压,快收藏我一个蜗居在城市里的凡人,除了每天在医院忙碌,剩余的时间就是想把自己多年的中医临床经验分享给大家,如果有不对的地方,也请大家指导!今天我给大家讲一下关于高血压的事情之前遇到这一个患豆腐是绿色健康食品,但对于糖尿病患者来说,2种豆腐可别吃豆腐,在我国的历史十分悠久,迄今为止,已有二千一百多年,深受祖祖辈辈的喜爱。发展到现在的豆制品,豆干腐竹豆浆豆皮豆腐丝等等,不仅种类多,风味还十分独特,制作简单又美味,是绿色健康食产量超全国三成!全网关注的黄桃罐头这个地方最强平淡无奇的黄桃罐头,在2022年大雪节气后,再次被关注。曾有段子说,东北人都是被黄桃罐头骗大的,过去物质匮乏的年代,多少东北人装感冒只为了吃一口黄桃罐头。谁要说黄桃罐头不好,东北人
近3天,盘点主力资金大幅买入100股及最大卖出100股名单更新日期2月26日单纯一天的主力资金局限性较大,很可能遇到一日游,在此汇集近3日(交易日)主力资金动向,了解主力资金高抛低吸哪些个股,以便辅助后市操作。一主力买入近3日主力资金净买在春暖花开的南澳岛,向快乐启辰汕头,近代中国最早对外开放的城市之一南澳岛,海上丝绸之路的重要节点。当然,相信不少人对它的了解都是从韩寒的四海开始的。一首歌一部电影带火一座城,这样的案例并不少见,但能够被慧眼识珠相约大冶共赏春色湖北日报讯(通讯员宋露露)粉桃画保安,梨雪铺仙桥桃园玫瑰红,金湖生铜草春到江南时,才道春光好何处赏花香,一城冶花娇。走进大冶的春天里,一幅万花齐放的盛景让无数游客为之沉醉。花海知音鲲鹏极目大美怀化一条会跳舞的河鲲鹏极目大美怀化(如今的水之畔,高楼耸立产业兴旺人民富足。)一条会跳舞的河航拍水河怀化段图文怀化日报全媒体记者潘雨通讯员杨志东一条河,是时间的沉淀,是岁月的印记,更是生命的歌谣。它彩云之南再行记之六十德宏州篇之十三瑞丽之九弄岛2017年9月23日上午8点,坐车前往瑞丽市弄岛镇。弄岛,地处瑞丽市西南部,距瑞丽市区30公里,地处中缅界河瑞丽江边,与缅甸重镇南坎(原中国领土)县城,隔江相望。自然地貌由平坝山地西双版纳西双版纳花卉,我喜欢花卉。随手拍,就是一道风景,傣族的妇女,黑黑的长发,高高的盘起,在插上一串鲜花。大部分人长的是国字脸型。坐在傣族竹凳子上绣花。还有傣族妇女喜欢喝酒,这是个女权的玉溪通海千亩花开醉春风二月正是百花争艳的时节在玉溪市通海县高大乡路南村老黑山的千亩果林中樱桃花刚刚谢幕千万株桃花梨花杏花就纷纷登场连绵起伏的山坡上层层铺叠的花朵似织锦一般绵软厚重微风一吹,香风漫漫置身其从开年大涨到最惨一周,美股经历了什么?本周最后一个交易日,美股三大指数低开低走,收盘显著下跌,均创下今年以来最差周度表现。其中,标普500指数周内下跌2。67,纳指跌3。33,而本周下跌2。99的道指,更是创去年9月份80亿全投在带毛的,今天,君乐宝当家人魏立华激动得有点哽咽2012年,我们第一次制定了企业愿景,要成为中国乳制品企业的领先品牌,那年君乐宝的销售额只有10亿,当时大家都觉得不可能,不好意思,口号有点大俗话说家财万贯,带毛的不算,但君乐宝这提前还房贷,我开始后悔了深燃(shenrancaijing)原创作者王敏邹帅李秋涵唐亚华编辑唐亚华提前还房贷的话题高居热门话题榜已经有一年多的时间了。最近,考研名师张雪峰吐槽房贷利率高接力贷连心贷等多个热消费金融机构利率上限再调整传闻争议一石激起千层浪!近日,市场传闻多家持牌消费金融机构收到监管部门的窗口指导,将利率上限从24调降至20。这让我们相当惊讶。一位助贷机构运营总监告诉记者。不过他所在的助贷机构向多家合作
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网