0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux下網(wǎng)絡(luò)編程-UDP協(xié)議探測(cè)在線好友

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 09:23 ? 次閱讀

1. UDP協(xié)議介紹

UDP協(xié)議 相對(duì)TCP協(xié)議來講屬于不可靠協(xié)議,UDP協(xié)議是廣播方式發(fā)送數(shù)據(jù),沒有服務(wù)器和客戶端的概念。

Linux下使用socket創(chuàng)建UDP的套接字時(shí),屬性要選擇數(shù)據(jù)報(bào)類型SOCK_DGRAM。

 sockfd=socket(AF_INET,SOCK_DGRAM,0);
復(fù)制代碼

2. UDP協(xié)議發(fā)送和接收數(shù)據(jù)的函數(shù)

2.1 recvfrom函數(shù)

UDP使用recvfrom()函數(shù)接收數(shù)據(jù),他類似于標(biāo)準(zhǔn)的read(),但是在recvfrom()函數(shù)中要指明數(shù)據(jù)的目的地址。

#include  
#include  
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * from, size_t *addrlen);
復(fù)制代碼

返回值

成功返回接收到數(shù)據(jù)的長(zhǎng)度,負(fù)數(shù)失敗

前三個(gè)參數(shù)等同于函數(shù)read()的前三個(gè)參數(shù),flags參數(shù)是傳輸控制標(biāo)志。最后兩個(gè)參數(shù)類似于accept的最后兩個(gè)參數(shù)(接收客戶端的IP地址)。

2.2 sendto函數(shù)

UDP使用sendto()函數(shù)發(fā)送數(shù)據(jù),他類似于標(biāo)準(zhǔn)的write(),但是在sendto()函數(shù)中要指明目的地址。

#include  
#include  
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr * to, int addrlen);
復(fù)制代碼

返回值

成功返回發(fā)送數(shù)據(jù)的長(zhǎng)度,失敗返回-1

前三個(gè)參數(shù)等同于函數(shù)read()的前三個(gè)參數(shù),flags參數(shù)是傳輸控制標(biāo)志。

參數(shù)to指明數(shù)據(jù)將發(fā)往的協(xié)議地址,他的大小由addrlen參數(shù)來指定。

2.3 設(shè)置套接字屬性

#include      /* See NOTES */
#include 
int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
復(fù)制代碼

setsockopt()函數(shù)用于任意類型、任意狀態(tài)套接口的設(shè)置選項(xiàng)值。盡管在不同協(xié)議層上存在選項(xiàng),但本函數(shù)僅定義了最高的“套接口”層次上的選項(xiàng)。選項(xiàng)影響套接口的操作,諸如加急數(shù)據(jù)是否在普通數(shù)據(jù)流中接收,廣播數(shù)據(jù)是否可以從套接口發(fā)送等等。

參數(shù)介紹:

sockfd:標(biāo)識(shí)一個(gè)套接口的描述字。
level:選項(xiàng)定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。
optname:需設(shè)置的選項(xiàng)。
optval:指針,指向存放選項(xiàng)值的緩沖區(qū)。
optlen:optval緩沖區(qū)的長(zhǎng)度。
UDP協(xié)議發(fā)送數(shù)據(jù)時(shí),設(shè)置具有廣播特性: 默認(rèn)情況下socket不支持廣播特性
char bBroadcast=1;
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(char));
復(fù)制代碼

3.案例: UDP協(xié)議完成數(shù)據(jù)收發(fā)

3.1 接收數(shù)據(jù)示例

#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/* According to POSIX.1-2001 */
#include 

