UDP服务器客户端编程流程
UDP服務器客戶端編程流程
- UDP編程流程
 - UDP服務端代碼實現
 - UDP客戶端代碼實現
 - UDP服務端客戶端代碼詳解
 
UDP編程流程
UDP提供的是無連接、不可靠的、數據報服務
 
 UDP是盡最大能力進行傳輸,但是并不能保證可靠性,TCP的可靠性是因為一系列的機制保證可靠性,UDP丟包并不會重發,兩種協議并沒有優略之分,要區分不同的場景來區分,比如:進行文件傳輸,不能有數據丟失,TCP協議就更合適,而進行實時視頻通話,UDP會根據恒定的速率進行發送,這樣的情況容許部分數據的丟失去追求更好的實時性,所以UDP更合適
流程:首先服務端與客戶端都需要套接字的創建socket()(UDP并沒有嚴格意義上的服務端與客戶端),然后服務端需要確定ip與端口bind(),等待接收接收數據recvfrom()(會記錄對方的ip和端口),在這里我們并沒有跟某個客戶端進行連接,只是接收發送過來的數據,客戶端發送數據sendto()(需要指定ip與端口),因為UDP并不像TCP建立連接,通過文件描述符來識別客戶端,只能通過發送與接收時識別ip與端口的方式來區分不同的數據,收發結束關閉套接字close()
UDP服務端代碼實現
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<assert.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h>int main() {//創建套接字//參數://AF_INET ipv4//SOCK_DGRAM UDP使用的數據報服務類型 (SOCK_STREAM 流式套接字TCP使用的服務類型//標志位 一般給 0int sockfd = socket(AF_INET,SOCK_DGRAM,0);assert(sockfd != -1);//創建套接字地址結構struct sockaddr_in saddr,caddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//命名套接字int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1);while(1){int len = sizeof(caddr);//這里專門存放在len中,是因為在recvfrom的時候接收一個指針char buff[128] = {0};//接受數據//參數://服務端套接字//存放數據//存放大小//標志位 一般給0//存放客戶端地址信息(ip與端口)//caddr的大小recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);printf("buff=%s\n",buff);//發送數據//參數://服務端套接字//發送的數據//發送數據大小//標志位 一般給0//發送目標的地址信息//地址信息的大小sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));}//關閉套接字close(sockfd); }UDP客戶端代碼實現
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<assert.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h>int main() {int sockfd = socket(AF_INET,SOCK_DGRAM,0);assert(sockfd != -1);//只需要指定服務器的ip與端口,客戶端自己的ip與端口由系統自動指定struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");while(1){char buff[128] = {0};printf("input:\n");fgets(buff,128,stdin);if(strncmp(buff,"end",3) == 0){break;}sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));memset(buff,0,128);int len = sizeof(saddr);recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);//占用了saddr存放獲取對方的ip與端口,實際上并沒有改變都是一樣的printf("buff=%s\n",buff);}close(sockfd); }UDP服務端客戶端代碼詳解
執行服務端與客戶端的代碼
 
 當我們打開多個窗口,啟動多個客戶端向服務端發送數據
 
 UDP服務端的接收只是根據是否有數據發送過來,只要有發送過來的數據就進行接收,并不進行連接,即使將服務端關閉重新開啟,使用原本的客戶端依舊可以進行發送數據,因為他們本身之間并不存在相互的連接
 
 假如將,服務端進行關閉不重啟,客戶端發送依舊發送出去sendto()不阻塞,但是會阻塞在recvfrom()這一步,簡單的說就是服務器只管接收數據或者向發送方發送數據,無論是誰都可以向其發送數據且無需任何連接
如果我們將服務端代碼進行修改
 
 我們再通過客戶端向服務端發送數據
 
 使用UDP協議的時候,當數據傳輸過來我們將數據包拆開只讀取設定大小的數據,其余就會丟掉,繼而丟失
 
 每次發送都是一個獨立的數據包,因為每次的發送可能目的地址都不相同,對于TCP是可以將多次的數據合并進行發送的,因為在同一描述符同一連接內發送對象只有連接的另一方
總結
以上是生活随笔為你收集整理的UDP服务器客户端编程流程的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Ranked List Loss for
 - 下一篇: 【附源码】计算机毕业设计java智慧灭火