中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

廣州海珠區(qū)繁華嗎排名seo公司哪家好

廣州海珠區(qū)繁華嗎,排名seo公司哪家好,重慶網(wǎng)站建設(shè)就找承越,網(wǎng)頁頁面建設(shè)方案目錄 預(yù)備知識 socket通信的本質(zhì) 認(rèn)識TCP協(xié)議和UDP協(xié)議 網(wǎng)絡(luò)字節(jié)序 socket編程流程 socket編程時(shí)常見的函數(shù) 服務(wù)端綁定 整數(shù)IP和字符串IP 客戶端套接字的創(chuàng)建和綁定 預(yù)備知識 理解源IP和目的IP 源IP指的是發(fā)送數(shù)據(jù)包的主機(jī)的IP地址,目的IP指的是接收數(shù)據(jù)包…

目錄

預(yù)備知識

?socket通信的本質(zhì)

認(rèn)識TCP協(xié)議和UDP協(xié)議

網(wǎng)絡(luò)字節(jié)序

socket編程流程

socket編程時(shí)常見的函數(shù)

服務(wù)端綁定

整數(shù)IP和字符串IP

客戶端套接字的創(chuàng)建和綁定


預(yù)備知識

理解源IP和目的IP

????????源IP指的是發(fā)送數(shù)據(jù)包的主機(jī)的IP地址,目的IP指的是接收數(shù)據(jù)包的主機(jī)的IP地址。在網(wǎng)絡(luò)通信中,當(dāng)一臺主機(jī)需要向另一臺主機(jī)發(fā)送數(shù)據(jù)包時(shí),它需要將數(shù)據(jù)包的目的IP地址設(shè)置為接收主機(jī)的IP地址,同時(shí)在數(shù)據(jù)包的頭部中加入源IP地址,以便接收主機(jī)能夠知道數(shù)據(jù)包來自哪個(gè)主機(jī)。

理解源MAC地址和目的MAC地址

????????源MAC地址和目的MAC地址是數(shù)據(jù)鏈路層中的兩個(gè)重要概念,MAC地址是每個(gè)網(wǎng)卡獨(dú)有的物理地址,用于在局域網(wǎng)中標(biāo)識設(shè)備。

源MAC地址是指發(fā)送數(shù)據(jù)包的主機(jī)的網(wǎng)卡的MAC地址,目的MAC地址是指接收數(shù)據(jù)包的主機(jī)的網(wǎng)卡的MAC地址。在數(shù)據(jù)包傳輸過程中,數(shù)據(jù)包的源MAC地址和目的MAC地址會隨著數(shù)據(jù)包一起傳輸,并被中間的路由器或交換機(jī)使用來判斷數(shù)據(jù)包的轉(zhuǎn)發(fā)。

當(dāng)數(shù)據(jù)包從源主機(jī)發(fā)送時(shí),它首先需要找到目的主機(jī)所在的網(wǎng)卡,這時(shí)候就需要目的MAC地址。發(fā)送主機(jī)會將目的MAC地址填入數(shù)據(jù)包中,以便路由器或交換機(jī)能夠?qū)?shù)據(jù)包準(zhǔn)確地發(fā)送給目的主機(jī)。而源MAC地址則用于標(biāo)識數(shù)據(jù)包的來源,這樣目的主機(jī)就能夠知道數(shù)據(jù)包是從哪個(gè)主機(jī)發(fā)送過來的

理解源端口號和目的端口號

????????在TCP/IP協(xié)議中,源端口號和目的端口號是定義在傳輸層的概念,用于在不同主機(jī)之間的通信中唯一標(biāo)識一個(gè)虛擬連接。源端口號和目的端口號組成了一個(gè)socket,可以理解為一個(gè)網(wǎng)絡(luò)應(yīng)用程序的地址。

源端口號是發(fā)送方的端口號,目的端口號是接收方的端口號。在發(fā)送數(shù)據(jù)時(shí),網(wǎng)絡(luò)應(yīng)用程序會將數(shù)據(jù)發(fā)送給目標(biāo)主機(jī)的特定端口號,而接收方則會通過監(jiān)聽特定端口號來接收發(fā)送方傳來的數(shù)據(jù)。

端口號的范圍是0~65535,其中0~1023是系統(tǒng)端口號,已經(jīng)被分配給一些知名的服務(wù)或應(yīng)用程序,比如80號端口是HTTP服務(wù)默認(rèn)端口、 21號端口是FTP服務(wù)默認(rèn)端口、25號端口是SMTP服務(wù)默認(rèn)端口。而1024~65535是動態(tài)端口號,可以由應(yīng)用程序自行分配使用。

通過源端口號和目的端口號,TCP/IP協(xié)議可以建立并維護(hù)一條虛擬連接,保證數(shù)據(jù)包的可靠傳輸,并可以區(qū)分不同的應(yīng)用程序之間的通信。

?socket通信的本質(zhì)

????????Socket通信的本質(zhì)是建立在TCP/IP協(xié)議之上的一種應(yīng)用層協(xié)議,它用于在網(wǎng)絡(luò)上實(shí)現(xiàn)進(jìn)程之間的通信。在Socket通信中,進(jìn)程可以作為客戶端或服務(wù)器端,通過IP地址和端口號建立連接并進(jìn)行數(shù)據(jù)傳輸。

