1. 程式人生 > 實用技巧 >QT5之UDP 通訊

QT5之UDP 通訊

UDP 通訊

UDP通訊的優點

UDP無連線通訊

  • 可以探測附近的裝置
  • 減輕服務端的壓力

UDP步驟

服務端

  1. 定義一個套接字s
  2. 定義檔案描述符
  3. 定義緩衝字串
  4. 申請一個套接字作用在檔案描述符上
    1. 引數一:協議 -> IPv4/IPv6 PF_INET/PF_INET6
    2. 引數二:套接字型別 -> UDP無連線/TCP有連線 SOCK_DGRAM/SOCK_STREAM
    3. 引數三:申請套接字
  5. 重新整理套接字s 為zero
  6. 賦值:
    s.sin_family = AF_INET; //IPV4協議族
    s.sin_port = htons(8888); //埠號
	s.sin_addr.s_addr = INADDR_ANY; //預設地址0x00000000
  1. 繫結埠

    1. 引數一:輸入檔案描述符
    2. 引數二:套接字的地址&s
    3. 引數三:s的大小

    這個套接字有了本地IP,埠,通訊協議

  2. 接收客戶端發來的資訊

    1. 引數一:套接字
    2. 引數二:緩衝字串
    3. 引數三:緩衝字串的大小
    4. 引數四:標誌位設定為0
    5. 引數五:套接字s的地址
    6. 引數六:套接字s的長度的二地址

客戶端

1 ~ 6 的步驟與服務端相同

  1. 對字串幅值
  2. 傳送資料

​ 參考:UDP簡單實戰

原始碼

//服務端:接收
int main()
{
    struct sockaddr_in s;	//定義套接字
    int sock;	//定義檔案表述符
    char buff[182];	//緩衝陣列
    if((sock = socket(AF_INET, SOCK_DGRAM, 0))==-1)
        perror("error");
    memset(&s,0,sizeof(s)); 	//重新整理
    s.sin_family = AF_INEF;
    s.sin_port = htons(8888);
    s.sin_addr.s_addr = INADDR_ANY;
    
    if( bind(sock, (struct sockaddr *)&s, sizeof(s)) == -1 )
        perror("error");
    
    int sock_len = sizeof(s);
    recvfrom( sock, buff, sizeof(buff)-1, 0, (struct sockaddr *)&s, &sock_len);
    printf("message:%s", buff);
    
    return 0;        
}
//客戶端:傳送
int main()
{
    struct sockaddr_in s;	//定義套接字
    int sock;	//定義檔案表述符
    char buff[182];	//緩衝陣列
    if((sock = socket(AF_INET, SOCK_DGRAM, 0))==-1)
        perror("error");
    memset(&s,0,sizeof(s)); 	//重新整理
    s.sin_family = AF_INEF;
    s.sin_port = htons(8888);
    s.sin_addr.s_addr = INADDR_ANY;
    
    scanf("%s", buff);	//對字串進行賦值
    sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&s, sizeof(s));
    
    return 0;
}

總結

UDP通訊需要的因素:

  • 雙方的埠號
  • 對方的IP (自己的IP手動設定)

QT實戰

pro檔案

加入network環境:在core gui後面加入 network

QT += core gui network

mainwindow.cpp

udpsocket=new QUdpSocket(this);  //新建一個套接字socket
/* 繫結本機埠號,允許其他伺服器繫結同樣的IP和埠,即使改地址被另外一個套接字繫結也應該重新繫結 */
udpsocket->bind((quint16)51303, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
connect(udpsocket,SIGNAL(readyRead()),this,SLOT(recvMsg())); // 發起連線
/* 關閉UDP */
udpsocket -> close();
/* 接收資訊 */
void MainWindow::recvMsg(){
    if(udpsocket->hasPendingDatagrams()){
        QByteArray datagram;
        datagram.resize(udpsocket->pendingDatagramSize());
        udpsocket->readDatagram(datagram.data(),datagram.size());
        ui->listWidget->insertItem(0,datagram);
    }
}
QHostAddress addr("192.168.1.100");		//目標地址
QByteArray msg;
msg.append(ui->lineEdit->text());	//傳送資訊內容
udpsocket->writeDatagram(msg,addr,(quint16)51303);	//傳送目標機的地址和埠號

mainwindow.h

加入UDP標頭檔案

#include <QUdpSocket>

公共成員宣告

public:
	QUdpSocket *udpsocket;

增加宣告一個private slots

private slots:
	void recvMsg();

​ 參考:寫個小小的UDP客戶端