socket通信-服务器端

服务器

  1. 新建工程,Base class选择QWidget,在工程文件tcpServer.pro中添加一行代码:QT += network。
QT += core gui
QT += 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。

posted @ 2017-07-03 14:58  云胡同学  阅读(133)  评论(0编辑  收藏  举报