偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

技術(shù)分析:基本 UDP 套接字編程

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
UDP 協(xié)議和 TCP 協(xié)議不同,它是一種面向無(wú)連接、不可靠的傳輸層協(xié)議。在基于 UDP 套接字編程中,數(shù)據(jù)傳輸可用函數(shù) sendto 和 recvfrom。

[[124415]]

UDP 協(xié)議和 TCP 協(xié)議不同,它是一種面向無(wú)連接、不可靠的傳輸層協(xié)議。在基于 UDP 套接字編程中,數(shù)據(jù)傳輸可用函數(shù) sendto 和 recvfrom。以下是基本 UDP 套接字編程過(guò)程:

 

 

sendto 與 recvfrom 函數(shù)

這兩個(gè)函數(shù)的功能類似于 write 和 read 函數(shù),可用無(wú)連接的套接字編程。其定義如下:

  1. /* 函數(shù)功能:發(fā)送數(shù)據(jù);  
  2.  * 返回值:若成功則返回已發(fā)送的字節(jié)數(shù),若出錯(cuò)則返回-1;  
  3.  * 函數(shù)原型:  
  4.  */   
  5. #include <sys/socket.h>   
  6.    
  7. ssize_t sendto(int sockfd, void *buff, size_t nbytes, int flags,   
  8.                 const struct sockaddr *destaddr, socklen_t addrlen);   
  9.    
  10. /* 說(shuō)明:  
  11.  * 該函數(shù)功能類似于write函數(shù),除了有標(biāo)識(shí)符flags和目的地址信息之外,其他參數(shù)一樣;  
  12.  *  
  13.  * flags標(biāo)識(shí)符取值如下:  
  14.  * (1)MSG_DONTROUTE   勿將數(shù)據(jù)路由出本地網(wǎng)絡(luò)  
  15.  * (2)MSG_DONTWAIT    允許非阻塞操作  
  16.  * (3)MSG_EOR         如果協(xié)議支持,此為記錄結(jié)束  
  17.  * (4)MSG_OOB         如果協(xié)議支持,發(fā)送帶外數(shù)據(jù)  
  18.  *  
  19.  * 若sendto成功,則只是表示已將數(shù)據(jù)無(wú)錯(cuò)誤的發(fā)送到網(wǎng)絡(luò),并不能保證正確到達(dá)對(duì)端;  
  20.  * 該函數(shù)通過(guò)指定目標(biāo)地址允許在無(wú)連接的套接字之間發(fā)送數(shù)據(jù)(例如UDP套接字);  
  21.  */   
  22.    
  23.  /* 函數(shù)功能:接收數(shù)據(jù);  
  24.   * 返回值:以字節(jié)計(jì)數(shù)的消息長(zhǎng)度,若無(wú)可用消息或?qū)Ψ揭呀?jīng)按序結(jié)束則返回0,若出錯(cuò)則返回-1;  
  25.   * 函數(shù)原型:  
  26.   */   
  27. #include <sys/socket.h>   
  28.    
  29. ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,   
  30.                 struct sockaddr *addr, socklen_t *addrlen);   
  31.  /* 說(shuō)明:  
  32.   * 該函數(shù)功能與read類似;  
  33.   * 若addr為非空時(shí),它將包含數(shù)據(jù)發(fā)送者的套接字地址;  
  34.   *  
  35.   * flags標(biāo)識(shí)符取值如下:  
  36.   * (1)MSG_WAITALL     等待所有數(shù)據(jù)可用  
  37.   * (2)MSG_DONTWAIT    允許非阻塞操作  
  38.   * (3)MSG_PEEK        查看已讀取的數(shù)據(jù)  
  39.   * (4)MSG_OOB         如果協(xié)議支持,發(fā)送帶外數(shù)據(jù)  
  40.   */   

基于 UDP 套接字編程

下面我們使用 UDP 協(xié)議實(shí)現(xiàn)簡(jiǎn)單的功能,客戶端從標(biāo)準(zhǔn)輸入讀取數(shù)據(jù)并把它發(fā)送給服務(wù)器,服務(wù)器接收到數(shù)據(jù)并把該數(shù)據(jù)回射給客戶端,然后客戶端收到從服務(wù)器回射的數(shù)據(jù)把它顯示到標(biāo)準(zhǔn)輸出。其功能實(shí)現(xiàn)如下圖所示:

 

 