在建立Socket連接時(shí),客戶端會向特定IP地址和端口號發(fā)送連接請求,服務(wù)器端會接受連接請求并建立連接。一旦連接建立成功,客戶端和服務(wù)器端就可以通過Socket實(shí)例進(jìn)行數(shù)據(jù)的收發(fā)。

Socket通信的本質(zhì)是通過TCP/IP協(xié)議在網(wǎng)絡(luò)上傳輸數(shù)據(jù),確保數(shù)據(jù)的可靠性和穩(wěn)定性。TCP協(xié)議提供可靠的數(shù)據(jù)傳輸和流量控制,IP協(xié)議提供數(shù)據(jù)包的路由和分發(fā)。通過Socket通信,可以建立一對一、一對多、多對多的通信方式,實(shí)現(xiàn)進(jìn)程之間的高效通信,廣泛應(yīng)用于互聯(lián)網(wǎng)、局域網(wǎng)和各種分布式系統(tǒng)中。

總結(jié):通過IP地址和MAC地址可以實(shí)現(xiàn)數(shù)據(jù)有一臺主機(jī)傳輸?shù)搅硪慌_主機(jī)了,但在實(shí)際生活中我們希望的是能將數(shù)據(jù)傳輸?shù)街付ǖ膽?yīng)用中(在機(jī)器上稱進(jìn)程),例如我們在自己主機(jī)上的京東APP上點(diǎn)贊一個(gè)店家時(shí)我們希望這個(gè)數(shù)據(jù)會傳輸?shù)狡渌鳈C(jī)上的京東APP上,而不是淘寶APP或其它APP。這時(shí)就需要使用端口號來標(biāo)識特定的進(jìn)程APP。

在不同的兩臺主機(jī)上,可能會同時(shí)存在多個(gè)正在進(jìn)行跨網(wǎng)絡(luò)通信的進(jìn)程,當(dāng)數(shù)據(jù)到達(dá)目的主機(jī)時(shí)就需要通過端口號找到該主機(jī)上對應(yīng)的通信進(jìn)程,然后將數(shù)據(jù)交給該進(jìn)程進(jìn)行處理。而該主機(jī)也需要記住發(fā)送端的信息,當(dāng)數(shù)據(jù)處理完后返還處理結(jié)果。

端口號的理解

端口號(port)是傳輸層協(xié)議的內(nèi)容

端口號是一個(gè)2字節(jié)16位的整數(shù);

端口號用來標(biāo)識一個(gè)進(jìn)程, 告訴操作系統(tǒng), 當(dāng)前的這個(gè)數(shù)據(jù)要交給哪一個(gè)進(jìn)程來處理;

IP地址 + 端口號能夠標(biāo)識網(wǎng)絡(luò)上的某一臺主機(jī)的某一個(gè)進(jìn)程; 一個(gè)端口號只能被一個(gè)進(jìn)程占用。

理解 "端口號" 和 "進(jìn)程ID"

????????到這里有人會問當(dāng)數(shù)據(jù)到達(dá)目的主機(jī)時(shí),為何不以進(jìn)程PID為根據(jù)將數(shù)據(jù)發(fā)送給目的進(jìn)程?端口號(prot)的作用和進(jìn)程ID具有同樣的功能,都是唯一標(biāo)識一臺主機(jī)上的某一個(gè)進(jìn)程。為何還要創(chuàng)建出端口號?

首先進(jìn)程ID是用于唯一標(biāo)識系統(tǒng)內(nèi)所有進(jìn)程的,屬于系統(tǒng)級概念,端口號用于唯一標(biāo)識系統(tǒng)內(nèi)要進(jìn)行跨網(wǎng)絡(luò)通信的進(jìn)程,屬于網(wǎng)絡(luò)概念。并不是所有的進(jìn)程都需要進(jìn)行跨網(wǎng)絡(luò)通信。

當(dāng)數(shù)據(jù)到達(dá)目的主機(jī)時(shí)如何找到要接收數(shù)據(jù)的端口號?

底層采用哈希表方式建立端口號和進(jìn)程IPD或PCB之間的映射,當(dāng)?shù)讓幽玫蕉丝谔枙r(shí)通過算法找到對應(yīng)的進(jìn)程。

認(rèn)識TCP協(xié)議和UDP協(xié)議

TCP協(xié)議

TCP協(xié)議(Transmission Control Protocol,傳輸控制協(xié)議)是一種可靠的、面向連接的協(xié)議。它主要用于在計(jì)算機(jī)網(wǎng)絡(luò)上提供可靠的數(shù)據(jù)傳輸服務(wù)。

TCP協(xié)議是一種面向字節(jié)流的協(xié)議,它通過將數(shù)據(jù)分成一系列的數(shù)據(jù)包進(jìn)行傳輸,從而保證了數(shù)據(jù)的可靠性。在TCP連接建立后,通信雙方將通過三次握手建立連接。數(shù)據(jù)傳輸過程中,TCP協(xié)議會對每一個(gè)數(shù)據(jù)包進(jìn)行確認(rèn)和校驗(yàn),確保數(shù)據(jù)的完整性和正確性。當(dāng)接收方接收到一個(gè)數(shù)據(jù)包時(shí),會向發(fā)送方發(fā)送一個(gè)確認(rèn)消息,確保發(fā)送方已經(jīng)正確地發(fā)送了該數(shù)據(jù)包。如果發(fā)送方在一定時(shí)間內(nèi)沒有收到確認(rèn)消息,它會重新發(fā)送相同的數(shù)據(jù)包,以確保數(shù)據(jù)的可靠傳輸。

總結(jié):

傳輸層協(xié)議

有連接

可靠傳輸

面向字節(jié)流

UDP協(xié)議

UDP協(xié)議(User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)是一種簡單的、無連接的網(wǎng)絡(luò)傳輸協(xié)議。UDP協(xié)議的特點(diǎn)是速度快,但可靠性比較低。

UDP協(xié)議是一種面向數(shù)據(jù)報(bào)的協(xié)議,它將數(shù)據(jù)分割成一個(gè)個(gè)獨(dú)立的數(shù)據(jù)包進(jìn)行傳輸,這些數(shù)據(jù)包被稱為用戶數(shù)據(jù)報(bào)(UDP Datagram)。在傳輸數(shù)據(jù)的過程中,UDP協(xié)議不會進(jìn)行數(shù)據(jù)的確認(rèn)和校驗(yàn),也不會保證數(shù)據(jù)的順序性。因此,UDP協(xié)議比TCP協(xié)議要快很多,但會存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)。

?總結(jié):

傳輸層協(xié)議

無連接

不可靠傳輸

面向數(shù)據(jù)報(bào)

網(wǎng)絡(luò)字節(jié)序

網(wǎng)絡(luò)字節(jié)序,也叫大端字節(jié)序,是一種字節(jié)序(byte order)規(guī)范,它規(guī)定了數(shù)據(jù)在網(wǎng)絡(luò)傳輸時(shí)的排序方式。

計(jì)算機(jī)數(shù)據(jù)存儲模式

大端模式:數(shù)據(jù)的高字節(jié)存儲在低地址,低字節(jié)存儲在高地址。

小端模式:數(shù)據(jù)的高字節(jié)存儲在高地址,低字節(jié)存儲在低地址。

????????在網(wǎng)絡(luò)傳輸中,不同計(jì)算機(jī)上的處理器可能采用不同的字節(jié)序,為了保證數(shù)據(jù)在網(wǎng)絡(luò)中傳輸時(shí)的正確性,就需要使用統(tǒng)一的字節(jié)序,即網(wǎng)絡(luò)字節(jié)序。在網(wǎng)絡(luò)字節(jié)序中,整數(shù)類型的數(shù)據(jù)的高字節(jié)存儲在低地址,低字節(jié)存儲在高地址,與大端字節(jié)序相同。而在小端字節(jié)序中,整數(shù)類型的數(shù)據(jù)的高字節(jié)存儲在高地址,低字節(jié)存儲在低地址。因此,在網(wǎng)絡(luò)傳輸中,數(shù)據(jù)需要轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序,才能確保不同計(jì)算機(jī)之間的數(shù)據(jù)傳輸?shù)恼_性。

網(wǎng)絡(luò)字節(jié)序是一種字節(jié)序規(guī)范,它規(guī)定了數(shù)據(jù)在網(wǎng)絡(luò)傳輸時(shí)的排序方式,能夠保證不同計(jì)算機(jī)之間的數(shù)據(jù)傳輸?shù)恼_性。

socket編程流程

sockaddr結(jié)構(gòu)

????????套接字屬于進(jìn)程間通信中的一種,它支持本地通信和網(wǎng)絡(luò)通信。在使用套接字進(jìn)行跨網(wǎng)絡(luò)通信是我們需要指明IP地址和端口號,而使用于本地通信則不需要,因此套接字提供了sockaddr_in結(jié)構(gòu)體和sockaddr_un結(jié)構(gòu)體,其中sockaddr_in結(jié)構(gòu)體用于跨網(wǎng)絡(luò)通信,而sockaddr_un結(jié)構(gòu)體用于本地通信,網(wǎng)絡(luò)讓套接字的本地通信和跨網(wǎng)絡(luò)通信都能使用一套相同的接口,系統(tǒng)還提供了sockaddr結(jié)構(gòu)體。這三個(gè)結(jié)構(gòu)體的頭部的16個(gè)比特位都是一樣的,這個(gè)字段叫協(xié)議家族。

所以我們在傳參是就不用傳入sockaddr_in或sockaddr_un這樣的結(jié)構(gòu)體,而使用統(tǒng)一的sockaddr,我們通過設(shè)置協(xié)議家族參數(shù)來表明我們要進(jìn)行本地通信還是網(wǎng)絡(luò)通信,這樣套接字的本地通信和網(wǎng)絡(luò)通信就得到了統(tǒng)一。

注意:在編寫程序時(shí),還是使用相應(yīng)得結(jié)構(gòu)體,如要進(jìn)行網(wǎng)絡(luò)通信時(shí),定義時(shí)仍使用sockaddr_in,但在傳參時(shí)強(qiáng)轉(zhuǎn)為sockaddr*。

socket編程時(shí)常見的函數(shù)

socket( )

socket( )是一個(gè)系統(tǒng)調(diào)用,用于在應(yīng)用程序中創(chuàng)建一個(gè)新的套接字(socket)。

該函數(shù)的原型如下:

int socket(int domain, int type, int protocol);

函數(shù)參數(shù)說明:

  • domain:套接字通信的協(xié)議族,相當(dāng)于struct sockaddr結(jié)構(gòu)體的前16位,如果使用于本地通信就設(shè)置為AF_UNIX,如果使用于網(wǎng)絡(luò)通信就設(shè)置AF_INET(IPv4協(xié)議)和AF_INET6(IPv6協(xié)議)等。
  • type:套接字的類型,常見的有SOCK_STREAM(面向連接的TCP協(xié)議)和SOCK_DGRAM(無連接的UDP協(xié)議)等。
  • protocol:指定協(xié)議,通常為0,表示使用默認(rèn)協(xié)議。

