亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Linux下使用C/C++進行UDP網(wǎng)絡(luò)編程詳解

 更新時間:2024年10月30日 09:48:54   作者:袁本美  
UDP 是User Datagram Protocol 的簡稱,中文名是用戶數(shù)據(jù)報協(xié)議,是一種無連接、不可靠的協(xié)議,本文主要介紹了如何在Linux下使用C/C++進行UDP網(wǎng)絡(luò)編程,有需要的可以了解下

UDP 是User Datagram Protocol 的簡稱,中文名是用戶數(shù)據(jù)報協(xié)議,是一種無連接、不可靠的協(xié)議,同樣它也是工作在傳順層。它只是簡單地實現(xiàn)從一端主機到另一端主機的數(shù)據(jù)傳輸功能,這些數(shù)據(jù)通過 IP 層發(fā)送,在網(wǎng)絡(luò)中傳輸,到達目標主機的順序是無法預知的,因此需要應(yīng)用程序?qū)@些數(shù)據(jù)進行排序處理,這就帶來了很大的不方便,此外,UDP 協(xié)議更沒有流量控制、擁塞控制等功能,在發(fā)送的一端,UDP 只是把上層應(yīng)用的數(shù)據(jù)封裝到UDP 報文中,在差錯檢測方面,僅僅是對數(shù)據(jù)進行了簡單的校驗,然后將其封裝到 IP 數(shù)據(jù)報中發(fā)送出去。而在接收端,無論是否收到數(shù)據(jù),它都不會產(chǎn)生一個應(yīng)答發(fā)送給源主機,并且如果接收到數(shù)據(jù)發(fā)送校驗錯誤,那么接收端就會丟棄該UDP 報文,也不會告訴源主機,這樣子傳輸?shù)臄?shù)據(jù)是無法保障其準確性的,如果想要其準確性,那么就需要應(yīng)用程序來保障了。

UDP 協(xié)議的特點:

  • 無連接、不可靠;
  • 盡可能提供交付數(shù)據(jù)服務(wù),出現(xiàn)差錯直接丟棄,無反饋;
  • 面向報文,發(fā)送方的UDP 拿到上層數(shù)據(jù)直接添加個UDP 首部,然后進行校驗后就遞交給 IP 層而接收的一方在接收到UDP 報文后簡單進行校驗,然后直接去除數(shù)據(jù)遞交給上層應(yīng)用;
  • 速度快,因為UDP 協(xié)議沒有TCP 協(xié)議的握手、確認、窗口、重傳、擁塞控制等機制,UDP 是一個無狀態(tài)的傳輸協(xié)議,所以它在傳遞數(shù)據(jù)時非???,即使在網(wǎng)絡(luò)擁塞的時候UDP 也不會降低發(fā)送的數(shù)據(jù)。 UDP 雖然有很多缺點,但也有自己的優(yōu)點,所以它也有很多的應(yīng)用場合,因為在如今的網(wǎng)絡(luò)環(huán)境下, UDP 協(xié)議傳輸出現(xiàn)錯誤的概率是很小的,并且它的實時性是非常好,常用于實時視頻的傳輸,比如直播、網(wǎng)絡(luò)電話等,因為即使是出現(xiàn)了數(shù)據(jù)丟失的情況,導致視頻卡幀,這也不是什么大不了的事情,所以,UDP協(xié)議還是會被應(yīng)用與對傳輸速度有要求,并且可以容忍出現(xiàn)差錯的數(shù)據(jù)傳輸中。

在Linux使用socket網(wǎng)絡(luò)編程實現(xiàn)udp通信流程如下:

1.  初始化socket

int sock_fd = socket(AF_INET , SOCK_DGRAM , 0); 
if(sock_fd < 0){
    perror("failed to open socket");
    return -1;
}

2.  綁定IP和端口號

/** 綁定IP和端口號 */ 
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // 本地任意IP
server_addr.sin_port = htons(8888);       // 指定端口號
int ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(ret < 0)
{
    perror("failed to bind");
    close(sock_fd);
    return -1;
}

3. 設(shè)置組播接收(可選)

std::string multi_addr = "224.0.0.10";
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(multi_addr.c_str());
mreq.imr_interface.s_addr = INADDR_ANY;
ret = setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq));
if (0 >ret)
{
    perror("set socket multicast error");
    return false;
}

4. 設(shè)置接收超時(可選)

/** 設(shè)置接收超時(可選) */
int mill_sec = 2000;  // 毫秒
struct timeval time_out;
time_out.tv_sec = mill_sec / 1000;
time_out.tv_usec = (mill_sec- time_out.tv_sec * 1000) * 1000;
ret = setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,&time_out,sizeof (timeval));
if(ret < 0)
{
    perror("udp setTimeOut error!");
}

5.  發(fā)送數(shù)據(jù)

unsigned char buf[1024];
std::string ip = "192.168.1.10";
int port = 1234;
struct sockaddr_in client{};
memset(&client, 0, sizeof(client));
client.sin_addr.s_addr = inet_addr(ip.c_str());
client.sin_family = AF_INET;
client.sin_port = htons(port);
ret = sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&client), sizeof(struct sockaddr));
if(ret < 0){
    perror("udpServer send error!");
}else{
    std::cout << "send success!" << std::endl;
}

6. 接收數(shù)據(jù)

unsigned char buffer[1024];
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
while(true)
{
    memset(buffer, 0, sizeof(buffer));
    ssize_t len = recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&addr), &addr_len);
    if(len > 0)
    {
        std::cout << "received message len : " << len << std::endl;
    }else{
        perror("recv error");
    }
}