服務(wù)器程序

  1. /* UDP 服務(wù)器 */   
  2. #include <string.h>   
  3. #include <stdio.h>   
  4. #include <unistd.h>   
  5. #include <stdlib.h>   
  6. #include <sys/socket.h>   
  7. #include <netinet/in.h>   
  8.    
  9. #define SERV_PORT 9877 /* 通用端口號(hào) */   
  10.    
  11. extern void err_sys(const char *, ...);   
  12. extern void dg_echo(int sockfd, struct sockaddr *addr, socklen_t addrlen);   
  13.    
  14. int main(int argc, char **argv)   
  15. {   
  16.     int sockfd;   
  17.     int err;   
  18.     struct sockaddr_in servaddr, cliaddr;   
  19.    
  20.     /* 初始化服務(wù)器地址信息 */   
  21.     bzero(&servaddr, sizeof(servaddr));   
  22.     servaddr.sin_family = AF_INET;   
  23.     servaddr.sin_port = htons(SERV_PORT);   
  24.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);   
  25.    
  26.     /* 創(chuàng)建套接字,并將服務(wù)器地址綁定到該套接字上 */   
  27.     if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)   
  28.         err_sys("socket error");   
  29.     err =bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));   
  30.     if(err < 0)   
  31.         err_sys("bind error");   
  32.     /* 服務(wù)器處理函數(shù):讀取套接字文本行,并把它回射給客戶端 */   
  33.     dg_echo(sockfd, (struct sockaddr*) &cliaddr, sizeof(cliaddr));   
  34.    
  35. }   

處理函數(shù)

  1. #include    "unp.h"   
  2.    
  3. void   
  4. dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)   
  5. {   
  6.     int         n;   
  7.     socklen_t   len;   
  8.     char        mesg[MAXLINE];   
  9.    
  10.     for ( ; ; ) {   
  11.         len = clilen;   
  12.         n = Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);   
  13.    
  14.         Sendto(sockfd, mesg, n, 0, pcliaddr, len);   
  15.     }   
  16. }   

#p#客戶端程序

  1. /* UDP 客戶端 */   
  2. #include <string.h>   
  3. #include <stdio.h>   
  4. #include <unistd.h>   
  5. #include <stdlib.h>   
  6. #include <sys/socket.h>   
  7. #include <netinet/in.h>   
  8. #include <arpa/inet.h>   
  9.    
  10. #define SERV_PORT 9877 /* 通用端口號(hào) */   
  11.    
  12. extern void err_sys(const char *, ...);   
  13. extern void err_quit(const char *, ...);   
  14. extern void dg_cli(FILE *fd, int sockfd, struct sockaddr *addr, socklen_t addrlen);   
  15.    
  16. int main(int argc, char **argv)   
  17. {   
  18.     int                 sockfd;   
  19.     struct sockaddr_in  servaddr;   
  20.    
  21.     if (argc != 2)   
  22.         err_quit("usage: udpcli <IPaddress>");   
  23.    
  24.     bzero(&servaddr, sizeof(servaddr));   
  25.     servaddr.sin_family = AF_INET;   
  26.     servaddr.sin_port = htons(SERV_PORT);   
  27.     inet_pton(AF_INET, argv[1], &servaddr.sin_addr);   
  28.    
  29.     if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)   
  30.         err_sys("socket err");   
  31. /* 客戶端處理函數(shù):從標(biāo)準(zhǔn)輸入讀入文本行,發(fā)送給服務(wù)器;接收來(lái)自服務(wù)器的回射文本,并把它顯示到標(biāo)準(zhǔn)輸出 */   
  32.     dg_cli(stdin, sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));   
  33.    
  34.     exit(0);   
  35. }   