int main(int argc,char **argv)
{
    if(argc!=2)
    {
        printf("參數(shù): ./tcp_server <端口號(hào)>\n");
        return 0;
    }

     /*1. 創(chuàng)建socket套接字*/
    int sockfd;
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        printf("服務(wù)器:套接字創(chuàng)建失敗.\n");
        return 0;
    }
    /*2. 綁定端口號(hào)*/
    struct sockaddr_in addr;
    addr.sin_family=AF_INET; //IPV4
    addr.sin_port=htons(atoi(argv[1])); //65535
    //addr.sin_addr.s_addr=inet_addr("192.168.2.16");
    addr.sin_addr.s_addr=INADDR_ANY; //本地所有IP地址 "0.0.0.0"
    if(bind(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr)))
    {
        printf("服務(wù)器:端口號(hào)綁定失敗.\n");
        return 0;
    }
    /*3. 接收數(shù)據(jù)*/
    char buff[100];
    struct sockaddr_in from;
    size_t addrlen=sizeof(struct sockaddr);
    ssize_t len;
    while(1)
    {
        //帶阻塞功能,收到數(shù)據(jù)才會(huì)返回
        len=recvfrom(sockfd,buff,sizeof(buff)-1,0,(struct sockaddr*)&from,&addrlen);
        buff[len]='\0';
        printf("接收到數(shù)據(jù):%s,長(zhǎng)度=%d,數(shù)據(jù)來自于:%s:%d\n",buff,len,inet_ntoa(from.sin_addr),ntohs(from.sin_port));
    }
}
復(fù)制代碼

3.2 發(fā)送數(shù)據(jù)示例

#include 
#include           /* See NOTES */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/* According to POSIX.1-2001 */
#include 
#include 

int main(int argc,char **argv)
{
     if(argc!=4)
    {
        printf("參數(shù): ./tcp_client  <端口號(hào)> <發(fā)送的數(shù)據(jù)>\n");
        return 0;
    }

    /*1. 創(chuàng)建socket套接字*/
    int sockfd;
    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    if(sockfd<0)
    {
        printf("服務(wù)器:套接字創(chuàng)建失敗.\n");
        return 0;
    }

    const int opt = 1;
    //設(shè)置該套接字為廣播類型,
    int nb = 0;
    nb = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
    if(nb == -1)
    {
        printf("設(shè)置廣播類型錯(cuò)誤.\n");
    }

    /*2. 開始發(fā)送數(shù)據(jù)*/
    struct sockaddr_in addr;
    addr.sin_family=AF_INET; //IPV4
    addr.sin_port=htons(atoi(argv[2])); //65535  服務(wù)器的端口號(hào)
    addr.sin_addr.s_addr=inet_addr(argv[1]); //服務(wù)器IP地址

    ssize_t len;
    while(1)
    {
        len=sendto(sockfd,argv[3],strlen(argv[3]),0,(const struct sockaddr*)&addr,sizeof(struct sockaddr));
        printf("成功發(fā)送:%d\n",len);
        sleep(1);
    }
}
復(fù)制代碼地址>

4. 案例: 使用UDP協(xié)議探測(cè)在線好友

