10 qt udp编程和网络聊天室的实现

来源:互联网 发布:2015网络银行交易额 编辑:程序博客网 时间:2024/06/05 23:58

Linux系统编程:
udp 接收端:
socket(AF_INET, SOCK_DGRAM, 0);
bind(..)
recvfrom(…)

udp发送端:    socket(...)    sendto(..);    // udp 也可以connect ,但不是连接,仅是指定目标IP,端口号而已                //    connect后就可以write, send//////////////////////////////////////////////tcp服务端:    socket(AF_INET, SOCK_STREAM, 0);    bind(..)    listen(..)    accept(..)tcp客户端:    socket();    connect();

udp是无连接,tcp是连接的。
什么是连接, 其实就是与每个客户端有没有需要单独的处理。如在Linux系统编程,udp不管多少个客户端发过来数据,服务端都只调用recvfrom函数就可以,用不着分开客户端来处理。在tcp里,客户端在服务端都是由一个不同的文件描述符来的区分的,在服务端操作不同的文件描述符就意味着与不同的客户端通信。

在QT里, udp和tcp 都封装成类. 其实就是把linux系统的网络编程封装成类.

Udp : QUdpSocket
tcp: QTcpServer, QTcpSocket

udp用法:
1不管是发送端或接收端都需要创建一个QUdpSocket对象(创建对象时,内部会socket());
2 发送端直接调用对象的writeDatagram就可以了, 发出数据后也会有bytesWritten()信号。  
3 接收端还需bind, 然后当有数据需接收处理,会有readyRead()信号,再调用readDatagram接收数据.

Qt里的udp默认就可以支持广播功能,只要往广播地址发送数据即可实现。

利用udp广播实现网络聊天室:

pro工程文件里: QT += gui core widgets network

mywin.h#ifndef MYWIN_H#define MYWIN_H#include <QWidget>#include <QTextEdit>#include <QLineEdit>#include <QPushButton>#include <QLabel>#include <QHBoxLayout>#include <QVBoxLayout>#include <QUdpSocket>#define PORT  7788class MyWin : public QWidget{    Q_OBJECTprivate:    QTextEdit *txt; //用于显示接收到内容    QLineEdit *lnd_ip; //用于接收用户发送数据的目标IP    QLineEdit *lnd_send; //接收要发送的数据    QLabel    *lbl_ip;    QLabel    *lbl_send;    QPushButton *btn_send; //发送按钮    QHBoxLayout *hlayout;    QVBoxLayout *vlayout;    QUdpSocket  *udp;public:    explicit MyWin(QWidget *parent = 0);    ~MyWin();signals:public slots:    void slot_btn();    void slot_udp_recv();};#endif // MYWIN_H
mywin.cpp#include "mywin.h"#include <QMessageBox>#include <QDebug>MyWin::MyWin(QWidget *parent) : QWidget(parent){    //初始化界面    txt = new QTextEdit;    lnd_ip = new QLineEdit("192.168.250.255"); //默认广播地址    lnd_send = new QLineEdit("hello udp");    btn_send = new QPushButton("send");    lbl_ip = new QLabel("ip:");    lbl_send = new QLabel("text:");    hlayout = new QHBoxLayout;    hlayout->addWidget(lbl_ip, 1);    hlayout->addWidget(lnd_ip, 3);    hlayout->addWidget(lbl_send, 1);    hlayout->addWidget(lnd_send, 4);    hlayout->addWidget(btn_send, 1);    vlayout = new QVBoxLayout(this);    vlayout->addWidget(txt, 8);    vlayout->addLayout(hlayout, 2);    resize(640, 480);    ///////////////////    // udp对象初始化    udp = new QUdpSocket(this);    if (!udp->bind((PORT)))//绑定端口号    {        QMessageBox::critical(this, "error", "bind failed");        exit(0);    }    //连接按钮的单击信号    connect(btn_send, SIGNAL(clicked(bool)), this, SLOT(slot_btn()));    // 连接udp对象的readyRead信号    connect(udp, SIGNAL(readyRead()), this, SLOT(slot_udp_recv()));}MyWin::~MyWin(){    delete txt;    delete lnd_ip;    delete lnd_send;    delete lbl_ip;    delete lbl_send;    delete hlayout;    delete vlayout;    delete udp;}void MyWin::slot_btn(){    //发送数据    QString str = lnd_send->text();    QString ip = lnd_ip->text();    udp->writeDatagram(str.toUtf8(), QHostAddress(ip), PORT); //发出的数据是utf8编码}void MyWin::slot_udp_recv(){    char *data;    int ret , len = udp->pendingDatagramSize()+1;    QHostAddress peer; //用于接收对方的IP地址    quint16 port;    QString ip, str("%1[%2]:%3"); //表示此字符是由三个参数组成的    data = new char[len];    ret = udp->readDatagram(data, len, &peer, &port); //接收数据,并存放对方的IP地址端口号    if (ret <= 0)        return;    data[ret] = 0; //设尾0    // ip[port] : data    // ip地址默认是64位,需转成32位    ip = QHostAddress(peer.toIPv4Address()).toString(); //用32位的地址创建对象,再获取地址    str  = str.arg(ip).arg(port).arg(data);    txt->append(str);    txt->moveCursor(QTextCursor::End); //自动翻到最后一行}
main.cpp#include <QApplication>#include "mywin.h"int main(int argc, char *argv[]){    QApplication a(argc, argv);    MyWin win;    win.show();    return a.exec();}
0 0