溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

基于UDP的效勞器端和客戶端

發(fā)布時間:2020-07-19 18:46:09 來源:網(wǎng)絡(luò) 閱讀:509 作者:yuw2017 欄目:網(wǎng)絡(luò)安全

后面的文章中我們給出了幾個TCP的例子,關(guān)于UDP而言,只需能了解后面的內(nèi)容,完成并責(zé)難事。

UDP中的效勞器端和客戶端沒有銜接

UDP不像TCP,無需在銜接形態(tài)下交流數(shù)據(jù),因而基于UDP的效勞器端和客戶端也無需經(jīng)由銜接進(jìn)程。也就是說,不用挪用 listen() 和 accept() 函數(shù)。UDP中只要創(chuàng)立套接字的進(jìn)程和數(shù)據(jù)交流的進(jìn)程。

UDP效勞器端和客戶端均只需1個套接字

TCP中,套接字是一對一的關(guān)系。如要向10個客戶端供給效勞,那么除了擔(dān)任監(jiān)聽的套接字外,還需求創(chuàng)立10套接字。但在UDP中,不論是效勞器端照樣客戶端都只需求1個套接字。之前說明UDP道理的時分舉了郵寄包裹的例子,擔(dān)任郵寄包裹的快遞公司可以比方為UDP套接字,只需有1個快遞公司,就可以經(jīng)過它向恣意地址郵寄包裹。異樣,只需1個UDP套接字就可以向恣意主機(jī)傳送數(shù)據(jù)。

基于UDP的接納和發(fā)送函數(shù)

創(chuàng)立好TCP套接字后,傳輸數(shù)據(jù)時無需再添加地址信息,由于TCP套接字將堅持與對方套接字的銜接。換言之,TCP套接字曉得目的地址信息。但UDP套接字不會堅持銜接形態(tài),每次傳輸數(shù)據(jù)都要添加目的地址信息,這相當(dāng)于在郵寄包裹前填寫收件人地址。
發(fā)送數(shù)據(jù)運用 sendto() 函數(shù):

			ssize_t sendto(int sock, void *buf, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen); //Linux int sendto(SOCKET sock, const char *buf, int nbytes, int flags, const struct sockadr *to, int addrlen); //Windows

Linux和Windows下的 sendto() 函數(shù)相似,下面是具體參數(shù)闡明:

  • sock:用于傳輸U(kuò)DP數(shù)據(jù)的套接字;

  • buf:保管待傳輸數(shù)據(jù)的緩沖區(qū)地址;

  • nbytes:帶傳輸數(shù)據(jù)的長度(以字節(jié)計);

  • flags:可選項參數(shù),若沒有可傳遞0;

  • to:存有目的地址信息的 sockaddr 構(gòu)造體變量的地址;

  • addrlen:傳遞給參數(shù) to 的地址值構(gòu)造體變量的長度。


UDP 發(fā)送函數(shù) sendto() 與TCP發(fā)送函數(shù) write()/send() 的最大差別在于,sendto() 函數(shù)需求向他傳遞目的地址信息。
接納數(shù)據(jù)運用 recvfrom() 函數(shù):

			ssize_t recvfrom(int sock, void *buf, size_t nbytes, int flags, struct sockadr *from, socklen_t *addrlen); //Linux int recvfrom(SOCKET sock, char *buf, int nbytes, int flags, const struct sockaddr *from, int *addrlen); //Windows

因為UDP數(shù)據(jù)的發(fā)送端不不定,所以 recvfrom() 函數(shù)界說為可接納發(fā)送端信息的方式,詳細(xì)參數(shù)如下:

  • sock:用于接納UDP數(shù)據(jù)的套接字;

  • buf:保管接納數(shù)據(jù)的緩沖區(qū)地址;

  • nbytes:可接納的最大字節(jié)數(shù)(不克不及超越buf緩沖區(qū)的巨細(xì));

  • flags:可選項參數(shù),若沒有可傳遞0;

  • from:存有發(fā)送端地址信息的sockaddr構(gòu)造體變量的地址;

  • addrlen:保管參數(shù) from 的構(gòu)造體變量長度的變量地址值。

