socket();創(chuàng)建一個(gè)套接字
當(dāng)前正在學(xué)習(xí)的網(wǎng)絡(luò)編程是基于linux系統(tǒng)的C++網(wǎng)絡(luò)編程,上面是在linux下的socket定義
輸入:
domain:翻譯為域,這里就是制定為套接字選擇的地址協(xié)議周循,常見的有IPV4植兰、IPV6等
AF_INET IPv4 Internet protocols
AF_INET6 IPv6 Internet protocols
AF_UNIX Local communication
(linux翻譯)domain參數(shù)指定通信域;這將選擇用于通信的協(xié)議族。
type:創(chuàng)建套接字選擇的數(shù)據(jù)傳輸協(xié)議蟹肘,常見的有SOCK_STREAM數(shù)據(jù)流協(xié)議词疼、SOCK_DGRAM數(shù)據(jù)報(bào)協(xié)議,一種是基于TCP協(xié)議帘腹,一種基于UDP協(xié)議
(linux)套接字具有指定的類型贰盗,該類型指定通信語(yǔ)義。當(dāng)前定義的類型有:
SOCK_STREAM提供有序的阳欲、可靠的舵盈、雙向的、基于連接的字節(jié)流球化。帶外數(shù)據(jù)傳輸機(jī)制可以被支持秽晚。
SOCK_DGRAM支持?jǐn)?shù)據(jù)報(bào)(無連接,固定最大長(zhǎng)度的不可靠消息)筒愚。
protocol:協(xié)議類型赴蝇,這個(gè)我也說不太清楚,一般默認(rèn)為0即可
(linux)協(xié)議指定套接字要使用的特定協(xié)議巢掺。通常只存在一個(gè)單獨(dú)的協(xié)議來支持一個(gè)部分
指定協(xié)議族中的Ular套接字類型句伶,在這種情況下,protocol可以指定為0陆淀。然而考余,有可能很多
協(xié)議可能存在,在這種情況下倔约,必須以這種方式指定特定的協(xié)議秃殉。使用的協(xié)議號(hào)是特定的
“交流領(lǐng)域”,交流將在其中發(fā)生;看到協(xié)議(5)。如何映射協(xié)議名請(qǐng)參見getprotoent(3)
協(xié)議號(hào)的字符串钾军。
返回值:等下來補(bǔ)充
示例:
#include <sys/types.h> /* See NOTES */
?#include <sys/socket.h>
socket(AF_INET,SOCK_STREAM,0);
bind();給套接字綁定一個(gè)名稱鳄袍,根據(jù)里面要傳遞的參數(shù),其實(shí)就是給套接字綁定一個(gè)地址吏恭,這里后面等下會(huì)具體來說
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
};
sockfd:socket函數(shù)的返回值
const struct sockaddr *addr:要說起這個(gè)函數(shù)拗小,可能需要提到一個(gè)概念性的問題。
上面是sockaddr的結(jié)構(gòu)樱哼,因此為了傳入有效的參數(shù)哀九,我們需要去給參數(shù)進(jìn)行賦值。
struce sockaddr_in addr;//初始化sockaddr,其實(shí)就是將sockaddr_in的結(jié)構(gòu)用于sockaddr搅幅,具體原因我后面也會(huì)補(bǔ)充
addr.sin_family=AF_INET;
addr.sin_port=htons(8888);
addr.sin_addr.s_addr=htonl(INADDR_ANY);//默認(rèn)寫法
addr:&addr
addrlen:地址結(jié)構(gòu)的大小阅束,sizeof(addr)
這里時(shí)間不是很夠,后面我會(huì)根據(jù)我的理解給出上面一些參數(shù)的原因茄唐,總的來說息裸,參數(shù)的選擇是跟套接字創(chuàng)建的時(shí)候的參數(shù)某種程度上面保持了一致性。
Linux:
下面是linux系統(tǒng)中沪编,在創(chuàng)建套接字的過程中呼盆,使用了AF_UNIX,所以my_addr.sun_family = AF_UNIX;我的理解是這些部分是有一些聯(lián)系的,而且在使用AF_UNIX之后蚁廓,并不需要使用sockaddr_in
暫時(shí)說說我的理解(還沒有去證實(shí))sockaddr_in,用于IPV4通信
sockaddr_in6很顯然访圃,用于IPV6的通信
(一些其他的觀點(diǎn)等待去驗(yàn)證)
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un my_addr, peer_addr;
my_addr.sun_family = AF_UNIX;
if (bind(sfd, (struct sockaddr *) &my_addr,
? ? ? ? ? ? ? ? ? sizeof(my_addr)) == -1)
? ? ? ? ? ? ? handle_error("bind");
返回值:On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
成功返回0,不成功返回-1相嵌,如果有錯(cuò)誤就返回錯(cuò)誤
示例:
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htonl(8888)
addr.sin_addr.s_addr=htonl(INADDR_ANY)
int sfd;
sfd=socket(.......);
bind(sfd,(struct sockaddr*)&addr,sizeof(addr);
listen();listen - listen for connections on a socket腿时,設(shè)置與套接字連接的服務(wù)器的上限數(shù)值(同時(shí)與服務(wù)器進(jìn)行3次握手的客戶端數(shù)量)
sockfd:sockfd參數(shù)是一個(gè)文件描述符,引用SOCK_STREAM或SOCK_SEQPACKET類型的套接字饭宾。
這里的sockfd與bind()函數(shù)中的sockfd相同圈匆,都是socket();函數(shù)的返回值
backlog:backlog參數(shù)定義了sockfd的掛起連接隊(duì)列可以增長(zhǎng)到的最大長(zhǎng)度。上限數(shù)值捏雌,最大128
返回值:On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
成功返回0
示例:
int cfd;
struct sockaddr_in addr;
addr.sin_famliy=AF_INET;
addr.sin_port=htonl(8888);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
cdf=socket(AF_INET,SOCK_STREAM,0);
accept(); accept a connection on a socket 阻塞客戶端建立連接,成功的話笆搓,返回一個(gè)與客戶端成功建立連接的套接字
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept()系統(tǒng)調(diào)用用于基于連接的套接字類型(SOCK_STREAM, SOCK_SEQPACKET)性湿。它提取掛起連接隊(duì)列上的第一個(gè)連接請(qǐng)求。監(jiān)聽套接字sockfd創(chuàng)建一個(gè)新的已連接套接字满败,并返回一個(gè)引用該套接字的新文件描述符肤频。創(chuàng)建的套接字不在監(jiān)聽狀態(tài)。原始套接字sockfd不受此調(diào)用的影響算墨。參數(shù)sockfd是一個(gè)用socket(2)創(chuàng)建的套接字宵荒,用bind(2)綁定到本地地址,在listen(2)之后監(jiān)聽連接。
sockfd:套接字的返回值报咳,準(zhǔn)確的來說是服務(wù)器端通過調(diào)用正確調(diào)用socket -> bind -> listen 函數(shù)之后的用于指向存放多個(gè)客戶端緩沖隊(duì)列緩沖區(qū)的套接字描述符
*addr:是用來保存客戶端套接字對(duì)應(yīng)的內(nèi)存空間變量(包括客戶端IP和端口信息等)
*addrlen:第二個(gè)參數(shù)的大小
addr是一個(gè)傳出參數(shù)侠讯,
示例:
connect();在一個(gè)套接字上面創(chuàng)建連接
connect()系統(tǒng)調(diào)用將文件描述符sockfd引用的套接字連接到由addr指定的地址。參數(shù)addrlen指定了addr的大小暑刃。addr中的地址格式由套接字sockfd的地址空間決定;詳見socket(2)厢漩。如果套接字sockfd類型為SOCK_DGRAM,則addr是缺省情況下發(fā)送數(shù)據(jù)報(bào)的地址岩臣,也是接收數(shù)據(jù)報(bào)的唯一地址溜嗜。如果socket類型為SOCK_STREAM或SOCK_SEQPACKET,則該調(diào)用嘗試建立到綁定到addr指定地址的套接字的連接架谎。一些協(xié)議套接字(例如UNIX域流套接字)可能只能成功地連接()一次炸宵。一些協(xié)議套接字(例如UNIX和Internet域中的數(shù)據(jù)報(bào)套接字)可能多次使用connect()來更改它們的關(guān)聯(lián)。一些協(xié)議套接字(例如谷扣,TCP套接字以及UNIX和Internet域中的數(shù)據(jù)報(bào)套接字)可以通過連接到帶有的地址來解除關(guān)聯(lián)sockaddr的sa_family成員設(shè)置為AF_UNSPEC;此后土全,套接字可以連接到另一個(gè)地址。(AF_UNSPEC自內(nèi)核2.2起在Linux上得到支持抑钟。)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:產(chǎn)生的套接字參數(shù)
*addr:傳入?yún)?shù)涯曲,指定服務(wù)器端地址信息,含IP地址和端口號(hào)
addrlen:第二個(gè)參數(shù)的長(zhǎng)度
到這里在塔,基本的通信所用到的函數(shù)就介紹完畢了幻件,這兩天也找了很多資料,但是始終很難有一個(gè)茅塞頓開的醒悟蛔溃,所以就先暫時(shí)到這吧绰沥,后面繼續(xù)學(xué)習(xí),有了感悟贺待,我會(huì)再后面重新再寫一遍函數(shù)的介紹徽曲,總的來說,對(duì)于accept麸塞、socket等函數(shù)印象很深刻秃臣,但是對(duì)于connect以及bind還是有點(diǎn)模糊的概念,因?yàn)槲掖_實(shí)也沒搞定哪工,某些參數(shù)的由來奥此,雖然linux系統(tǒng)下面提供了源碼,我也看了一些雁比,但是確實(shí)還是很難理解稚虎,但是我記得這里是一個(gè)疑點(diǎn),往后面學(xué)習(xí)偎捎,我還會(huì)回來的蠢终!
上次少更新的兩個(gè)函數(shù)序攘,在后面學(xué)習(xí)的過程中我才發(fā)現(xiàn),現(xiàn)在先來簡(jiǎn)單說一下啦
inet_pton();
說到最后這兩個(gè)函數(shù)寻拂,就要提到一些概念性的定義程奠,例如我們常見的IP:192.168.8.88,這是一個(gè)十進(jìn)制的網(wǎng)絡(luò)字節(jié)序兜喻,但是在我們計(jì)算機(jī)中的網(wǎng)絡(luò)字節(jié)序梦染,可不是這種,而是一種二進(jìn)制的網(wǎng)絡(luò)字節(jié)序朴皆。
網(wǎng)絡(luò)字節(jié)序:
類型:大端字節(jié)序帕识、小端字節(jié)序
大端:最高有效位存于最低內(nèi)存地址處,最低有效位存于最高內(nèi)存處遂铡;(低到高)
小端:最高有效位存于最高內(nèi)存地址肮疗,最低有效位存于最低內(nèi)存處。(高到低)
? ??
這里由于一些原因扒接,導(dǎo)致我們電腦本機(jī)使用的是小端字節(jié)序伪货,而在網(wǎng)絡(luò)中的數(shù)據(jù)傳輸使用的是大端字節(jié)序,因此在對(duì)數(shù)據(jù)進(jìn)行傳世時(shí)钾怔,需要進(jìn)行轉(zhuǎn)化碱呼。而現(xiàn)在也有著一些很合適的轉(zhuǎn)化函數(shù)
1.htons、htonl宗侦,解釋為Host to Network愚臀,從主機(jī)轉(zhuǎn)換到網(wǎng)路,也就是表明矾利,講字節(jié)序由小端轉(zhuǎn)化為大端姑裂,兩個(gè)函數(shù)的區(qū)別主要是返回值的長(zhǎng)短不同,s表示返回unsigned short int男旗,l表示返回unsigned int
2舶斧、ntohs、ntohl察皇,聽懂了上面的解釋茴厉,這兩個(gè)函數(shù)的意思就顯而易見了。Netword to Host什荣,網(wǎng)絡(luò)中的大端字節(jié)序轉(zhuǎn)化為Host中的小端字節(jié)序呀忧。
后面的s、l是同一個(gè)意思溃睹,只是返回的值部同
明白了網(wǎng)絡(luò)字節(jié)序,就明白了數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸基本都是二進(jìn)制形式的胰坟,但是我們還是會(huì)經(jīng)骋蚱看到ip 192.128.66.255 193.253.255.21等等這些ip泞辐,但是這些ip有一個(gè)共同的特點(diǎn),就是這些ip都使用了十進(jìn)制來表示竞滓,但是在機(jī)器語(yǔ)言中咐吼,傳遞的數(shù)據(jù)可能是這樣0000. 0125.2352.1563
所以這里牽扯到如何講ip轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序的,這個(gè)地方就是我們今天要說的函數(shù)商佑,inet_pton,inet_ntop,
兩個(gè)函數(shù)就是將網(wǎng)絡(luò)字節(jié)序和正常人類能看懂的進(jìn)行一個(gè)轉(zhuǎn)換锯茄,
1100.1200.1300.1400
所以在某些函數(shù)里面是需要使用十進(jìn)制二維碼,當(dāng)然也可以手動(dòng)轉(zhuǎn)換
為此茶没,這兩個(gè)函數(shù)起到十進(jìn)制和網(wǎng)絡(luò)字節(jié)序之間的轉(zhuǎn)換肌幽。