函數(shù)返回值:

  • 成功:返回一個(gè)socket的文件描述符,可以用于后續(xù)網(wǎng)絡(luò)通信中。
  • 失敗:返回-1,并設(shè)置errno全局變量表示具體錯誤原因。

當(dāng)我們在程序中執(zhí)行了socket函數(shù)時(shí),底層會進(jìn)行以下幾個(gè)步驟:

  1. 內(nèi)核創(chuàng)建一個(gè)新的socket對象,并為它分配唯一的文件描述符。

  2. 內(nèi)核為此socket分配相關(guān)的資源,包括緩沖區(qū)、狀態(tài)信息等。

  3. 內(nèi)核為此socket分配本地端口號(如果是TCP協(xié)議的話),并對本地端口進(jìn)行綁定(bind)操作,使得其它進(jìn)程可以通過這個(gè)端口號來與此socket進(jìn)行通信。

  4. 內(nèi)核返回新socket對象的文件描述符,程序可以通過這個(gè)文件描述符來訪問此socket。

?
????????當(dāng)進(jìn)程調(diào)用socket函數(shù)時(shí),實(shí)際就相當(dāng)于打開了一個(gè)“網(wǎng)絡(luò)文件”,這時(shí)進(jìn)程就要對這個(gè)"網(wǎng)絡(luò)文件"進(jìn)行管理,就要為這個(gè)"網(wǎng)絡(luò)文件"分配文件描述符,這個(gè)文件描述符會作為socket函數(shù)的返回值返回用戶,與普通的磁盤文件不同的是,磁盤文件是將數(shù)據(jù)刷新到磁盤上就完成了數(shù)據(jù)的操作,而網(wǎng)絡(luò)文件則是將文件緩沖區(qū)的數(shù)據(jù)將會刷新到網(wǎng)卡里而卡是負(fù)責(zé)數(shù)據(jù)發(fā)送的,最終會將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)中。

創(chuàng)建套接字

? ? ? ? 進(jìn)行創(chuàng)建套接字時(shí),要根據(jù)使用場景而填入相應(yīng)的參數(shù),這里我們使用UDP進(jìn)行網(wǎng)絡(luò)通信,所以協(xié)議族填A(yù)F_INET,SOCK_DGRAM,第三個(gè)參數(shù)填0為默認(rèn)。

