1. UDP協(xié)議介紹
UDP協(xié)議 相對TCP協(xié)議來講屬于不可靠協(xié)議,UDP協(xié)議是廣播方式發(fā)送數(shù)據(jù),沒有服務(wù)器和客戶端的概念。
在Linux下使用socket創(chuàng)建UDP的套接字時,屬性要選擇數(shù)據(jù)報類型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ù)的長度,負(fù)數(shù)失敗
前三個參數(shù)等同于函數(shù)read()的前三個參數(shù),flags參數(shù)是傳輸控制標(biāo)志。最后兩個參數(shù)類似于accept的最后兩個參數(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ù)的長度,失敗返回-1
前三個參數(shù)等同于函數(shù)read()的前三個參數(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é)議層上存在選項,但本函數(shù)僅定義了最高的“套接口”層次上的選項。選項影響套接口的操作,諸如加急數(shù)據(jù)是否在普通數(shù)據(jù)流中接收,廣播數(shù)據(jù)是否可以從套接口發(fā)送等等。
參數(shù)介紹:
sockfd:標(biāo)識一個套接口的描述字。
level:選項定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。
optname:需設(shè)置的選項。
optval:指針,指向存放選項值的緩沖區(qū)。
optlen:optval緩沖區(qū)的長度。
UDP協(xié)議發(fā)送數(shù)據(jù)時,設(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 <端口號>\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. 綁定端口號*/
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ù)器:端口號綁定失敗.\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ù)才會返回
len=recvfrom(sockfd,buff,sizeof(buff)-1,0,(struct sockaddr*)&from,&addrlen);
buff[len]='\0';
printf("接收到數(shù)據(jù):%s,長度=%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 <端口號> <發(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è)置廣播類型錯誤.\n");
}
/*2. 開始發(fā)送數(shù)據(jù)*/
struct sockaddr_in addr;
addr.sin_family=AF_INET; //IPV4
addr.sin_port=htons(atoi(argv[2])); //65535 服務(wù)器的端口號
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é)議探測在線好友
前面幾篇文章介紹了Linux下TCP協(xié)議設(shè)計的群聊天室的一個程序,如果想要知道同一個網(wǎng)絡(luò)下有多少好友在線,就可以使用UDP協(xié)議進(jìn)行廣播探測。 大家的端口號是固定的,也就是只要在這個網(wǎng)絡(luò)范圍內(nèi),大家都跑這個同一個聊天室程序,就可以互相探測,得到對方IP地址之后,再完成TCP協(xié)議建立,完成點對點聊天通信。
#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 //固定的端口號
?
int sockfd;
int main(int argc,char **argv)
{
if(argc!=2)
{
printf("./app <廣播地址> 當(dāng)前程序固定的端口號是8888\n");
return 0;
}
/*1. 創(chuàng)建socket套接字*/
sockfd=socket(AF_INET,SOCK_DGRAM,0);
//設(shè)置端口號的復(fù)用功能
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
/*2. 綁定端口號與IP地址*/
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT); // 端口號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ù)器:端口號綁定失敗.\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';
//判斷是不是探測包數(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)探測包:%d字節(jié).\n",cnt);
?
//這里可以繼續(xù)寫代碼,將存在的好友保存在鏈表,并記錄在線好友數(shù)量
}
}
else
{
ssize_t cnt;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT); // 端口號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("探測包發(fā)送:%d字節(jié).\n",cnt);
}
}
return 0;
}
審核編輯:湯梓紅
-
Linux
+關(guān)注
關(guān)注
87文章
11499瀏覽量
213346 -
UDP
+關(guān)注
關(guān)注
0文章
330瀏覽量
34585 -
網(wǎng)絡(luò)編碼
+關(guān)注
關(guān)注
0文章
38瀏覽量
11856
發(fā)布評論請先 登錄
UDP網(wǎng)絡(luò)編程

基于UDP協(xié)議的網(wǎng)絡(luò)通信應(yīng)用程序
基于UDP協(xié)議的Socket網(wǎng)絡(luò)編程模式的實現(xiàn)
Linux下的UDP協(xié)議編程
UDP協(xié)議,UDP協(xié)議是什么意思
udp協(xié)議詳細(xì)介紹與qudpsocket編程

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

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

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

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

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

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

評論