基于UDP的反響效勞器端/客戶端

下面聯(lián)合之前的內(nèi)容完成反響客戶端。需求留意的是,UDP分歧于TCP,不存在懇求銜接和受理進(jìn)程,因而在某種意義上無法明白辨別效勞器端和客戶端,只是由于其供給效勞而稱為效勞器端,愿望列位讀者不要曲解。
下面給出Windows下的代碼,Linux與此相似,不再贅述。
效勞器端 server.cpp:

			#include <stdio.h> #include <winsock2.h> #pragma comment (lib, "ws2_32.lib") //加載 ws2_32.dll #define BUF_SIZE 100 int main(){ WSADATA wsaData; WSAStartup( MAKEWORD(2, 2), &wsaData); //創(chuàng)立套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); //綁定套接字 sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); //每一個字節(jié)都用0填充 servAddr.sin_family = PF_INET; //運用IPv4地址 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //主動獲取IP地址 servAddr.sin_port = htons(1234); //端口 bind(sock, (SOCKADDR*)&servAddr, sizeof(SOCKADDR)); //接納客戶端懇求 SOCKADDR clntAddr; //客戶端地址信息 int nSize = sizeof(SOCKADDR); char buffer[BUF_SIZE]; //緩沖區(qū) while(1){ int strLen = recvfrom(sock, buffer, BUF_SIZE, 0, &clntAddr, &nSize); sendto(sock, buffer, strLen, 0, &clntAddr, nSize); } closesocket(sock); WSACleanup(); return 0; }

代碼闡明:
1) 第12行代碼在創(chuàng)立套接字時,向 socket() 第二個參數(shù)傳遞 SOCK_DGRAM,以指明運用UDP協(xié)定。
2) 第18行代碼中運用htonl(INADDR_ANY)來主動獲取IP地址。
應(yīng)用常數(shù) INADDR_ANY 主動獲取IP地址有一個分明的益處,就是當(dāng)軟件裝置到其他效勞器或許效勞器IP地址改動時,不必再更改源碼從新編譯,也不必在啟動軟件時手動輸出。并且,假如一臺盤算機(jī)中已分派多個IP地址(例如路由器),那么只需端標(biāo)語分歧,就可以從分歧的IP地址接納數(shù)據(jù)。所以,效勞器中優(yōu)先思索運用INADDR_ANY;而客戶端中除非帶有一局部效勞器功用,不然不會采取。
客戶端 client.cpp:

			#include <stdio.h> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") //加載 ws2_32.dll #define BUF_SIZE 100 int main(){ //初始化DLL WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); //創(chuàng)立套接字 SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0); //效勞器地址信息 sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); //每一個字節(jié)都用0填充 servAddr.sin_family = PF_INET; servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(1234); //不時獲取用戶輸出并發(fā)送給效勞器,然后承受效勞器數(shù)據(jù) sockaddr fromAddr; int addrLen = sizeof(fromAddr); while(1){ char buffer[BUF_SIZE] = {0}; printf("Input a string: "); gets(buffer); sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); int strLen = recvfrom(sock, buffer, BUF_SIZE, 0, &fromAddr, &addrLen); buffer[strLen] = 0; printf("Message form server: %s\n", buffer); } closesocket(sock); WSACleanup(); return 0; }

先運轉(zhuǎn) server,再運轉(zhuǎn) client,client 輸入后果為:

Input a string: C言語中文網(wǎng)
Message form server: C言語中文網(wǎng)
Input a string: c.biancheng.net Founded in 2012
Message form server: c.biancheng.net Founded in 2012
Input a string:


從代碼中可以看出,server.cpp 中沒有運用 listen() 函數(shù),client.cpp 中也沒有運用 connect() 函數(shù),由于 UDP 不需求銜接。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI