共计 5443 个字符,预计需要花费 14 分钟才能阅读完成。
本来今天学习到多线程的一个实例,这个实例是基于多线程抓取服务器时间,这中间运用到TCP网络编程这块,之前看过TCP那块(其实忘记差不多了,现在回过头来看看)。
TCP三次握手
TCP建立连接的三次握手就是这个样子了,其实这篇文章关注的并不是三次握手。
本篇文章主要是说建立C/S模型即客户端与服务端进行通信,通过一个小例子来说明
这两幅图其实是COPY过来的文件传递,别人是实现的服务端与客户端之间文件的传递,本文的例子通过发一些字符串来演示。
先看服务端的代码:
#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
#include <QObject>
#include "tcpclientsocket.h"//这个是一个继承与Tcpsocket的类
class Server : public QTcpServer
{
Q_OBJECT
public:
Server(QObject *parent=0,int port=0);
QList<TcpClientSocket*> tcpClientSocketList;//保存所有与服务端建立连接的客户端服务
signals:
void updateServer(QString,int);
public slots:
void updateClients(QString,int);//更新客户端
void slotDisconnected(int);//中断连接的槽函数
protected:
void incomingConnection(int socketDescriptor);//新连接函数,捕捉来自客户端的连接
};
#endif // SERVER_H
#include "server.h"
Server::Server(QObject *parent,int port)
:QTcpServer(parent)
{
listen(QHostAddress::Any,port);//监听所有IP地址和端口
}
void Server::incomingConnection(int socketDescriptor)//socketDescriptor来自客户端的IP PORT信息
{
TcpClientSocket *tcpClientSocket=new TcpClientSocket(this);
//前面的updateClients(QString,int)是tcpClientSocket信号函数,有新的客户端就会激活,后面的槽函数是服务端重写的函数
connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,SLOT(updateClients(QString,int)));
//同上
connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int)));
//服务端绑定socketDescriptor
tcpClientSocket->setSocketDescriptor(socketDescriptor);
//加入套接字列表中
tcpClientSocketList.append(tcpClientSocket);
}
void Server::updateClients(QString msg,int length)
{
emit updateServer(msg,length);//通知服务器对话框进行相应的更新
for(int i=0;i<tcpClientSocketList.count();i++) //通知所有人,信息广播
{
QTcpSocket *item = tcpClientSocketList.at(i);
if(item->write(msg.toLatin1(),length)!=length)
{
continue;
}
}
}
void Server::slotDisconnected(int descriptor)
{
for(int i=0;i<tcpClientSocketList.count();i++)
{
QTcpSocket *item = tcpClientSocketList.at(i);
if(item->socketDescriptor()==descriptor)
{
tcpClientSocketList.removeAt(i);
return;
}
}
return;
}
客户端代码如下:
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QDialog>
#include <QListWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QGridLayout>
#include <QHostAddress>
#include <QTcpSocket>
class TcpClient : public QDialog
{
Q_OBJECT
public:
TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
~TcpClient();
private:
QListWidget *contentListWidget;
QLineEdit *sendLineEdit;
QPushButton *sendBtn;
QLabel *userNameLabel;
QLineEdit *userNameLineEdit;
QLabel *serverIPLabel;
QLineEdit *serverIPLineEdit;
QLabel *portLabel;
QLineEdit *portLineEdit;
QPushButton *enterBtn;
QGridLayout *mainLayout;
bool status;
int port;
QHostAddress *serverIP;
QString userName;
QTcpSocket *tcpSocket;
public slots:
void slotEnter();
void slotConnected();
void slotDisconnected();
void dataReceived();
void slotSend();
};
#endif // TCPCLIENT_H
#include "tcpclient.h"
#include <QMessageBox>
#include <QHostInfo>
TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(tr("TCP Client"));
contentListWidget = new QListWidget;
sendLineEdit = new QLineEdit;
sendBtn = new QPushButton(tr("发送"));
userNameLabel = new QLabel(tr("用户名:"));
userNameLineEdit = new QLineEdit;
serverIPLabel = new QLabel(tr("服务器地址:"));
serverIPLineEdit = new QLineEdit;
portLabel = new QLabel(tr("端口:"));
portLineEdit = new QLineEdit;
enterBtn= new QPushButton(tr("进入聊天室"));
mainLayout = new QGridLayout(this);
mainLayout->addWidget(contentListWidget,0,0,1,2);
mainLayout->addWidget(sendLineEdit,1,0);
mainLayout->addWidget(sendBtn,1,1);
mainLayout->addWidget(userNameLabel,2,0);
mainLayout->addWidget(userNameLineEdit,2,1);
mainLayout->addWidget(serverIPLabel,3,0);
mainLayout->addWidget(serverIPLineEdit,3,1);
mainLayout->addWidget(portLabel,4,0);
mainLayout->addWidget(portLineEdit,4,1);
mainLayout->addWidget(enterBtn,5,0,1,2);
status = false;
port = 8010;
portLineEdit->setText(QString::number(port));
serverIP =new QHostAddress();
connect(enterBtn,SIGNAL(clicked()),this,SLOT(slotEnter()));
connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend()));
sendBtn->setEnabled(false);
}
TcpClient::~TcpClient()
{
}
void TcpClient::slotEnter()
{
if(!status)
{
//相关设置的正确性,需要检查服务器IP等
QString ip = serverIPLineEdit->text();
if(!serverIP->setAddress(ip))
{
QMessageBox::information(this,tr("error"),tr("server ip address error!"));
return;
}
if(userNameLineEdit->text()=="")
{
QMessageBox::information(this,tr("error"),tr("User name error!"));
return;
}
userName=userNameLineEdit->text();
tcpSocket = new QTcpSocket(this);
connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
//建立与服务器的连接
tcpSocket->connectToHost(*serverIP,port);
status=true;
}
else
{
int length=0;
QString msg=userName+tr(":Leave Chat Room");
//向服务端发送消息
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg. length())
{
return;
}
//中断与服务端的连接
tcpSocket->disconnectFromHost();
status=false;
}
}
void TcpClient::slotConnected()
{
sendBtn->setEnabled(true);
enterBtn->setText(tr("离开"));
int length=0;
QString msg=userName+tr(":Enter Chat Room");
if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())
{
return;
}
}
void TcpClient::slotSend()
{
if(sendLineEdit->text()=="")
{
return ;
}
QString msg=userName+":"+sendLineEdit->text();
tcpSocket->write(msg.toLatin1(),msg.length());
sendLineEdit->clear();
}
void TcpClient::slotDisconnected()
{
sendBtn->setEnabled(false);
enterBtn->setText(tr("进入聊天室"));
}
void TcpClient::dataReceived()
{
//bytesAvailable判定socket I/O中是否存在等待被读取的数据
while(tcpSocket->bytesAvailable()>0)
{
QByteArray datagram;
datagram.resize(tcpSocket->bytesAvailable());
tcpSocket->read(datagram.data(),datagram.size());
QString msg=datagram.data();
contentListWidget->addItem(msg.left(datagram.size()));
}
}
正文完
请博主喝杯咖啡吧!