class udpserver
{public:
bool InitServer()
{//創(chuàng)建套接字_sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET//表示要進(jìn)行網(wǎng)絡(luò)通信,SOCK_DGRAM  UDP協(xié)議if(_sockfd<0){//表示創(chuàng)建套接字失敗std::cout<<" socket error";return false;}std::cout<<" socket create success,socfd:"<<_sockfd<< std::endl;return true;}
~udpserver()
{if(_sockfd>0){close(_sockfd);//關(guān)閉文件描述符}
}
private:
int _sockfd;//網(wǎng)絡(luò)文件描述符};
#include"server.hpp"
int main()
{udpserver* ser=new udpserver();ser->InitServer();return 0;
}

運(yùn)行結(jié)果:?

服務(wù)端綁定


????????套接字創(chuàng)建好后,就相當(dāng)于打開了一個(gè)文件,這個(gè)文件和其他文件并沒有什么不同;操作系統(tǒng)并不知道要將文件的內(nèi)容寫到磁盤還網(wǎng)卡,所以我們需要將這個(gè)文件與一個(gè)本地地址進(jìn)行綁(?通常指IP地址和端口號)?,?這就不得不介紹bind函數(shù)。

bind函數(shù)是一個(gè)系統(tǒng)調(diào)用,它在應(yīng)用程序的套接字(socket)和本地地址(IP地址和端口號)之間建立一個(gè)關(guān)聯(lián)關(guān)系,使得其他應(yīng)用程序可以通過該本地地址與該套接字進(jìn)行通信。bind函數(shù)的主要作用是將一個(gè)特定的套接字綁定到一個(gè)特定的本地地址上,使得該套接字在網(wǎng)絡(luò)上唯一地標(biāo)識一個(gè)通信節(jié)點(diǎn),從而實(shí)現(xiàn)網(wǎng)絡(luò)通信。bind函數(shù)的函數(shù)原型如下:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

其中,sockfd是由socket函數(shù)返回的套接字描述符,addr是一個(gè)指向本地地址結(jié)構(gòu)體的指針,addrlen是該結(jié)構(gòu)體的長度。bind函數(shù)的調(diào)用方法如下:

struct sockaddr_in addr;
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 創(chuàng)建一個(gè)TCP套接字
memset(&addr, 0, sizeof(addr)); // 清空地址結(jié)構(gòu)體
addr.sin_family = AF_INET; // 設(shè)置地址族為IPv4
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 設(shè)置本地地址為任意IP地址
addr.sin_port = htons(8080); // 設(shè)置本地端口號為8080
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { // 綁定套接字和本地地址perror("bind error");exit(EXIT_FAILURE);
}

在上面的例子中,我們首先通過socket函數(shù)創(chuàng)建了一個(gè)TCP套接字,然后創(chuàng)建了一個(gè)本地地址結(jié)構(gòu)體addr,該結(jié)構(gòu)體包含了本地IP地址和端口號等信息,然后將該結(jié)構(gòu)體和套接字描述符作為參數(shù)傳入bind函數(shù)中,調(diào)用bind函數(shù)將套接字和本地地址綁定起來。在綁定成功后,應(yīng)用程序就可以通過該本地地址來訪問該套接字,實(shí)現(xiàn)網(wǎng)絡(luò)通信的功能。

#pragma once#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include<unistd.h>
#include <unordered_map>
using namespace std;class udpserver
{public:
udpserver(std::string ip,int port):_sockfd(-1),_port(port),_ip(ip)
{}
bool InitServer()
{//創(chuàng)建套接字_sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET//表示要進(jìn)行網(wǎng)絡(luò)通信,SOCK_DGRAM  UDP協(xié)議if(_sockfd<0){//表示創(chuàng)建套接字失敗std::cout<<" socket error";return false;}std::cout<<" socket create success,socfd:"<<_sockfd<< std::endl;struct sockaddr_in local;memset(&local,'\0',sizeof(local));//清空結(jié)構(gòu)體local.sin_family=AF_INET;local.sin_port=htons(_port);local.sin_addr.s_addr=inet_addr(_ip.c_str());//綁定if(bind(_sockfd,(struct sockaddr*)&local,sizeof(sockaddr))<0){std::cout<<"bind error"<<std::endl;return false;}std::cout<<"bind success"<<std::endl;return true;}~udpserver()
{if(_sockfd>0){close(_sockfd);//關(guān)閉文件描述符}
}
private:
int _sockfd;//網(wǎng)絡(luò)文件描述符
int _port;//端口號
std::string _ip;//IP地址};
#include"server.hpp"
int main(int argc,char*argv[])
{if(argc!=2){std:cout<<"usage:"<<argv[0]<<" port"<<std::endl;return 1;}std::string ip="127.0.0.1";int port=atoi(argv[1]);udpserver* ser=new udpserver(ip,port);ser->InitServer();return 0;
}

整數(shù)IP和字符串IP

IP地址是Internet Protocol的縮寫,是一個(gè)32位二進(jìn)制數(shù),通常表示為四個(gè)8位二進(jìn)制數(shù),即四個(gè)數(shù)字,每個(gè)數(shù)字范圍在0到255之間,用點(diǎn)分十進(jìn)制形式表示。例如:192.168.1.1

IP地址的表示形式有兩種:

整數(shù)IP:將點(diǎn)分十進(jìn)制形式表示的IP地址轉(zhuǎn)換為一個(gè)32位整數(shù),例如:192.168.1.1可以轉(zhuǎn)換為十進(jìn)制數(shù)3232235777。

字符串IP:即點(diǎn)分十進(jìn)制形式表示的IP地址,例如:192.168.1.1。

整數(shù)IP轉(zhuǎn)為字符串IP

????????將整數(shù)IP轉(zhuǎn)換為字符串IP的主要原因是方便人們閱讀和理解IP地址。字符串IP的形式更符合人們的閱讀習(xí)慣,同時(shí)也更容易記憶。在實(shí)際應(yīng)用中,比如在配置網(wǎng)絡(luò)設(shè)備和編寫網(wǎng)絡(luò)應(yīng)用程序時(shí),我們通常使用字符串IP來表示IP地址,因?yàn)檫@更符合人們的直覺和需要。

inet_ntoa()函數(shù)是一個(gè)用于將32位無符號整數(shù)表示的IP地址轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串表示的網(wǎng)絡(luò)函數(shù)。它的頭文件為"arpa/inet.h",使用時(shí)需要包含該頭文件。

該函數(shù)的原型如下:

char *inet_ntoa(struct in_addr in);

參數(shù)in是一個(gè)struct in_addr類型的結(jié)構(gòu)體,表示待轉(zhuǎn)換的32位無符號整數(shù)表示的IP地址。函數(shù)返回值是轉(zhuǎn)換后的點(diǎn)分十進(jìn)制字符串表示的IP地址,如果轉(zhuǎn)換失敗則返回NULL。

例如,以下代碼將32位無符號整數(shù)表示的IP地址192.168.0.1轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串,并打印出轉(zhuǎn)換后的結(jié)果:

inet_ntoa()函數(shù)是一個(gè)用于將32位無符號整數(shù)表示的IP地址轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串表示的網(wǎng)絡(luò)函數(shù)。它的頭文件為"arpa/inet.h",使用時(shí)需要包含該頭文件。

該函數(shù)的原型如下:

char *inet_ntoa(struct in_addr in);

參數(shù)in是一個(gè)struct in_addr類型的結(jié)構(gòu)體,表示待轉(zhuǎn)換的32位無符號整數(shù)表示的IP地址。

函數(shù)返回值是轉(zhuǎn)換后的點(diǎn)分十進(jìn)制字符串表示的IP地址,如果轉(zhuǎn)換失敗則返回NULL。

例如,以下代碼將32位無符號整數(shù)表示的IP地址192.168.0.1轉(zhuǎn)換為點(diǎn)分十進(jìn)制字符串,并打印出轉(zhuǎn)換后的結(jié)果:

#include <stdio.h>
#include <arpa/inet.h>int main() {in_addr_t ip_int = 3232235521; // 192.168.0.1的32位無符號整數(shù)表示struct in_addr in;in.s_addr = ip_int;char* ip_str = inet_ntoa(in);if (ip_str == NULL) {printf("IP address conversion error!\n");return -1;} else {printf("IP address in string format: %s\n", ip_str);return 0;}
}

需要注意的是,由于inet_ntoa()函數(shù)返回的是指向靜態(tài)緩沖區(qū)的指針,因此每次調(diào)用該函數(shù)時(shí)返回的字符串都會被覆蓋。如果需要保存轉(zhuǎn)換后的IP地址字符串,可以使用strdup()函數(shù)對其進(jìn)行復(fù)制。

recvfrom()函數(shù)是一個(gè)用于在UDP協(xié)議中接收數(shù)據(jù)的網(wǎng)絡(luò)函數(shù)。它的頭文件為<sys/socket.h>,使用時(shí)需要包含該頭文件。

該函數(shù)的原型如下:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

參數(shù)說明:

參數(shù)sockfd為已經(jīng)創(chuàng)建好的socket文件描述符,用于接收數(shù)據(jù);

參數(shù)buf為接收數(shù)據(jù)的緩沖區(qū);參數(shù)len為緩沖區(qū)的長度,即最多接收的字節(jié)數(shù);

參數(shù)flags一般為0,表示沒有特殊要求;

參數(shù)src_addr為指向存放發(fā)送者IP地址和端口號的sockaddr結(jié)構(gòu)體指針;

參數(shù)addrlen為指向sockaddr結(jié)構(gòu)體長度的指針,接收到的發(fā)送者地址長度會寫入其中。

返回值:函數(shù)返回值為接收到的字節(jié)數(shù),如果出錯則返回-1。

注意:udp是不面向連接的,所以在使用udp協(xié)議進(jìn)行通信時(shí),我們在獲取數(shù)據(jù)信息時(shí),還要獲取數(shù)據(jù)發(fā)送方的有關(guān)屬性,包括IP地址和端口號,要將struct sockadd_in* 轉(zhuǎn)為更適合傳輸?shù)膕truct sockadd*類型。

例如,以下代碼從創(chuàng)建好的socket文件描述符sock_fd中接收數(shù)據(jù),并輸出接收到的信息:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>int main() {int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);if (sock_fd == -1) {printf("Failed to create socket!\n");return -1;}struct sockaddr_in serv_addr;memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");serv_addr.sin_port = htons(8888);if (bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) {printf("bind error!\n");return -1;}char buf[1024] = {0};struct sockaddr_in cli_addr;socklen_t cli_len = sizeof(cli_addr);ssize_t recv_len = recvfrom(sock_fd, buf, sizeof(buf), 0, (struct sockaddr *)&cli_addr, &cli_len);if (recv_len == -1) {printf("recvfrom error!\n");return -1;}printf("Received message from %s:%d, message: %s\n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port), buf);close(sock_fd);return 0;
}

