fedora14 基于Qt的TCP发送文本信息 聊天室 开发记录

30 篇文章 0 订阅
5 篇文章 0 订阅

      TCP协议部分,还真让我迷糊了好大一会。原因是刚弄完UDP,UDP的本地端和远程端代码是完全一样的。只是初始化在构造函数里,绑定的本地Ip地址不同,这点有函数getIp()自动完成。因此本地和远程完全一样。但Tcp部分不是这样,我这里总结一下(本人水平很低级的,属菜鸟未入门级。总结下只是防自己忘):

一,服务器端:

       整个工作流程是:如下图:

     

   程序的核心部分在tcpNewConnect()这个函数里,当服务器收到连接时会触发这个槽函数。这个函数实现为:

//服务器监听到客户端连接时,服务器的响应槽函数
void Widget::tcpNewConnect()
{
    QMessageBox box;
    box.setText("tcp客户端,请求连接....");
    box.exec();
    tcpsocketServer = tcpServer->nextPendingConnection();
    connect(tcpsocketServer, SIGNAL(readyRead()), this, SLOT(tcpReadmesg()));
    connect(ui->tcpSendButton, SIGNAL(clicked()), this, SLOT(tcpSendmesg()));
    ui->tcpSendButton->setEnabled(true);

}

这个时候tcpsocketServer被实例化了,tcpsocketServer是一个QTcpSocket类型的,我为了区别客户端的tcpSocket给加了后缀server。 也就是说tcpServer的作用仅仅是监听,监听到了就实例化一个QTcpSocket,剩下的工作由这个QTcpSocket来完成,包括接收信息和发送信息。

//TCP端的接收信息并显示槽函数
void Widget::tcpReadmesg()
{
    QTextCodec *tc=QTextCodec::codecForName("UTF-8");
    QByteArray data = tcpsocketServer->readAll();
    QString str = tc->toUnicode(data);


    QDateTime time;
    QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");


    autoScroll();
    ui->getTextEdit->setTextColor(QColor("red"));
    ui->getTextEdit->insertPlainText("远程" + remoteIpStr+": "+ timeStr +"--TCP--\n" );
    ui->getTextEdit->setTextColor(QColor("black"));
    ui->getTextEdit->insertPlainText(str + "\n" );
    autoScroll();
}


//TCP端的发送文本槽函数
void Widget::tcpSendmesg()
{
    autoScroll();
    QString str = ui->sendTextEdit->toPlainText();
    if(str.length()==0)
    {
        QMessageBox box;
        box.setText("请输入内容后再发送!");
        box.exec();
    }
    else
    {
        QByteArray data = str.toAscii();
        // qDebug()<<str;
        tcpsocketServer->write(data);
        QDateTime time;
        QString timeStr = time.currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");


        ui->getTextEdit->setTextColor(QColor("red"));
        ui->getTextEdit->insertPlainText("本机" + localIpStr + ": " + timeStr + "--TCP--\n");
        ui->getTextEdit->setTextColor(QColor("black"));
        ui->getTextEdit->insertPlainText(str +"\n");
        ui->sendTextEdit->clear(); //点击发送后,发送编辑框内清零
        ui->sendTextEdit->setFocus(); //焦点停留在发送编辑框
        autoScroll();
    }
}

       有了UDp的经验,这两个函数还算好些,至少编码解码上不会出问题了。服务器端和接收端的显示发送函数都是一样的。接收函数用的QByteArray data = tcpsocketServer->readAll();发送函数写数据用的 tcpsocketServer->write(data);着和UDP的发送接收还是有区别的。当然了只是发送简单的文本可以这么搞,如果发送大文件,估计没这么简单了。

二、Tcp客户端

     客户端只有一个QTcpSocket *tcpSocket,在构造函数里tcpSocket = new QTcpSocket(this),我们希望按下“连接”按键,客户端发出请求连接。这个按键的槽函数是:

//客户端,按下启动TCP按键的槽函数
void Widget::on_startTcpBtn_clicked()
{
    remoteIpStr = ui->ipEdit->text();
    port = ui->portEdit->text();
    tcpSocket->abort(); //取消原来的连接
    tcpSocket->connectToHost(remoteIpStr, port.toInt());
}

      核心的一句话是tcpSocket->connectToHost(remoteIpStr, port.toInt());注意这里remoteIpStr是个QString类型的变量,您也可以写成tcpSocket->connectToHost(“192.168.2.211”, 6665)这样来测试下是没问题的。也可以写成 remoteHostAddr = new QHostAddress(remoteIpStr); tcpSocket->connectToHost(*remoteHostAddr, port.toInt());这样也是没有问题的!看来qt还是很灵活的。

     另外,在客户端的构造函数里还应该连接四个槽函数:

connect(tcpSocket, SIGNAL(connected()), this,SLOT(tcpIsConnect()));    //已经连接上时的槽函数

connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(tcpFailConnect())); //断开连接时的槽函数

 connect(ui->tcpSendButton, SIGNAL(clicked()), this, SLOT(tcpSendmesg())); //发送消息
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(tcpReadmesg()));        //收到消息

发送消息、接收消息的和上面一样,前两个槽函数只是弹出个提示就行啦,如下:

bool Widget::tcpIsConnect()
{
    ui->tcpSendButton->setEnabled(true);
    QMessageBox box;
    box.setText("恭喜您,TCP连接已建立!");
    box.exec();
    return true;
}
void Widget::tcpFailConnect()
{
    ui->tcpSendButton->setEnabled(false);
    QMessageBox box;
    box.setText("TCP连接失败,请重新连接或使用UDP发送!");
    box.exec();
}

      最后,总结下让我一开始云里雾里的基于Qt的TCP协议实现:

      只有两个类用到,QTcpServer和QTcpSocket,服务器端用到一个QTcpServer和一个QTcpSocket;客户端只用一个QTcpSocket。QTcpServer的作用是监听对方的连接,因此开始时要设置监听的端口号或者监听具体的Ip地址。当有客户端连接时,QTcpServer调用 tcpsocketServer = tcpServer->nextPendingConnection();来实例化服务器端的QTcpSocket,然后剩下的发送和接收都由这个QTcpSocket来担当!客户端用到QTcpSocket,让他发送连接请求,当连接成功后又会触发一个函数。

      一句话:数据的发送、读取永远由QTcpSocket来担当!!!QTcpSocket还可以发送连接请求,QTcpServer进行监听,并得到发送请求的QTcpSocket实例。

核心的代码,红色加下划线的部分。

疑惑:服务器端在侦听到连接请求时,如果不想连接客户端,拒绝怎么搞?估计应该再服务器端加个按键,按键槽函数里用QTcpServer的一些方法进行拒绝。继续研究啊还得!



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值