您好,登錄后才能下訂單哦!
一、UDP協議
UDP協議的特點:用戶數據包協議
1、UDP協議是無連接的。也就說在數據發送之前并不需要建立連接(當然,在發送數據結束的時候也就不存在鏈接的釋放),因此減少了開銷和數據發送之前的時延。
2、UDP使用盡最大努力的交付,但是不保證可靠性的交付,因此主機不需要維持復雜的鏈接狀態表。(網上的的可靠性建立在應答的基礎上,不提供可靠×××付,即不需要應答,因此不需要維護狀態表)
3、UDP是面向報文。發送方的UDP對于應用程序進程交下來的報文,即不合并,也不拆分,而是保留這些報文的邊界。這也就是說,應用層交付給UDP多長的報文,UDP就照樣發送,即一次發送一個報文。同時,在接收方,對于IP層交上來的UDP用戶數據報,在去除首部后就原封不動的交付給應用層的應用進程了。也就說,UDP一次交付一個完整的報文。因此報文的大小必須合適,負責會降低數據的傳輸效率。如果報文太長,在IP層需要對報文分片,就會降低IP層的效率。反之,若報文太短,UDP把它交給IP層后,會使得IP數據報的首部相對過長,同樣會降低IP層的效率。
4、UDP沒有擁塞控制
二、基于UDP的socket編程的一般流程
1.server端
a.獲取有效的IP地址與端口號(port)(服務器端需要約定好的端口號與IP,方便客戶直接與該IP下的該端口建立連接)
b.將IP與port轉為網絡通用格式
c.聲明監聽文件描述符 (int listen_sock),將該文件描述符”注冊“為
套接字文件(listen_sock=socket(AF_INET,SOCK_DGRAM,0))
參數:
AF_INET:IPv4套接字類型(說明地址類型格式)
SOCK_DGRAM:UDP協議類型(提供無連接的盡力交付)
0:表示該套接字只支持一種協議
d.給listen_sock綁定相應的信息( IP,port),因為socket套接字是由內核接管處理的,因此我們無法直接操作,寫入信息需要以下操作:
1>聲明struct sockaddr_in 結構體,將對因信息賦值給結構體對應單元
local.sin_family=AF_INET;
local.sin_port=htons(port);
local.sin_addr.s_addr=ip;
2>調用bind(int sockfd,struct sockaddr* addr,socklen_t addrlen)函數,將ip,port信息寫入(即綁定)套接字的
f.使用recvfrom()接收數據。
server端代碼實例:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> void usage(char* arg) { printf("Missing Parameters: %s [remote ip :] [remote port :]",arg); } int main(int argc,char* argv[]) { if(argc!=3){ usage(argv[0]); exit(1); } in_addr_t _ip=inet_addr(argv[1]); int _port=atoi(argv[2]); int sock=socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in server; socklen_t len=sizeof(server); server.sin_family=AF_INET; server.sin_port=_port; server.sin_addr.s_addr=_ip; if(bind(sock,(struct sockaddr*)&server,len)<0){ perror("bind"); exit(2); } char buf[1024]; while(1){ ssize_t size=recvfrom( sock,buf, 1023,0,\ (struct sockaddr *)&server, &len); if(size<0){ perror("read"); break; }else if(size==0){ printf("server %d close: ip: %s !\n",sock,inet_ntoa(server.sin_addr)); } else{ printf("get a connect %d... ip:%s,port:%d\n",sock\ ,inet_ntoa(server.sin_addr),ntohs(server.sin_port)); buf[size]=0; printf("server# %s\n",buf); } } return 0; }
2.client端
a.獲取有效的IP地址與端口號(port)(此處為需要發送的目標服務器的ip,與廣知的port)
b.將IP與port轉為網絡通用格式
c.聲明文件描述符 (int _sock),將該文件描述符”注冊“為
套接字文件(_sock=socket(AF_INET,SOCK_DGRAM,0))
d.聲明struct sockaddr_in _server結構體,connect()將目標服務器ip與port寫入使用,并與_sock綁定,同時與目標服務器建立連接。
e.使用sendto()向目標發送UDP報文。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> void usage(char* arg) { printf("Missing Parameters: %s [remote ip :] [remote port :]",arg); } int main(int argc,char* argv[]) { if(argc!=3){ usage(argv[0]); exit(1); } in_addr_t _ip=inet_addr(argv[1]); int _port=atoi(argv[2]); int sock=socket(AF_INET,SOCK_DGRAM,0); if(sock<-1){ perror("socket"); exit(2); } struct sockaddr_in server; socklen_t len=sizeof(server); server.sin_family=AF_INET; server.sin_port=_port; server.sin_addr.s_addr=_ip; if( connect( sock, (struct sockaddr *)&server, len)<0){ perror("connect"); exit(3); } char buf[1024]; while(1){ printf("please Enter:"); gets(buf); if(strcmp(buf,"quit")==0){ sendto(sock, buf,0,0 ,(struct sockaddr *)&server, len); break; } sendto(sock, buf,strlen(buf),0 ,(struct sockaddr *)&server, len); } close(sock); return 0; }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。