此處為UDP服務(wù)器代碼,創(chuàng)建套接字,進(jìn)行bind()操作后等待客戶端發(fā)送數(shù)據(jù),使用recvfrom()函數(shù)接收數(shù)據(jù),然后輸出接收到的信息。

#pragma once#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <functional>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include<unistd.h>
#include <unordered_map>
using namespace std;class udpserver
{public:
udpserver(std::string ip,int port):_sockfd(-1),_port(port),_ip(ip)
{}
bool InitServer()
{//創(chuàng)建套接字_sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET//表示要進(jìn)行網(wǎng)絡(luò)通信,SOCK_DGRAM  UDP協(xié)議if(_sockfd<0){//表示創(chuàng)建套接字失敗std::cout<<" socket error";return false;}std::cout<<" socket create success,socfd:"<<_sockfd<< std::endl;struct sockaddr_in local;memset(&local,'\0',sizeof(local));//清空結(jié)構(gòu)體local.sin_family=AF_INET;local.sin_port=htons(_port);local.sin_addr.s_addr=inet_addr(_ip.c_str());//綁定if(bind(_sockfd,(struct sockaddr*)&local,sizeof(sockaddr))<0){std::cout<<"bond error"<<std::endl;return false;}std::cout<<"bond success"<<std::endl;return true;}void Start()
{#define SIZE 1024 char buffer[SIZE];while(true){struct sockaddr_in perr;socklen_t len=sizeof(perr);//讀取數(shù)據(jù)ssize_t size=recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&perr,&len);if(size<0)//讀取失敗{std::cout<<"recvfrom cerror"<<std::endl;}else{buffer[size]='\0';int port=ntohs(perr.sin_port);std::string ip=inet_ntoa(perr.sin_addr);std::cout<<ip<<": "<<port<<"# "<<buffer<<std::endl;}}
}
~udpserver()
{if(_sockfd>0){close(_sockfd);//關(guān)閉文件描述符}
}
private:
int _sockfd;//網(wǎng)絡(luò)文件描述符
int _port;//端口號
std::string _ip;//IP地址};
#include"server.hpp"
int main(int argc,char*argv[])
{if(argc!=2){std:cout<<"usage:"<<argv[0]<<" port"<<std::endl;return 1;}std::string ip="127.0.0.1";int port=atoi(argv[0]);udpserver* ser=new udpserver(ip,port);ser->InitServer();ser->Start();return 0;
}

客戶端套接字的創(chuàng)建和綁定

客戶端在創(chuàng)建套接字時(shí)參數(shù)的傳遞與服務(wù)端創(chuàng)建套接字時(shí)一樣都是AF_INET, SOCK_DGRAM, 0,不同的是服務(wù)端需要進(jìn)行端口號綁定,而客戶端不需要。

但在網(wǎng)絡(luò)通信,通信雙方都需要找到對方,因此服務(wù)端和客戶端都需要有各自的IP地址和端口號,只不過服務(wù)端需要進(jìn)行端口號的綁定,而客戶端不需要。
因?yàn)榉?wù)器就是為了給別人提供服務(wù)的,因此服務(wù)器必須要讓別人知道自己的IP地址和端口號,IP地址一般對應(yīng)的就是域名,而端口號一般沒有顯示指明過,因此服務(wù)端的端口號一定要是一個(gè)眾所周知的端口號,并且選定后不能輕易改變,否則客戶端是無法知道服務(wù)端的端口號的,這就是服務(wù)端要進(jìn)行綁定的原因,只有綁定之后這個(gè)端口號才真正屬于自己,因?yàn)橐粋€(gè)端口只能被一個(gè)進(jìn)程所綁定,服務(wù)器綁定一個(gè)端口就是為了獨(dú)占這個(gè)端口。
而客戶端在通信時(shí)雖然也需要端口號,但客戶端一般是不進(jìn)行綁定的,客戶端訪問服務(wù)端的時(shí)候,端口號只要是唯一的就行了,不需要和特定客戶端進(jìn)程強(qiáng)相關(guān)。

