




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Socket網(wǎng)絡(luò)開發(fā)目標(biāo)什么是套接字?Internet套接字的兩種類型網(wǎng)絡(luò)理論IP地址和如何處理它們使用Socket開發(fā)網(wǎng)絡(luò)程序什么是socket?所謂socket通常也稱作“套接字”,用于描述IP地址和端口,是一個(gè)通信鏈的句柄。應(yīng)用程序通常通過(guò)“套接字”向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。生成套接字,主要有3個(gè)參數(shù):通信的目的IP地址、使用的傳輸層協(xié)議(TCP或UDP)和使用的端口號(hào)。Socket原意是“插座”。通過(guò)將這3個(gè)參數(shù)結(jié)合起來(lái),與一個(gè)“插座”Socket綁定,應(yīng)用層就可以和傳輸層通過(guò)套接字接口,區(qū)分來(lái)自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。Socket可以看成在兩個(gè)程序進(jìn)行通訊連接中的一個(gè)端點(diǎn),一個(gè)程序?qū)⒁欢涡畔懭隨ocket中,該Socket將這段信息發(fā)送給另外一個(gè)Socket中,使這段信息能傳送到其他程序中。
套接字的兩種類型一種是“StreamSockets”(流格式),另外一種是“DatagramSockets”(數(shù)據(jù)包格式)。我們以后談到它們的時(shí)候也會(huì)用到SOCK_STREAM和SOCK_DGRAM。數(shù)據(jù)報(bào)套接字有時(shí)也叫“無(wú)連接套接字”(如果你確實(shí)要連接的時(shí)候可以用connect()。)流式套接字是可靠的雙向通訊的數(shù)據(jù)流。如果你向套接字按順序輸出“1,2”,那么它們將按順序“1,2”到達(dá)另一邊。它們是無(wú)錯(cuò)誤的傳遞的,除非自己的控制錯(cuò)誤。例如:telnet、及ftp等都是使用流格式,這是因?yàn)樗褂昧恕皞鬏斂刂茀f(xié)議(TheTransmissionControlProtocol)”。流式套接字可以達(dá)到高質(zhì)量的數(shù)據(jù)傳輸。網(wǎng)絡(luò)理論網(wǎng)絡(luò)分層模型(LayeredNetworkModel)?,F(xiàn)在列出整個(gè)層次模型。如果你要參加網(wǎng)絡(luò)考試,可一定要記?。?/p>
應(yīng)用層(Application)
表示層(Presentation)
會(huì)話層(Session)
傳輸層(Transport)
網(wǎng)絡(luò)層(Network)
數(shù)據(jù)鏈路層(DataLink)
物理層(Physical)
物理層是硬件(串口,以太網(wǎng)等等)。應(yīng)用層是和硬件層相隔最遠(yuǎn)的--它是用戶和網(wǎng)絡(luò)交互的地方。
這個(gè)模型如此通用,如果你想,你可以把它作為修車指南。把它對(duì)應(yīng)到Unix,結(jié)果是:
應(yīng)用層(ApplicationLayer)(telnet,ftp,等等)
傳輸層(Host-to-HostTransportLayer)(TCP,UDP)
Internet層(InternetLayer)(IP和路由)
網(wǎng)絡(luò)訪問(wèn)層(NetworkAccessLayer)
(網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層和物理層)
網(wǎng)絡(luò)數(shù)據(jù)排列有兩種字節(jié)排列順序:重要的字節(jié)(有時(shí)叫“octet”,即八位位組)在前面,或者不重要的字節(jié)在前面。前一種叫“網(wǎng)絡(luò)字節(jié)順序(NetworkByteOrder)”。有些機(jī)器在內(nèi)部是按照這個(gè)順序儲(chǔ)存數(shù)據(jù),而另外一些則不然。當(dāng)我說(shuō)某數(shù)據(jù)必須按照NBO順序,那么你要調(diào)用函數(shù)(例如htons())來(lái)將它從本機(jī)字節(jié)順序(HostByteOrder)轉(zhuǎn)換過(guò)來(lái)。如果我沒有提到NBO,那么就讓它保持本機(jī)字節(jié)順序。
Socket數(shù)據(jù)類型socket描述符:僅僅是一個(gè)常見的int。套接字地址信息structsockaddr{
unsignedshortsa_family;/*地址家族,AF_xxx*/
charsa_data[14];/*14字節(jié)協(xié)議地址*/
};
sa_family能夠是各種各樣的類型,但是在這篇文章中都是"AF_INET"。sa_data包含套接字中的目標(biāo)地址和端口信息。為了處理structsockaddr,程序員創(chuàng)造了一個(gè)并列的結(jié)構(gòu):structsockaddr_in("in"代表"Internet"。)
structsockaddr_in{
shortintsin_family;/*通信類型*/
unsignedshortintsin_port;/*端口*/
structin_addrsin_addr;/*Internet地址*/
unsignedcharsin_zero[8];/*與sockaddr結(jié)構(gòu)的長(zhǎng)度相同*/};
IP地址如何處理假設(shè)你已經(jīng)有了一個(gè)sockaddr_in結(jié)構(gòu)體ina,你有一個(gè)IP地址"0"要儲(chǔ)存在其中,你就要用到函數(shù)inet_addr(),將IP地址從點(diǎn)數(shù)格式轉(zhuǎn)換成無(wú)符號(hào)長(zhǎng)整型。使用方法如下:
ina.sin_addr.s_addr=inet_addr("");
好了,現(xiàn)在你可以將IP地址轉(zhuǎn)換成長(zhǎng)整型了。有沒有其相反的方法呢?它可以將一個(gè)in_addr結(jié)構(gòu)體輸出成點(diǎn)數(shù)格式?這樣的話,你就要用到函數(shù)inet_ntoa()("ntoa"的含義是"networktoascii"),就像這樣:
printf("%s",inet_ntoa(ina.sin_addr));
socket()函數(shù)Windows包含文件:
#include<WinSock2.h>
intsocket(intdomain,inttype,intprotocol);domain應(yīng)該設(shè)置成“AF_INET”,就象上面的數(shù)據(jù)結(jié)構(gòu)structsockaddr_in中一樣。參數(shù)type告訴內(nèi)核是SOCK_STREAM類型還是SOCK_DGRAM類型。把protocol設(shè)置為“0”。(注意:有很多種domain、type,我不一一列出了,請(qǐng)看socket()的幫助。socket()只是返回你以后在系統(tǒng)調(diào)用種可能用到的socket描述符,或者在錯(cuò)誤的時(shí)候返回-1。使用WSAGetLastError()可以查看錯(cuò)誤原因。bind()函數(shù)一旦你有一個(gè)套接字,你可能要將套接字和機(jī)器上的一定的端口關(guān)聯(lián)起來(lái)。intbind(intsockfd,structsockaddr*my_addr,intaddrlen);sockfd是調(diào)用socket返回的文件描述符。my_addr是指向數(shù)據(jù)結(jié)構(gòu)structsockaddr的指針,它保存你的地址(即端口和IP地址)信息。my_addr.sin_port是網(wǎng)絡(luò)字節(jié)順序,addrlen設(shè)置為sizeof(structsockaddr)。在處理自己的IP地址和/或端口的時(shí)候,有些工作是可以自動(dòng)處理的。
my_addr.sin_port=0;/*隨機(jī)選擇一個(gè)沒有使用的端口*/
my_addr.sin_addr.s_addr=INADDR_ANY;/*使用自己的IP地址*/
通過(guò)將0賦給my_addr.sin_port,你告訴bind()自己選擇合適的端口。同樣,將my_addr.sin_addr.s_addr設(shè)置為INADDR_ANY,你告訴它自動(dòng)填上它所運(yùn)行的機(jī)器的IP地址。簡(jiǎn)單得很不是嗎?再看看例子:bind()函數(shù)bind()在錯(cuò)誤的時(shí)候依然是返回-1,并且使用WSAGetLastError()取錯(cuò)。在你調(diào)用bind()的時(shí)候,你要小心的另一件事情是:不要采用小于1024的端口號(hào)。所有小于1024的端口號(hào)都被系統(tǒng)保留!你可以選擇從1024到65535的端口(如果它們沒有被別的程序使用的話)。你要注意的另外一件小事是:有時(shí)候你根本不需要調(diào)用它。如果你使用connect()來(lái)和遠(yuǎn)程機(jī)器進(jìn)行通訊,你不需要關(guān)心你的本地端口號(hào)(就象你在使用telnet的時(shí)候),你只要簡(jiǎn)單的調(diào)用connect()就可以了,它會(huì)檢查套接字是否綁定端口,如果沒有,它會(huì)自己綁定一個(gè)沒有使用的本地端口。connect()函數(shù)connect()程序
現(xiàn)在我們假設(shè)你是個(gè)telnet程序。你的用戶命令你得到套接字的文件描述符。你聽從命令調(diào)用了socket()。下一步,你的用戶告訴你通過(guò)端口23(標(biāo)準(zhǔn)telnet端口)連接到"0"。你該怎么做呢?幸運(yùn)的是,你正在閱讀connect()--如何連接到遠(yuǎn)程主機(jī)這一章。你可不想讓你的用戶失望。
connect()系統(tǒng)調(diào)用是這樣的:
intconnect(intsockfd,structsockaddr*serv_addr,intaddrlen);sockfd是系統(tǒng)調(diào)用socket()返回的套接字文件描述符。serv_addr是保存著目的地端口和IP地址的數(shù)據(jù)結(jié)構(gòu)structsockaddr。addrlen設(shè)置為sizeof(structsockaddr)。想知道得更多嗎?讓我們來(lái)看個(gè)例子:之后,你應(yīng)該檢查connect()的返回值--它在錯(cuò)誤的時(shí)候返回-1,并通過(guò)WSAGetLastError()取錯(cuò)。
同時(shí),你可能看到,我沒有調(diào)用bind()。因?yàn)槲也辉诤醣镜氐亩丝谔?hào)。我只關(guān)心我要去那。內(nèi)核將為我選擇一個(gè)合適的端口號(hào),而我們所連接的地方也自動(dòng)地獲得這些信息。一切都不用擔(dān)心。listen()函數(shù)是換換內(nèi)容得時(shí)候了。假如你不希望與遠(yuǎn)程的一個(gè)地址相連,或者說(shuō),僅僅是將它踢開,那你就需要等待接入請(qǐng)求并且用各種方法處理它們。處理過(guò)程分兩步:首先,你聽--listen(),然后,你接受--accept()(請(qǐng)看下面的內(nèi)容)。
除了要一點(diǎn)解釋外,系統(tǒng)調(diào)用listen也相當(dāng)簡(jiǎn)單。
intlisten(intsockfd,intbacklog);
sockfd是調(diào)用socket()返回的套接字文件描述符。backlog是在進(jìn)入隊(duì)列中允許的連接數(shù)目。什么意思呢?進(jìn)入的連接是在隊(duì)列中一直等待直到你接受(accept()請(qǐng)看下面的文章)連接。它們的數(shù)目限制于隊(duì)列的允許。大多數(shù)系統(tǒng)的允許數(shù)目是20,你也可以設(shè)置為5到10。和別的函數(shù)一樣,在發(fā)生錯(cuò)誤的時(shí)候返回-1,并通過(guò)WSAGetLastError()取錯(cuò)。
你可能想象到了,在你調(diào)用listen()前你或者要調(diào)用bind()或者讓內(nèi)核隨便選擇一個(gè)端口。如果你想偵聽進(jìn)入的連接,那么系統(tǒng)調(diào)用的順序可能是這樣的:
socket();
bind();
listen();
accept()函數(shù)準(zhǔn)備好了,系統(tǒng)調(diào)用accept()會(huì)有點(diǎn)古怪的地方的!你可以想象發(fā)生這樣的事情:有人從很遠(yuǎn)的地方通過(guò)一個(gè)你在偵聽(listen())的端口連接(connect())到你的機(jī)器。它的連接將加入到等待接受(accept())的隊(duì)列中。你調(diào)用accept()告訴它你有空閑的連接。它將返回一個(gè)新的套接字文件描述符!這樣你就有兩個(gè)套接字了,原來(lái)的一個(gè)還在偵聽你的那個(gè)端口,新的在準(zhǔn)備發(fā)送(send())和接收(recv())數(shù)據(jù)。這就是這個(gè)過(guò)程!
intaccept(intsockfd,void*addr,int*addrlen);
sockfd相當(dāng)簡(jiǎn)單,是和listen()中一樣的套接字描述符。addr是個(gè)指向局部的數(shù)據(jù)結(jié)構(gòu)sockaddr_in的指針。這是要求接入的信息所要去的地方(你可以測(cè)定那個(gè)地址在那個(gè)端口呼叫你)。在它的地址傳遞給accept之前,addrlen是個(gè)局部的整形變量,設(shè)置為sizeof(structsockaddr_in)。accept將不會(huì)將多余的字節(jié)給addr。如果你放入的少些,那么它會(huì)通過(guò)改
變addrlen的值反映出來(lái)。同樣,在錯(cuò)誤時(shí)返回-1,并通過(guò)WSAGetLastError()取錯(cuò)。
現(xiàn)在是你應(yīng)該熟悉的代碼片段。注意,在系統(tǒng)調(diào)用send()和recv()中你應(yīng)該使用新的套接字描述符new_fd。如果你只想讓一個(gè)連接進(jìn)來(lái),那么你可以使用close()去關(guān)閉原來(lái)的文件描述符sockfd來(lái)避免同一個(gè)端口更多的連接。send()andrecv()函數(shù)這兩個(gè)函數(shù)用于流式套接字或者數(shù)據(jù)報(bào)套接字的通訊。如果你喜歡使用無(wú)連接的數(shù)據(jù)報(bào)套接字,你應(yīng)該看一看下面關(guān)于sendto()和recvfrom()的章節(jié)。
send()是這樣的:
intsend(intsockfd,constvoid*msg,intlen,intflags);
sockfd是你想發(fā)送數(shù)據(jù)的套接字描述符(或者是調(diào)用socket()或者是accept()返回的。)msg是指向你想發(fā)送的數(shù)據(jù)的指針。len是數(shù)據(jù)的長(zhǎng)度。把flags設(shè)置為0就可以了。(詳細(xì)的資料請(qǐng)看send()的manpage)。
這里是一些可能的例子:
char*msg="Beejwashere!";
intlen,bytes_sent;
.
.
len=strlen(msg);
bytes_sent=send(sockfd,msg,len,0);
send()andrecv()函數(shù)send()返回實(shí)際發(fā)送的數(shù)據(jù)的字節(jié)數(shù)--它可能小于你要求發(fā)送的數(shù)目!注意,有時(shí)候你告訴它要發(fā)送一堆數(shù)據(jù)可是它不能處理成功。它只是發(fā)送它可能發(fā)送的數(shù)據(jù),然后希望你能夠發(fā)送其它的數(shù)據(jù)。記住,如果send()返回的數(shù)據(jù)和len不匹配,你就應(yīng)該發(fā)送其它的數(shù)據(jù)。但是這里也有個(gè)好消息:如果你要發(fā)送的包很小(小于大約1K),它可能處理讓數(shù)據(jù)一次發(fā)送完。它在錯(cuò)誤的時(shí)候返回-1,并通過(guò)WSAGetLastError()取錯(cuò)。recv()函數(shù)很相似:
intrecv(intsockfd,void*buf,intlen,unsignedintflags);
sockfd是要讀的套接字描述符。buf是要讀的信息的緩沖。len是緩沖的最大長(zhǎng)度。flags可以設(shè)置為0。(請(qǐng)參考recv()的manpage。)recv()返回實(shí)際讀入緩沖的數(shù)據(jù)的字節(jié)數(shù)。或者在錯(cuò)誤的時(shí)候返回-1,并通過(guò)WSAGetLastError()取錯(cuò)。
很簡(jiǎn)單,不是嗎?你現(xiàn)在可以在流式套接字上發(fā)送數(shù)據(jù)和接收數(shù)據(jù)了。close()和shutdown()函數(shù)你已經(jīng)整天都在發(fā)送(send())和接收(recv())數(shù)據(jù)了,現(xiàn)在你準(zhǔn)備關(guān)閉你的套接字描述符了。這很簡(jiǎn)單,你可以使用一般的Unix文件描述符的close()函數(shù):
close(sockfd);
它將防止套接字上更多的數(shù)據(jù)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 教育數(shù)字化轉(zhuǎn)型中的技術(shù)挑戰(zhàn)與機(jī)遇
- 智慧城市環(huán)保監(jiān)測(cè)網(wǎng)絡(luò)教育普及的必要性
- 商業(yè)培訓(xùn)中的心理教育培養(yǎng)高績(jī)效員工
- 輸尿管鏡術(shù)后護(hù)理查房
- 教育技術(shù)創(chuàng)新對(duì)未來(lái)社會(huì)的推動(dòng)作用
- 煙酒招牌更換方案簡(jiǎn)單
- 社區(qū)養(yǎng)老資金監(jiān)管方案
- 惡性腫瘤的多學(xué)科治療
- 心內(nèi)科常見癥狀診療要點(diǎn)
- 蓋縣老房改造方案
- 2025年中國(guó)安全閥行業(yè)市場(chǎng)專項(xiàng)調(diào)研及投資前景可行性預(yù)測(cè)報(bào)告
- 2024年金華東陽(yáng)市人民醫(yī)院招聘筆試真題
- 方劑歌訣(廣中醫(yī)版)
- 藥物過(guò)敏的急救與處理流程
- 天翼云筆試題目及答案
- 數(shù)據(jù)知識(shí)產(chǎn)權(quán)培訓(xùn)課件
- 青年教師培養(yǎng)與發(fā)展指南
- 煉鋼廠中壓氮?dú)?、氧氣吹掃安全方?副本
- 某型水下目標(biāo)模擬器高功率密度驅(qū)動(dòng)技術(shù)研究
- 四新安全教育培訓(xùn)
- 弱電工程項(xiàng)目團(tuán)隊(duì)職責(zé)與績(jī)效考核
評(píng)論
0/150
提交評(píng)論