7. 完整代碼

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netdb.h>
#include <net/if.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <thread>
 
void recv_func(int sock_fd_)
{
unsigned char buffer[1024];
struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
while(true)
{
    memset(buffer, 0, sizeof(buffer));
    ssize_t len = recvfrom(sock_fd_, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&addr), &addr_len);
    if(len > 0)
    {
        std::cout << "received message len : " << len << std::endl;
    }else{
        perror("recv error");
    }
}
}
 
int main(int agrc, char** argv)
{
    int sock_fd = socket(AF_INET , SOCK_DGRAM , 0); 
    if(sock_fd < 0){
        perror("failed to open socket");
        return -1;
    }
 
    /** 綁定IP和端口號 */ 
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 本地任意IP
    server_addr.sin_port = htons(8888);       // 指定端口號
    int ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(ret < 0)
    {
        perror("failed to bind");
        close(sock_fd);
        return -1;
    }
 
    /** 設(shè)置組播接收 (可選)*/
std::string multi_addr = "224.0.0.10";
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(multi_addr.c_str());
mreq.imr_interface.s_addr = INADDR_ANY;
ret = setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq));
if (0 >ret)
{
    perror("set socket multicast error");
    return false;
}
 
/** 設(shè)置接收超時(可選) */
int mill_sec = 2000;  // 毫秒
struct timeval time_out;
time_out.tv_sec = mill_sec / 1000;
time_out.tv_usec = (mill_sec- time_out.tv_sec * 1000) * 1000;
ret = setsockopt(sock_fd, SOL_SOCKET,SO_RCVTIMEO,&time_out,sizeof (timeval));
if(ret < 0)
{
    perror("udp setTimeOut error!");
}
 
 
    /** 開啟線程接收 */
    std::thread recv_t(recv_func, sock_fd);
    recv_t.detach();
 
    /** 主線程發(fā)送 */
    while (true)
    {
unsigned char buf[1024];
std::string ip = "192.168.1.10";
int port = 1234;
struct sockaddr_in client{};
memset(&client, 0, sizeof(client));
client.sin_addr.s_addr = inet_addr(ip.c_str());
client.sin_family = AF_INET;
client.sin_port = htons(port);
ret = sendto(sock_fd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&client), sizeof(struct sockaddr));
if(ret < 0){
    perror("udpServer send error!");
}else{
    std::cout << "send success!" << std::endl;
}
        
        usleep(50*1000);
    }
}

8. 編譯運行

# 編譯
g++ udp_main.cpp -o main -lpthread
# 運行
./main

以上就是Linux下使用C/C++進行UDP網(wǎng)絡(luò)編程詳解的詳細內(nèi)容,更多關(guān)于C++ UDP網(wǎng)絡(luò)編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • json error: Use of overloaded operator [] is ambiguous錯誤的解決方法

    json error: Use of overloaded operator [] is ambiguous錯誤的解決方

    今天小編就為大家分享一篇關(guān)于json error: Use of overloaded operator [] is ambiguous錯誤的解決方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • win10環(huán)境下C++ vs2015編譯opencv249的教程

    win10環(huán)境下C++ vs2015編譯opencv249的教程

    這篇文章主要介紹了win10環(huán)境下C++ vs2015編譯opencv249的教程,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • 函數(shù)外初始化與函數(shù)內(nèi)初始化詳細解析

    函數(shù)外初始化與函數(shù)內(nèi)初始化詳細解析

    函數(shù)內(nèi)初始化:bool FillStr(char *&szDst, int nSize);第一個參數(shù)中的&一定不能少,這是因為在函數(shù)外部我們只聲明了這個指針,具體這個指針指向內(nèi)存中的哪個地址我們并不知道,所以&是為了說明傳遞的是這個指針的引用,那么在函數(shù)內(nèi)初始化后這個指針的地址也就是外面指針的地址了
    2013-09-09
  • 二叉樹先根(先序)遍歷的改進

    二叉樹先根(先序)遍歷的改進

    這篇文章主要介紹了二叉樹先根(先序)遍歷的改進,有需要的朋友可以參考一下
    2014-01-01
  • 解析C語言中空指針、空指針常量、NULL & 0的詳解

    解析C語言中空指針、空指針常量、NULL & 0的詳解

    本篇文章是對C語言中空指針、空指針常量、NULL & 0 進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中多態(tài)的定義及實現(xiàn)詳解

    C++中多態(tài)的定義及實現(xiàn)詳解

    這篇文章主要給大家介紹了關(guān)于C++中多態(tài)的定義及實現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-05-05
  • 詳解C++異常處理(try catch throw)完全攻略

    詳解C++異常處理(try catch throw)完全攻略

    這篇文章主要介紹了詳解C++異常處理(try catch throw)完全攻略,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • C語言雙指針多方法旋轉(zhuǎn)數(shù)組解題LeetCode

    C語言雙指針多方法旋轉(zhuǎn)數(shù)組解題LeetCode

    這篇文章主要為大家介紹了C語言雙指針使用多方法旋轉(zhuǎn)數(shù)組題解LeetCode,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-02-02
  • C語言連接并操作Sedna XML數(shù)據(jù)庫的方法

    C語言連接并操作Sedna XML數(shù)據(jù)庫的方法

    這篇文章主要介紹了C語言連接并操作Sedna XML數(shù)據(jù)庫的方法,實例分析了C語言操作XML文件的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • 實例講解C++ 命名空間

    實例講解C++ 命名空間

    這篇文章主要介紹了C++ 命名空間的的相關(guān)資料,文中示例代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06

最新評論