客戶端不需要綁定端口號是因?yàn)榭蛻舳说奶捉幼衷趧?chuàng)建時(shí)會自動由操作系統(tǒng)分配一個(gè)隨機(jī)端口號,并且這個(gè)隨機(jī)端口號會在套接字連接到服務(wù)器端時(shí)被發(fā)送給服務(wù)器端,因此服務(wù)器端就可以使用該端口號來與客戶端進(jìn)行數(shù)據(jù)傳輸??蛻舳颂捉幼值碾S機(jī)端口號一般是在1024到65535之間的一個(gè)空閑端口號,這樣可以避免與其他已知端口號沖突。
如果客戶端綁定了某個(gè)端口號,那么以后這個(gè)端口號就只能給這一個(gè)客戶端使用,就是這個(gè)客戶端沒有啟動,這個(gè)端口號也無法分配給別人,并且如果這個(gè)端口號被別人使用了,那么這個(gè)客戶端就無法啟動了。所以客戶端的端口只要保證唯一性就行了,因此客戶端端口可以動態(tài)的進(jìn)行設(shè)置,并且客戶端的端口號不需要我們來設(shè)置,當(dāng)我們調(diào)用類似于sendto這樣的接口時(shí),操作系統(tǒng)會自動給當(dāng)前客戶端獲取一個(gè)唯一的端口號。
也就是說,客戶端每次啟動時(shí)使用的端口號可能是變化的,此時(shí)只要我們的端口號沒有被耗盡,客戶端就永遠(yuǎn)可以啟動。

#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include<unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>class udpclient
{
public:udpclient(std::string server_ip,int server_port):_sockfd(-1),_server_port(server_port),_server_ip(server_ip){}bool Initclient(){//創(chuàng)建套接字_sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET//表示要進(jìn)行網(wǎng)絡(luò)通信,SOCK_DGRAM  UDP協(xié)議if(_sockfd<0){//表示創(chuàng)建套接字失敗std::cout<<" socket error";return false;}return true;}udpclient(){if(_sockfd>0){close(_sockfd);//關(guān)閉文件描述符}}private:int _sockfd;//文件描述符int _server_port;//服務(wù)端端口號std::string _server_ip;//服務(wù)端的IP地址
};

當(dāng)客戶端與服務(wù)端進(jìn)行綁定后接下來就是要向?qū)Ψ桨l(fā)送消息進(jìn)行通信了。

UDP通信中的sendto函數(shù)用于向指定的IP地址和端口號發(fā)送數(shù)據(jù)報(bào)。該函數(shù)的調(diào)用格式如下:

int sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

參數(shù)說明:

  • sockfd:要發(fā)送數(shù)據(jù)的套接字文件描述符。
  • buf:待發(fā)送的數(shù)據(jù)指針。
  • len:待發(fā)送的數(shù)據(jù)長度。
  • flags:發(fā)送標(biāo)志,一般為0。
  • dest_addr:指向目的地址結(jié)構(gòu)體的指針,需要將IP地址和端口號分別填入該結(jié)構(gòu)體的sin_addr和sin_port成員中。
  • addrlen:目的地址結(jié)構(gòu)體的長度。

調(diào)用sendto函數(shù)時(shí)需要填寫目的地址結(jié)構(gòu)體,例如:

struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = inet_addr(ip);

其中,port和ip分別為目的端口號和IP地址字符串。

sendto函數(shù)會將指定的數(shù)據(jù)報(bào)發(fā)送到指定的目的地址,如果發(fā)送成功返回發(fā)送的字節(jié)數(shù),如果失敗返回-1,并設(shè)置全局errno變量的值。由于UDP是無連接的,因此在發(fā)送數(shù)據(jù)時(shí)不需要建立連接。

UDP通信中的sendto函數(shù)用于向指定的IP地址和端口號發(fā)送數(shù)據(jù)報(bào)。該函數(shù)的調(diào)用格式如下:

int sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

參數(shù)說明:

  • sockfd:要發(fā)送數(shù)據(jù)的套接字文件描述符。
  • buf:待發(fā)送的數(shù)據(jù)指針。
  • len:待發(fā)送的數(shù)據(jù)長度。
  • flags:發(fā)送標(biāo)志,一般為0。
  • dest_addr:指向目的地址結(jié)構(gòu)體的指針,需要將IP地址和端口號分別填入該結(jié)構(gòu)體的sin_addr和sin_port成員中。
  • addrlen:目的地址結(jié)構(gòu)體的長度。

