日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《UNIX网络编程 卷1:套接字联网API》学习笔记——基本UDP套接字编程

發布時間:2024/8/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《UNIX网络编程 卷1:套接字联网API》学习笔记——基本UDP套接字编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

UNIX網絡編程——基本UDP套接字編程

  • 概述
  • recvfrom 和 sendto函數
  • UDP 回射服務器程序:main 函數
  • UDP 回射服務器程序:dg_echo 函數
  • UDP 回射客戶程序: main 函數
  • UDP 回射客戶程序: dg_cli 函數
  • 數據報的丟失
  • 驗證接收到的響應

概述

UDP是無連接不可靠的數據報協議。
使用UDP編寫的一些常見的應用程序有:DNS(域名系統)、NFS(網絡文件系統)和 SNMP(簡單網絡管理協議)。

recvfrom 和 sendto函數

#include <sys/socket.h> ssize_t recvfrom(int sockfd, void* buff, size_t nbytes, int flags, struct sockaddr* from, socklen_t *addrlen); ssize_t sendto(int sockfd, const void* buff, size_t nbytes, int flags,const struct sockaddr* to, socklen_t addrlen);均返回:若成功則為讀或寫的字節數,若出錯則為-1

前三個參數 sockfd、buff 和 nbytes 等同于 read 和 write 函數的三個參數:描述符、指向讀入或寫成緩沖區的指針和讀寫字節數。

使用sendto、recvfrom發送和接收數據量為0的數據報是允許的。
recvfrom返回0,并不意味著收到對端FIN(sendto,recvfrom使用的場景下沒有連接的概念)。

UDP 回射服務器程序:main 函數

#include "unp.h" int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr, cliaddr;/*創建一個UDP套接字*/sockfd = socket(AF_INET, SOCK_DGRAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT); /*SERV_PORT 服務器的眾所周知端口*/bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr));/*調用函數 dg_echo 來執行服務器的處理工作*/dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr)); }

UDP 回射服務器程序:dg_echo 函數

#include "unp.h" void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen) {int n;socklen_t len;char mesg[MAXLINE];/*該函數是一個簡單的循環,它使用 recvfrom 讀入下一個到達服務器端口的數據報,再使用 sendto 把它發送回發送者*/for ( ; ;){len = clilen;n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);sendto(sockfd, mesg, n, 0, pcliaddr, len);} }

圖中總結了TCP客戶/服務器在兩個客戶與服務器建立連接時情形。
服務器主機上有兩個已連接套接字,其中每一個都有各自的套接字接收緩沖區。

下圖展示了兩個客戶發送數據報到UDP服務器的情形。

UDP 回射客戶程序: main 函數

#include "unp.h" int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: udpcli <IPaddress>");/*把服務器的IP地址和端口號填入一個IPv4的套接字地址結構*/bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);inet_pton(AF_INET, argv[1], &servaddr.sin_addr);/*創建一個UDP套接字,然后調用dg_cli*/sockfd = socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));exit(0); }

UDP 回射客戶程序: dg_cli 函數

#include "unp.h" void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen) {int n;char sendline[MAXLINE], recvline[MAXLINE + 1];/*客戶處理循環中的四個步驟*//*使用 fgets 從標準輸入讀入一個文本行*/while (fgets(sendline, MAXLINE, fp) != NULL){/*使用 sendto 將該文本行發送給服務器*/sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);/*使用 recvfrom 讀回服務器的回射*/n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);recvline[n] = 0; /*null terminate*//*使用 fputs 把回射的文本行顯示到標準輸出*/fputs(recvline, stdout);} }

數據報的丟失

如果一個客戶數據報丟失(如,被客戶主機與服務器主機之間的某個路由器丟棄),客戶將永遠阻塞于 dg_cli 函數中的 recvfrom 調用,等待一個永遠不會到達的服務器應答。

防止這樣永久阻塞的一般方法是給客戶的 recvfrom 調用設置一個超時。

驗證接收到的響應

recvfrom 返回的IP地址(UDP數據報的源IP地址)不是我們所發送數據報的目的IP地址。

保證應答的源地址與請求的目的地址相同的方法:

  • 一個解決辦法是:得到由 recvfrom 返回的IP地址后,客戶通過在DNS中查找服務器主機的名字來驗證該主機的域名(而不是它的IP地址)。
  • 另一個解決辦法是:UDP服務器給服務器主機上配置的每個IP地址創建一個套接字,用bind捆綁每個IP地址到各自的套接字,然后在所有這些套接字上使用 select (等待其中任何一個變得可讀),再從可讀的套接字給出應答。

學習參考資料:

《UNIX網絡編程 卷1:套接字聯網API》 第3版

總結

以上是生活随笔為你收集整理的《UNIX网络编程 卷1:套接字联网API》学习笔记——基本UDP套接字编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。