您的位置:首页 > 编程语言 > Qt开发

QT编程系列10--客户端的网络编程

2014-08-14 20:07 337 查看
客户端的网络编程
上一篇文章,我们实现了服务器端程序的编写,首先创建一个服务器对象,然后使其处于监听的状态,当有新连接过来时,进行与新连接的连接工作。连接使用的是套接字socket类实现的对象,通过该类的write方法,定时1S发送数据到连接上的客户端。我们从中可以看出,这次网络通信首先是有客户发起的,那么客户端是怎么发送这个连接的了,以及连接成功后怎么接收或发送数据的?这就是本篇要讲解的内容。

首先我们要先设计好客户端的界面布局。可以设计成如下图所示的样式,关于如何设计界面布局是前面讲过的内容,这里就不在重复。那么在这个界面包含的组件有:一个标签、两个输入框、一个编辑框及四个按钮。这些组件如何生成,如何布局在界面上请查阅前面的文章。关键的是connect、flush及save三个按钮功能是如何实现的是需要我们研究的,尤其是connect按钮。改按钮点击后会由对应的myconnect槽函数来响应。



mywindow.h文件的内容如下:

#include "mywindow.h"

mywindow::mywindow(){
	tcpsocket = new QTcpSocket;
	label = new QLabel("Server IP:");
	ledit_ip = new QLineEdit;
	ledit_ip->setInputMask("000.000.000.000;");
	ledit_ip->setText("192.168.7.200");
	ledit_port = new QLineEdit;
	ledit_port->setText("7070");
	button_connect = new QPushButton("connect");
	button_flush = new QPushButton("flush");
	button_save = new QPushButton("save");
	button_quit = new QPushButton("quit");
	hlayout_1 = new QHBoxLayout;
	hlayout_2 = new QHBoxLayout;
	layout = new QVBoxLayout;
	tedit = new QTextEdit;

	hlayout_1->addWidget(label);
	hlayout_1->addWidget(ledit_ip);
	hlayout_1->addWidget(ledit_port);
	hlayout_1->addWidget(button_connect);

	hlayout_2->addWidget(button_flush);
	hlayout_2->addWidget(button_save);
	hlayout_2->addWidget(button_quit);

	layout->addLayout(hlayout_1);
	layout->addWidget(tedit);
	layout->addLayout(hlayout_2);
	setLayout(layout);
	connect(button_connect,SIGNAL(clicked()),this,SLOT(myconnect()));
	connect(button_quit,SIGNAL(clicked()),qApp,SLOT(quit()));
	connect(tcpsocket,SIGNAL(connected ()),this,SLOT(mytt()));
	connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(myread()));
	connect(button_flush,SIGNAL(clicked()),this,SLOT(myflush()));
	connect(button_save,SIGNAL(clicked()),this,SLOT(mysave()));

}
void mywindow::mysave(void)
{
	QString name;
	name = QFileDialog::getSaveFileName();
	if(name.count() <= 0){
	QMessageBox::about(this,"save:","file name!!!");
	return ;
	}
	QFile file(name);
	if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
		return;

	QTextStream out(&file);
	out << tedit->toPlainText ();
}
void mywindow::myflush(){
	tedit->clear();
}
void mywindow::myread(void){
	QString tmp;
	int i;
	QTime tt;
	tt = QTime::currentTime ();
	QString time_str;
	time_str = tt.toString("hh:mm:ss");
	UART_Format uformat;	
	tcpsocket->read((char *)&uformat,(quint64)sizeof(uformat));	
	tmp.append(time_str);

	tmp.append(" ");
	tmp.append(QString::number (uformat.Header_1,16)); 		//cc				ee
	tmp.append(" ");
	tmp.append(QString::number (uformat.Header_2,16)); 		//ee				cc
	tmp.append(" ");
	tmp.append(QString::number (uformat.NodeSeq,16)); //模块序列 01				01
	tmp.append(" ");
	tmp.append(QString::number (uformat.NodeID,16)); //模块ID (00表示网关)	DeviceAddrList	Motor == 9 
	tmp.append(" ");
	tmp.append(QString::number (uformat.Command,16)); 			//功能 01			dd
	tmp.append(" ");
	for(i = 0; i < 10; i++){
	tmp.append(QString::number (uformat.Data[i],16)); 		//无用				保存节点的数据
	tmp.append(" ");
	}
	tmp.append(QString::number (uformat.Tailer,16)); 			//ff
	tmp.append(" ");

	tedit->append(tmp);
}
void mywindow::myconnect(void)
{
	//ip port
	QString ip;
	QString port;
	ip = ledit_ip->text();
	port = ledit_port->text();
	qDebug() << ip;
	qDebug() << port;
	tcpsocket -> connectToHost (ip,port.toInt());	

}
void mywindow::mytt(void)
{
	QMessageBox::about(this,"title:","connected!!!");
}


上文我们提到客户端与服务器端的一次网络通信首先是由客户端发起连接的,并且上文有提到这个客户端的连接是由connect按钮的点击及其槽函数实现的。代码中我们也看到了,在myconnect函数中实质性的就是做了tcpsocket -> connectToHost (ip,port.toInt()); 这样一件事。根据函数参数中给定的ip、端口进行主动连接。至此我们了解了客户端与服务器端的一次网络通信到底是怎么产生的了。

当端口接收到数据时,QT会触发一个叫做readyRead的信号,该信号与myread槽函数进行了捆绑。也就是说当有数据来的时候myread函数会进行数据的接收及处理,该存放就存放该做处理做处理。我们要注意的用C语言实现网络编程时的读数据和QT实现的不同,C中的connect及读数据是一种阻塞型的,而QT中则是使用的信号与槽来解决。因为在QT中不允许使用阻塞因此也就不需要考虑多线程了。好了到这里我们的QT网络通信的介绍就告一段落了。下面展示一下在PC上测试客户端和服务器端程序情形的图片作为本专题的结束。



By:霜月孤鸟

2014.8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