客戶端處理函數(shù)

  1. #include    "unp.h"   
  2.    
  3. void   
  4. dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)   
  5. {   
  6.     int n;   
  7.     char    sendline[MAXLINE], recvline[MAXLINE + 1];   
  8.    
  9.     while (Fgets(sendline, MAXLINE, fp) != NULL) {   
  10. /* 把從標(biāo)準(zhǔn)輸入讀取的文本行發(fā)送給服務(wù)器套接字 */   
  11.         Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);   
  12. /* 接收來(lái)自服務(wù)器回射的文本行 */   
  13.         n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);   
  14.    
  15.         recvline[n] = 0;    /* null terminate */   
  16.         Fputs(recvline, stdout);   
  17.     }   
  18. }   
  1.  $./serv &   
  2. [1] 17911   
  3. $ ./client 127.0.0.1   
  4. sending text based on UDP   
  5. sending text based on UDP   
  6. goodbyte..   
  7. goodbyte..   

數(shù)據(jù)報(bào)丟失

由于 UDP 是一種不可靠的傳輸協(xié)議。在上面的客戶端 / 服務(wù)器 程序中,若數(shù)據(jù)報(bào)在傳輸?shù)倪^(guò)程中丟失,那么客戶端就是阻塞于 dg_cli 處理函數(shù)中的 recvfrom 函數(shù)調(diào)用,等待一個(gè)永遠(yuǎn)都不會(huì)達(dá)到的服務(wù)器應(yīng)答。也有可能是,客戶端數(shù)據(jù)報(bào)成功到達(dá)服務(wù)器,但是服務(wù)器的應(yīng)答數(shù)據(jù)報(bào)丟失,同樣,客戶端也將永遠(yuǎn)阻塞于 recvfrom 函數(shù)調(diào)用。一般來(lái)說(shuō),會(huì)給客戶端 recvfrom 函數(shù)調(diào)用設(shè)置一個(gè)超時(shí)時(shí)鐘,但是超時(shí)時(shí)鐘并不能確定是客戶端數(shù)據(jù)報(bào)不能到達(dá)服務(wù)器還是服務(wù)器應(yīng)答不能到達(dá)客戶端。所以我們可以采用驗(yàn)證接收到的響應(yīng)。即在 recvfrom 函數(shù)調(diào)用以返回?cái)?shù)據(jù)報(bào)發(fā)送者的 IP 地址和端口號(hào),保留來(lái)自數(shù)據(jù)報(bào)所發(fā)往服務(wù)器的應(yīng)答。

UDP 中使用 connect 函數(shù)

在沒(méi)有啟動(dòng) UDP 服務(wù)器的情況下,客戶端鍵入文本行之后,并不會(huì)回顯該文本行。此時(shí)客戶端永遠(yuǎn)阻塞于它的 recvfrom 調(diào)用,等待一個(gè)永遠(yuǎn)不會(huì)出現(xiàn)的服務(wù)器應(yīng)答。由于服務(wù)器沒(méi)有啟動(dòng),因此會(huì)響應(yīng)一個(gè)端口不可到達(dá)的 ICMP 錯(cuò)誤消息(即異步錯(cuò)誤),但是該 ICMP 錯(cuò)誤消息并不會(huì)到達(dá)客戶端進(jìn)程,因此客戶端進(jìn)程根本不知道發(fā)生什么,一直阻塞于它的 recvfrom 調(diào)用。為了能使這個(gè)異步錯(cuò)誤到達(dá)客戶端進(jìn)程,我們可以在 UDP 中調(diào)用 connect 函數(shù),使其成為一個(gè)已連接的 UDP 套接字,但是該鏈接不會(huì)像 TCP 那樣引起三次握手過(guò)程。內(nèi)核只是檢查是否存在立即可知的錯(cuò)誤,并記錄對(duì)端的 IP 地址和端口號(hào),然后立即返回到調(diào)用進(jìn)程。

下面要區(qū)分 未連接 UDP 套接字 和 已連接 UDP 套接字:

● 未連接 UDP 套接字:新創(chuàng)建 UDP 套接字默認(rèn)為該情況;

● 已連接 UDP 套接字:對(duì) UDP 套接字調(diào)用 connect 函數(shù)的結(jié)果;

已連接 UDP 套接字 相對(duì)于 未連接 UDP 套接字 會(huì)有以下的變化:

1、不能給輸出操作指定目的 IP 地址和端口號(hào)(因?yàn)檎{(diào)用 connect 函數(shù)時(shí)已經(jīng)指定),即不能使用 sendto 函數(shù),而是使用 write 或 send 函數(shù)。寫(xiě)到已連接 UDP 套接字上的內(nèi)容都會(huì)自動(dòng)發(fā)送到由 connect 指定的協(xié)議地址;

2、不必使用 recvfrom 函數(shù)以獲悉數(shù)據(jù)報(bào)的發(fā)送者,而改用 read、recv 或 recvmsg 函數(shù)。在一個(gè)已連接 UDP 套接字上,由內(nèi)核為輸入操作返回的數(shù)據(jù)報(bào)只有那些來(lái)自 connect 函數(shù)所指定的協(xié)議地址的數(shù)據(jù)報(bào)。目的地為這個(gè)已連接 UDP 套接字的本地協(xié)議地址,發(fā)源地不是該套接字早先 connect 到的協(xié)議地址的數(shù)據(jù)報(bào),不會(huì)投遞到該套接字。即只有發(fā)源地的協(xié)議地址與 connect 所指定的地址相匹配才可以把數(shù)據(jù)報(bào)傳輸?shù)皆撎捉幼?。這樣已連接 UDP 套接字只能與一個(gè)對(duì)端交換數(shù)據(jù)報(bào);

3、由已連接 UDP 套接字引發(fā)的異步錯(cuò)誤會(huì)返回給它們所在的進(jìn)程,而未連接 UDP 套接字不會(huì)接收任何異步錯(cuò)誤;

UDP 客戶端進(jìn)程或服務(wù)器進(jìn)程只在使用自己的 UDP 套接字與確定的唯一對(duì)端通信時(shí),才可以調(diào)用 connect 函數(shù)。調(diào)用 connect 函數(shù)的通常是 UDP 客戶端。以下是調(diào)用 connect 函數(shù)的客戶端處理函數(shù):

  1. #include    "unp.h"   
  2.    
  3. void   
  4. dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)   
  5. {   
  6.     int     n;   
  7.     char    sendline[MAXLINE], recvline[MAXLINE + 1];   
  8.    
  9.     Connect(sockfd, (SA *) pservaddr, servlen);   
  10.    
  11.     while (Fgets(sendline, MAXLINE, fp) != NULL) {   
  12.    
  13.         Write(sockfd, sendline, strlen(sendline));   
  14.    
  15.         n = Read(sockfd, recvline, MAXLINE);   
  16.    
  17.         recvline[n] = 0;    /* null terminate */   
  18.         Fputs(recvline, stdout);   
  19.     }   
  20. }   

此時(shí)若不啟動(dòng)服務(wù)器,只啟動(dòng)客戶端,并鍵入文本行時(shí),客戶端會(huì)接收到 異步錯(cuò)誤。

  1. $ ./client 127.0.0.1   
  2. message...   
  3. read error: Connection refused   

 

責(zé)任編輯:林琳 來(lái)源: CSDN博客
相關(guān)推薦

2014-12-11 09:20:30

TCP

2014-12-17 09:22:10

網(wǎng)絡(luò)·安全技術(shù)周刊

2015-03-31 11:24:02

2010-07-06 15:33:10

UDP套接字

2009-03-10 13:59:41

C#套接字編程

2015-05-28 10:47:38

Unix網(wǎng)絡(luò)編程TCP

2021-02-05 15:20:06

網(wǎng)絡(luò)安全套接字命令

2021-03-14 18:22:23

套接字網(wǎng)絡(luò)通信

2012-01-06 13:58:47

JavaTCP

2020-10-15 19:10:05

LinuxAPI函數(shù)

2015-10-16 09:33:26

TCPIP網(wǎng)絡(luò)協(xié)議

2013-12-27 13:39:23

Java套接字

2009-08-21 09:20:44

C#異步套接字

2010-07-05 16:17:18

UDP協(xié)議

2010-07-12 11:58:02

Java UDP協(xié)議

2019-06-25 10:32:19

UDP編程通信

2017-01-16 09:26:07

2009-08-26 09:48:48

C#異步套接字

2014-12-03 14:05:01

TCPUDP

2010-06-10 12:42:38

UDP協(xié)議
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)