前面幾篇文章介紹了Linux下TCP協(xié)議設(shè)計(jì)的群聊天室的一個(gè)程序,如果想要知道同一個(gè)網(wǎng)絡(luò)下有多少好友在線,就可以使用UDP協(xié)議進(jìn)行廣播探測(cè)。 大家的端口號(hào)是固定的,也就是只要在這個(gè)網(wǎng)絡(luò)范圍內(nèi),大家都跑這個(gè)同一個(gè)聊天室程序,就可以互相探測(cè),得到對(duì)方IP地址之后,再完成TCP協(xié)議建立,完成點(diǎn)對(duì)點(diǎn)聊天通信。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
?
?
#define SEND_MSG "1314520"  //發(fā)送的數(shù)據(jù)包
#define PORT 8888      //固定的端口號(hào)
?
int sockfd;
int main(int argc,char **argv)
{  
  if(argc!=2)
   {
    printf("./app <廣播地址>  當(dāng)前程序固定的端口號(hào)是8888\n");
    return 0;
   }

  /*1. 創(chuàng)建socket套接字*/
  sockfd=socket(AF_INET,SOCK_DGRAM,0);

  //設(shè)置端口號(hào)的復(fù)用功能
  int on = 1;
  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

  /*2. 綁定端口號(hào)與IP地址*/
  struct sockaddr_in addr;
  addr.sin_family=AF_INET;
  addr.sin_port=htons(PORT); // 端口號(hào)0~65535
  addr.sin_addr.s_addr=INADDR_ANY;  //inet_addr("0.0.0.0"); //IP地址
  if(bind(sockfd,(const struct sockaddr *)&addr,sizeof(struct sockaddr))!=0)
   {
    printf("UDP服務(wù)器:端口號(hào)綁定失敗.\n");
    return 0;
   }
  /*3. 接收數(shù)據(jù)*/
  unsigned char buff[1024+1];
  int cnt;
  struct sockaddr_in client_addr;
  socklen_t addrlen=sizeof(struct sockaddr_in);

  struct pollfd fds;
  fds.fd=sockfd;
  fds.events=POLLIN;
  while(1)
   {
    cnt=poll(&fds,1,1000);
    if(cnt>0)
     {
      cnt=recvfrom(sockfd,buff,1024,0,(struct sockaddr *)&client_addr,&addrlen);
      buff[cnt]='\0';
      
      //判斷是不是探測(cè)包數(shù)據(jù)
      if(strcmp(buff,SEND_MSG)==0)
       {
        printf("在線好友:%s,%d-->%s:%d\n",buff,cnt,inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
        cnt=sendto(sockfd,SEND_MSG,strlen(SEND_MSG),0,(const struct sockaddr *)&client_addr,sizeof(struct sockaddr));
        printf("回應(yīng)探測(cè)包:%d字節(jié).\n",cnt);
?
        //這里可以繼續(xù)寫代碼,將存在的好友保存在鏈表,并記錄在線好友數(shù)量
       }
     }
    else
     {
      ssize_t cnt;
      struct sockaddr_in addr;
      addr.sin_family=AF_INET;
      addr.sin_port=htons(PORT); // 端口號(hào)0~65535
      addr.sin_addr.s_addr=inet_addr(argv[1]); //IP地址
?
      cnt=sendto(sockfd,SEND_MSG,strlen(SEND_MSG),0,(const struct sockaddr *)&addr,sizeof(struct sockaddr));
      printf("探測(cè)包發(fā)送:%d字節(jié).\n",cnt);
     }
   }
  return 0;
}

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11207

    瀏覽量

    208721
  • UDP
    UDP
    +關(guān)注

    關(guān)注

    0

    文章

    322

    瀏覽量

    33849
  • 網(wǎng)絡(luò)編碼
    +關(guān)注

    關(guān)注

    0

    文章

    38

    瀏覽量

    11576
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    UDP網(wǎng)絡(luò)編程

    UDP 是User Datagram Protocol的簡(jiǎn)稱, 中文名是用戶數(shù)據(jù)報(bào)協(xié)議,是OSI(Open System Interconnection,開放式系統(tǒng)互聯(lián)) 參考模型中一種無連接的傳輸
    的頭像 發(fā)表于 08-26 20:58 ?1379次閱讀
    <b class='flag-5'>UDP</b><b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>編程</b>

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)前兩篇文章介紹了基于TCP/IP協(xié)議網(wǎng)絡(luò)
    發(fā)表于 11-05 08:29

    基于UDP協(xié)議的Socket網(wǎng)絡(luò)編程模式的實(shí)現(xiàn)

    傳輸層進(jìn)行網(wǎng)絡(luò)通信編程的接口是Socket&它是通用的開發(fā)網(wǎng)絡(luò)通信程序標(biāo)準(zhǔn)) 本文介紹了基于UDP協(xié)議Socket
    發(fā)表于 09-09 15:10 ?42次下載

    Linux下的UDP協(xié)議編程

    Linux下的UDP協(xié)議編程 介紹UDP協(xié)議,并提供一個(gè)適用于客戶端和服務(wù)器端的實(shí)例子程序。 
    發(fā)表于 10-16 22:22 ?3948次閱讀
    <b class='flag-5'>Linux</b>下的<b class='flag-5'>UDP</b><b class='flag-5'>協(xié)議</b><b class='flag-5'>編程</b>

    UDP協(xié)議,UDP協(xié)議是什么意思

    UDP協(xié)議,UDP協(xié)議是什么意思 UDP 是User Datagram Protocol的簡(jiǎn)稱, 中文名是用戶數(shù)據(jù)包
    發(fā)表于 03-29 17:35 ?1483次閱讀

    linux下網(wǎng)卡配置詳解

    linux下網(wǎng)卡配置詳解
    發(fā)表于 12-15 22:38 ?0次下載

    udp協(xié)議詳細(xì)介紹與qudpsocket編程

    關(guān)于udp協(xié)議詳細(xì)介紹與qudpsocket編程,UDP報(bào)頭由4個(gè)域組成,其中每個(gè)域各占用2個(gè)字節(jié),具體如下: 端口號(hào) ,目標(biāo)端口號(hào) ,數(shù)據(jù)報(bào)長(zhǎng)度 ,校驗(yàn)值
    發(fā)表于 12-08 14:57 ?9154次閱讀
    <b class='flag-5'>udp</b><b class='flag-5'>協(xié)議</b>詳細(xì)介紹與qudpsocket<b class='flag-5'>編程</b>

    Linux下網(wǎng)絡(luò)怎樣來配置總結(jié)

    Linux下網(wǎng)絡(luò)配置總結(jié)
    發(fā)表于 11-07 11:35 ?876次閱讀

    Linux下網(wǎng)絡(luò)編程TCP并發(fā)服務(wù)器和TCP客戶端程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是Linux下網(wǎng)絡(luò)編程TCP并發(fā)服務(wù)器和TCP客戶端程序免費(fèi)下載
    發(fā)表于 01-08 15:12 ?9次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>下網(wǎng)絡(luò)</b><b class='flag-5'>編程</b>TCP并發(fā)服務(wù)器和TCP客戶端程序免費(fèi)下載

    tcp和udp協(xié)議的異同

    。UDP 校驗(yàn)和則是包含 UDP 首部和數(shù)據(jù)在內(nèi)的校驗(yàn)結(jié)果。 TCP協(xié)議 TCP協(xié)議基于網(wǎng)絡(luò)層的 IP
    的頭像 發(fā)表于 11-12 14:45 ?3986次閱讀
    tcp和<b class='flag-5'>udp</b><b class='flag-5'>協(xié)議</b>的異同

    嵌入式Linux應(yīng)用程序開發(fā)-(9)UDP網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)前兩篇文章介紹了基于TCP/IP協(xié)議網(wǎng)絡(luò)
    發(fā)表于 11-02 12:21 ?35次下載
    嵌入式<b class='flag-5'>Linux</b>應(yīng)用程序開發(fā)-(9)<b class='flag-5'>UDP</b><b class='flag-5'>網(wǎng)絡(luò)</b>通信應(yīng)用程序(<b class='flag-5'>UDP</b>-Socket)

    Linux應(yīng)用開發(fā)【第六章】網(wǎng)絡(luò)編程應(yīng)用開發(fā)

    文章目錄 6 網(wǎng)絡(luò)編程應(yīng)用開發(fā) 6.1 網(wǎng)絡(luò)編程簡(jiǎn)介 6.1.1 五層因特網(wǎng)協(xié)議棧 6.1.2 傳輸層和應(yīng)用層的常見
    的頭像 發(fā)表于 12-10 19:17 ?509次閱讀
    <b class='flag-5'>Linux</b>應(yīng)用開發(fā)【第六章】<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>編程</b>應(yīng)用開發(fā)

    Linux編程UDP SOCKET攻略詳解

    一、基本的udp socket編程 1. UDP編程框架 要使用UDP協(xié)議進(jìn)行程序開發(fā),我們必須
    的頭像 發(fā)表于 05-21 16:23 ?2141次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>編程</b>之<b class='flag-5'>UDP</b> SOCKET攻略詳解

    Linux下網(wǎng)絡(luò)編程

    TCP/IP協(xié)議源于1969年,是針對(duì)Internet開發(fā)的一種體系結(jié)構(gòu)和協(xié)議標(biāo)準(zhǔn),目的在于解決異種計(jì)算機(jī)網(wǎng)絡(luò)的通信問題。使得網(wǎng)絡(luò)在互聯(lián)時(shí)能為用戶提供一種通用、一致的通信服務(wù)。是Int
    的頭像 發(fā)表于 08-26 20:53 ?1102次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>下網(wǎng)絡(luò)</b><b class='flag-5'>編程</b>

    Linux開發(fā)_網(wǎng)絡(luò)編程網(wǎng)絡(luò)通信介紹

    介紹Linux網(wǎng)絡(luò)編程: TCP網(wǎng)絡(luò)編程、UDP網(wǎng)絡(luò)
    的頭像 發(fā)表于 09-17 15:46 ?1243次閱讀
    <b class='flag-5'>Linux</b>開發(fā)_<b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>編程</b>、<b class='flag-5'>網(wǎng)絡(luò)</b>通信介紹