調(diào)用sendto函數(shù)時(shí)需要填寫目的地址結(jié)構(gòu)體,例如:

struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = inet_addr(ip);

其中,port和ip分別為目的端口號和IP地址字符串。

sendto函數(shù)會將指定的數(shù)據(jù)報(bào)發(fā)送到指定的目的地址,如果發(fā)送成功返回發(fā)送的字節(jié)數(shù),如果失敗返回-1,并設(shè)置全局errno變量的值。由于UDP是無連接的,因此在發(fā)送數(shù)據(jù)時(shí)不需要建立連接。

#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include<unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>class udpclient
{
public:udpclient(std::string server_ip,int server_port):_sockfd(-1),_server_port(server_port),_server_ip(server_ip){}bool Initclient(){//創(chuàng)建套接字_sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET//表示要進(jìn)行網(wǎng)絡(luò)通信,SOCK_DGRAM  UDP協(xié)議if(_sockfd<0){//表示創(chuàng)建套接字失敗std::cout<<" socket error";return false;}return true;}void Start(){std::string msg;struct sockaddr_in perr;memset(&perr,'\0',sizeof(perr));perr.sin_family=AF_INET;perr.sin_port=htons(_server_port);perr.sin_addr.s_addr=inet_addr(_server_ip.c_str());while(true){std::cout<<"Please Enter#";getline(std::cin,msg);sendto(_sockfd,msg.c_str(),msg.size(),0,(struct sockaddr*)&perr,sizeof(perr));//std::cout<<"sendto()  success"<<std::endl;}}udpclient(){if(_sockfd>0){close(_sockfd);//關(guān)閉文件描述符}}private:int _sockfd;//文件描述符int _server_port;//服務(wù)端端口號std::string _server_ip;//服務(wù)端的IP地址
};
#include"client.hpp"
int main(int argc,char*argv[])
{if(argc!=3){std::cout<<"usage:"<<argv[0]<<" port"<<std::endl;return 1;}std::string server_ip=argv[1];int server_port=atoi(argv[2]);udpclient* cli=new udpclient(server_ip,server_port);cli->Initclient();cli->Start();return 0;
}

http://m.risenshineclean.com/news/59855.html

相關(guān)文章:

  • wordpress 插件 論壇常州seo排名收費(fèi)
  • 建設(shè)手機(jī)網(wǎng)站的公司灰色seo推廣
  • 網(wǎng)站平臺建設(shè)的作用巨量算數(shù)數(shù)據(jù)分析
  • 安徽網(wǎng)站設(shè)計(jì)流程軟文發(fā)布平臺媒體
  • 找人做一個(gè)網(wǎng)站要多少錢百度推廣客戶端怎么登陸
  • 制作花燈百度刷排名優(yōu)化軟件
  • wap游戲縱橫四海優(yōu)化設(shè)計(jì)卷子答案
  • 做月季評分表的工程網(wǎng)站叫什么西安百度推廣開戶多少錢
  • 室內(nèi)設(shè)計(jì)軟件手機(jī)版semseo是什么意思
  • 中國住房和城鄉(xiāng)建設(shè)部網(wǎng)站安全seo優(yōu)化排名軟件
  • 鞋圖相冊網(wǎng)站怎么做seo網(wǎng)站優(yōu)化網(wǎng)站編輯招聘
  • 建設(shè)彩票網(wǎng)站犯法嗎seo網(wǎng)站排名優(yōu)化公司哪家好
  • 推廣引流文案鄭州網(wǎng)站優(yōu)化外包
  • 知名做漫畫網(wǎng)站百度官網(wǎng)進(jìn)入
  • 南通市住房城鄉(xiāng)建設(shè)局網(wǎng)站百度服務(wù)中心人工24小時(shí)電話
  • 做網(wǎng)站公司漢獅團(tuán)隊(duì)google play三件套
  • 知名網(wǎng)站建設(shè)多少錢排名優(yōu)化工具下載
  • 網(wǎng)頁的定義seo推廣軟件排行榜
  • 網(wǎng)站備案 身份證廣州seo成功案例
  • 福鼎建設(shè)局網(wǎng)站首頁最簡單的網(wǎng)頁制作
  • 網(wǎng)站怎么做微信登錄四川網(wǎng)站制作
  • 網(wǎng)站建設(shè)南京關(guān)鍵詞seo價(jià)格
  • 桃江縣建設(shè)局網(wǎng)站凱里seo排名優(yōu)化
  • 什么網(wǎng)站做電腦系統(tǒng)好免費(fèi)網(wǎng)絡(luò)推廣軟件
  • 做農(nóng)業(yè)種子的網(wǎng)站湖南網(wǎng)站建設(shè)效果
  • 桑拿網(wǎng)站橫幅廣告怎么做seo工資多少
  • 西安網(wǎng)站制作怎么做網(wǎng)站推廣
  • 建設(shè)網(wǎng)站找哪里怎么分析一個(gè)網(wǎng)站seo
  • 中國網(wǎng)站模板免費(fèi)下載廣東整治互聯(lián)網(wǎng)霸王條款
  • 做盜版系統(tǒng)網(wǎng)站會不會百度識圖掃一掃