socket通信-服务器端

来源:互联网 发布:热阻流软件 编辑:程序博客网 时间:2024/05/24 01:21

服务器

  1. 新建工程,Base class选择QWidget,在工程文件tcpServer.pro中添加一行代码:QT += network。
QT += core guiQT += network
  1. ui中添加一个label,用于显示状态信息。

  2. 在widget.h文件中做以下更改。

添加头文件:

#include<QtNetwork/QtNetwork>

添加private对象:

QTcpServer *tcpServer;

添加私有槽函数:

private slots:void sendMessage();

4.在widget.cpp文件中进行更改。

Widget::Widget(QWidget *parent) :    QWidget(parent),    ui(new Ui::Widget){    ui->setupUi(this);    tcpServer = new QTcpServer(this);           if(!tcpServer->listen(QHostAddress::LocalHost,6666))            {  //监听本地主机的6666端口,如果出错就输出错误信息,并关闭               qDebug() << tcpServer->errorString();                close();            }         connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage()));}

监听主机的6666端口,然后关联了newConnection()和我们自己的sendMessage()函数。这时候是准备状态,服务器的socket并没有被打开。

如果6666端口有来自客户端socket请求,也就是客户端请求连接服务器,服务器的socket会被动打开,开始接受客户端的情求,此时服务器的socket阻塞,禁止接受其他客户端的socket请求,知道客户端返回信息后才返回。

第一次握手:客户端尝试连接服务器,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认

第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态

第三次握手:第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

void Widget::sendMessage(){    QByteArray block; //用于暂存我们要发送的数据    QDataStream out(&block,QIODevice::WriteOnly);    //使用数据流写入数据    out.setVersion(QDataStream::Qt_4_6);    //设置数据流的版本,客户端和服务器端使用的版本要相同    out<<(quint16) 0;    out<<tr("你好啊!!!");    out.device()->seek(0);    out<<(quint16) (block.size()-sizeof(quint16));    //out<< (quint16) (block.size()–sizeof(quint16));    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();    //我们获取已经建立的连接的子套接字    connect(clientConnection,SIGNAL(disconnected()),clientConnection,            SLOT(deleteLater()));    clientConnection->write(block);    clientConnection->disconnectFromHost();    ui->statusLabel->setText("send message successful!!!");    //ui->statusLabel->setText(“send message successful!!!”);    //发送数据成功后,显示提示}

数据发送函数:
1. 为了客户端收到完整的文件大小,最开始写入完整文件的大小信息,服务器端最开始无法预知发送文件的大小,所以我们先使用了out<<(quint16) 0;在block的开始添加了一个quint16大小的空间,也就是两字节的空间,它用于后面放置文件的大小信息。然后out<

clientConnection->write(block);

将block的数据写入到建立连接的Tcp socket中

然后是clientConnection->disconnectFromHost();它表示当发送完成时就会断开连接,这时就会发出disconnected()信号,而最后调用deleteLater()函数保证在关闭连接后删除该套接字clientConnection。