tcpip socket網(wǎng)絡(luò)編程_第1頁
tcpip socket網(wǎng)絡(luò)編程_第2頁
tcpip socket網(wǎng)絡(luò)編程_第3頁
tcpip socket網(wǎng)絡(luò)編程_第4頁
tcpip socket網(wǎng)絡(luò)編程_第5頁
已閱讀5頁,還剩79頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、TCP/IP Socket網(wǎng)絡(luò)編程Version: 2007-12-15赫衛(wèi)卿 2007-12-15 內(nèi)容大綱Internet與TCP/IP協(xié)議TCP/IP協(xié)議體系結(jié)構(gòu)與OSI模型Socket編程接口Windows SocketLinux SocketTCP/IP網(wǎng)絡(luò)程序框架與示例2022/7/192TCP/IP Socket網(wǎng)絡(luò)編程Internet與TCP/IP協(xié)議第一節(jié)Internet與TCP/IP協(xié)議2022/7/193TCP/IP Socket網(wǎng)絡(luò)編程Internet的歷史Internet“冷戰(zhàn)”的產(chǎn)物1957年10月和11月,前蘇聯(lián)先后有兩顆“Sp

2、utnik”衛(wèi)星上天1958年美國總統(tǒng)艾森豪威爾向美國國會提出建立DARPA (Defense Advanced Research Project Agency),即國防部高級研究計劃署,簡稱ARPA1968年6月DARPA提出“資源共享計算機(jī)網(wǎng)絡(luò)” (Resource Sharing Computer Networks),目的在于讓DARPA的所有電腦互連起來,這個網(wǎng)絡(luò)就叫做ARPAnet,即“阿帕網(wǎng)”,是Interne的最早雛形2022/7/194TCP/IP Socket網(wǎng)絡(luò)編程網(wǎng)絡(luò)互聯(lián)促成了TCP/IP協(xié)議的產(chǎn)生早期的ARPAnet使用網(wǎng)絡(luò)控制協(xié)議(Network Control Pr

3、otocol,NCP),不能互聯(lián)不同類型的計算機(jī)和不同類型的操作系統(tǒng),沒有糾錯功能1973年由Kahn和Vinton Cerf兩人合作為ARPAnet開發(fā)了新的互聯(lián)協(xié)議。1974年12月兩人正式發(fā)表第一份TCP協(xié)議詳細(xì)說明,但此協(xié)議有信包丟失時不能得到有效的糾正2022/7/195TCP/IP Socket網(wǎng)絡(luò)編程網(wǎng)絡(luò)互聯(lián)促成了TCP/IP協(xié)議的產(chǎn)生TCP協(xié)議分成了兩個不同的協(xié)議:用來檢測網(wǎng)絡(luò)傳輸中差錯的傳輸控制協(xié)議TCP專門負(fù)責(zé)對不同網(wǎng)絡(luò)進(jìn)行互聯(lián)的互聯(lián)網(wǎng)協(xié)議IP從此TCP/IP協(xié)議誕生1983年ARPAnet上停止使用NCP,互聯(lián)網(wǎng)上的主機(jī)全部使用TCP/IP協(xié)議,TCP/IP協(xié)議成為Int

4、ernet中的“世界語”2022/7/196TCP/IP Socket網(wǎng)絡(luò)編程Internet與TCP/IP協(xié)議第二節(jié)TCP/IP協(xié)議體系結(jié)構(gòu)與OSI模型2022/7/197TCP/IP Socket網(wǎng)絡(luò)編程網(wǎng)絡(luò)的體系結(jié)構(gòu)網(wǎng)絡(luò)采用分而治之的方法設(shè)計,將網(wǎng)絡(luò)的功能劃分為不同的模塊,以分層的形式有機(jī)組合在一起。每層實現(xiàn)不同的功能,其內(nèi)部實現(xiàn)方法對外部其他層次來說透明,每層向上層提供服務(wù),也可以使用下層提供的服務(wù)網(wǎng)絡(luò)體系結(jié)構(gòu)即指網(wǎng)絡(luò)的層次結(jié)構(gòu)和每層所使用協(xié)議的集合兩類非常重要的體系結(jié)構(gòu):OSI與TCP/IP2022/7/198TCP/IP Socket網(wǎng)絡(luò)編程OSI開放系統(tǒng)互聯(lián)模型OSI模型相關(guān)的協(xié)

5、議已經(jīng)很少使用,但模型本身非常通用共有七層2022/7/199TCP/IP Socket網(wǎng)絡(luò)編程TCP/IP協(xié)議族的體系結(jié)構(gòu)TCP/IP協(xié)議是Internet事實上的工業(yè)標(biāo)準(zhǔn)。一共有四層2022/7/1910TCP/IP Socket網(wǎng)絡(luò)編程TCP/IP協(xié)議與OSI參考模型的對應(yīng)關(guān)系2022/7/1911TCP/IP Socket網(wǎng)絡(luò)編程TCP/IP協(xié)議通信模型2022/7/1912TCP/IP Socket網(wǎng)絡(luò)編程數(shù)據(jù)的封裝與傳遞過程2022/7/1913TCP/IP Socket網(wǎng)絡(luò)編程一些基本概念I(lǐng)P地址端口號字節(jié)序2022/7/1914TCP/IP Socket網(wǎng)絡(luò)編程IP地址IP地址

6、是Internet中主機(jī)的標(biāo)識Internet中的主機(jī)要與別的機(jī)器通信必須具有一個IP地址一個IP地址為32位(IPV4),或者128位(IPV6)每個數(shù)據(jù)包都必須攜帶目的IP地址和源IP地址,路由器依靠此信息為數(shù)據(jù)包選擇路由特殊的IP地址:廣播地址、多播地址表示形式:常用點分形式,如0,最后都會轉(zhuǎn)換為一個32位的整數(shù)。IP地址分級子網(wǎng)掩碼2022/7/1915TCP/IP Socket網(wǎng)絡(luò)編程端口號為了區(qū)分一臺主機(jī)接收到的數(shù)據(jù)包應(yīng)該遞交給哪個進(jìn)程來進(jìn)行處理,使用端口號TCP端口號與UDP端口號獨立端口號一般由IANA (Internet Assigned Numbers

7、 Authority) 管理眾所周知端口:11023,1255之間為大部分眾所周知端口,2561023端口通常由UNIX占用注冊端口:102449151動態(tài)或私有端口:49151655352022/7/1916TCP/IP Socket網(wǎng)絡(luò)編程端到端通信數(shù)據(jù)包投遞過程2022/7/1917TCP/IP Socket網(wǎng)絡(luò)編程一個比喻如果把IP數(shù)據(jù)包的投遞過程看成是給遠(yuǎn)方的一位朋友寄一封信,那么IP地址就是這位朋友的所在位置,如安徽合肥中國科大計算系(依靠此信息進(jìn)行路由)端口號就是這位朋友的名字(依靠這個信息最終把這封信交付給這位收信者)2022/7/1918TCP/IP Socket網(wǎng)絡(luò)編程字節(jié)

8、序大尾端(Big-Endian):字節(jié)的高位在內(nèi)存中放在存儲單元的起始位置小尾端(Little-Endian):與大尾端相反2022/7/1919TCP/IP Socket網(wǎng)絡(luò)編程字節(jié)序網(wǎng)絡(luò)字節(jié)序(NBO,Network Byte Order)使用統(tǒng)一的字節(jié)順序,避免兼容性問題主機(jī)字節(jié)序(HBO,Host Byte Order)不同的機(jī)器HBO是不一樣的,這與CPU的設(shè)計有關(guān)Motorola 68K系列,HBO與NBO是一致的Intel X86系列,HBO與NBO不一致2022/7/1920TCP/IP Socket網(wǎng)絡(luò)編程Internet與TCP/IP協(xié)議第三節(jié)Socket編程接口2022/

9、7/1921TCP/IP Socket網(wǎng)絡(luò)編程內(nèi)容Socket簡介Windows SocketLinux SocketSocket常用函數(shù)介紹TCP/IP網(wǎng)絡(luò)程序框架與實例通信方式阻塞非阻塞2022/7/1922TCP/IP Socket網(wǎng)絡(luò)編程為什么需要Socket普通的I/O操作過程打開文件讀/寫操作關(guān)閉文件TCP/IP協(xié)議被集成到操作系統(tǒng)的內(nèi)核中,引入了新型的“I/O”操作進(jìn)行網(wǎng)絡(luò)操作的兩個進(jìn)程在不同的機(jī)器上,如何連接?網(wǎng)絡(luò)協(xié)議具有多樣性,如何進(jìn)行統(tǒng)一的操作需要一種通用的網(wǎng)絡(luò)編程接口:Socket2022/7/1923TCP/IP Socket網(wǎng)絡(luò)編程什么是Socket獨立于具體協(xié)議的網(wǎng)

10、絡(luò)編程接口在ISO模型中,主要位于會話層和傳輸層之間BSD Socket(伯克利套接字)是通過標(biāo)準(zhǔn)的UNIX文件描述符和其它程序通訊的一個方法,目前已經(jīng)被廣泛移植到各個平臺。2022/7/1924TCP/IP Socket網(wǎng)絡(luò)編程Socket類型流式套接字(SOCK_STREAM)提供了一個面向連接、可靠的數(shù)據(jù)傳輸服務(wù),數(shù)據(jù)無差錯、無重復(fù)的發(fā)送且按發(fā)送順序接收。內(nèi)設(shè)置流量控制,避免數(shù)據(jù)流淹沒慢的接收方。數(shù)據(jù)被看作是字節(jié)流,無長度限制。數(shù)據(jù)報套接字(SOCK_DGRAM)提供無連接服務(wù)。數(shù)據(jù)包以獨立數(shù)據(jù)包的形式被發(fā)送,不提供無差錯保證,數(shù)據(jù)可能丟失或重復(fù),順序發(fā)送,可能亂序接收。原始套接字(SO

11、CK_RAW)可以對較低層次協(xié)議,如IP、ICMP直接訪問。2022/7/1925TCP/IP Socket網(wǎng)絡(luò)編程Socket的位置2022/7/1926TCP/IP Socket網(wǎng)絡(luò)編程兩類系統(tǒng)中使用的Socket不同操作系統(tǒng)中的SocketWindows Socket (Winsock)Linux Socket (BSD Socket)2022/7/1927TCP/IP Socket網(wǎng)絡(luò)編程Windows Socket簡稱Winsock,是在Windows環(huán)境下使用的一套網(wǎng)絡(luò)編程規(guī)范,基于4.3BSD的BSD Socket API制定1991年Winsock 1.1,16位,由WINSO

12、CK.DLL支持,主要用在Windows 95中1997年Winsock 2.2 版,32位,由WSOCK32.DLL支持,主要用在Windows 98及以后的版本中已經(jīng)成為Windows環(huán)境下網(wǎng)絡(luò)編程的事實標(biāo)準(zhǔn)三類函數(shù)與BSD Socket相兼容的基本函數(shù)與BSD Socket相兼容的網(wǎng)絡(luò)信息檢索函數(shù)Windows專用擴(kuò)展函數(shù)2022/7/1928TCP/IP Socket網(wǎng)絡(luò)編程Linux Socket基本上就是BSD Socket需要使用的頭文件數(shù)據(jù)類型:#include 函數(shù)定義:#include 2022/7/1929TCP/IP Socket網(wǎng)絡(luò)編程Socket常用函數(shù)介紹基本函數(shù)

13、網(wǎng)絡(luò)信息檢索函數(shù)2022/7/1930TCP/IP Socket網(wǎng)絡(luò)編程基本函數(shù)網(wǎng)絡(luò)連接函數(shù)socket創(chuàng)建套接字bind綁定本機(jī)端口connect建立連接listen監(jiān)聽端口accept接受連接recv, recvfrom數(shù)據(jù)接收send, sendto數(shù)據(jù)發(fā)送close, shutdown關(guān)閉套接字2022/7/1931TCP/IP Socket網(wǎng)絡(luò)編程基本函數(shù)轉(zhuǎn)換函數(shù)IP地址轉(zhuǎn)換函數(shù)inet_addr()點分十進(jìn)制數(shù)表示的IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序的IP地址inet_ntoa()網(wǎng)絡(luò)字節(jié)序的IP地址轉(zhuǎn)換為點分十進(jìn)制數(shù)表示的IP地址字節(jié)排序函數(shù)htonl4字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序nto

14、hl 4字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序htons2字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序ntohs2字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序2022/7/1932TCP/IP Socket網(wǎng)絡(luò)編程網(wǎng)絡(luò)信息檢索函數(shù)網(wǎng)絡(luò)信息檢索函數(shù)gethostname獲得主機(jī)名getpeername獲得與套接口相連的遠(yuǎn)程協(xié)議地址getsockname獲得套接口本地協(xié)議地址gethostbyname根據(jù)主機(jī)名取得主機(jī)信息gethostbyaddr根據(jù)主機(jī)地址取得主機(jī)信息getprotobyname根據(jù)協(xié)議名取得主機(jī)協(xié)議信息getprotobynumber根據(jù)協(xié)議號取得主機(jī)協(xié)議信息getservbyname根據(jù)服務(wù)名取得相關(guān)服務(wù)信息

15、getservbyport根據(jù)端口號取得相關(guān)服務(wù)信息getsockopt/setsockopt獲取/設(shè)置一個套接口選項 ioctlsocket設(shè)置套接口的工作方式2022/7/1933TCP/IP Socket網(wǎng)絡(luò)編程Windows中的Socket編程Windows中的Socket編程Winsock 的啟動Winsock API基本函數(shù)TCP/IP網(wǎng)絡(luò)程序框架(C/S模式)阻塞與非阻塞通信方式實例程序說明2022/7/1934TCP/IP Socket網(wǎng)絡(luò)編程WinsockWinsock是一個基于Socket模型的API,在Windows系統(tǒng)中廣泛使用它在Berkeley接口函數(shù)的基礎(chǔ)上,還增

16、加了基于消息驅(qū)動機(jī)制的Windows擴(kuò)展函數(shù)Winsock1.1只支持TCP/IP網(wǎng)絡(luò),Winsock2.2增加了對更多協(xié)議的支持2022/7/1935TCP/IP Socket網(wǎng)絡(luò)編程Winsock(2)需要包含頭文件Winsock2.h,需要使用庫ws2_32.lib,包含辦法可以用語句來告訴編譯時調(diào)用該庫#pragma comment(lib,”ws2_32.lib”);如果使用Visual C+ 6.0,可以通過“工程” “設(shè)置”“工程設(shè)置”“鏈接”“對象/庫模塊”中加入“ws2_32.lib”2022/7/1936TCP/IP Socket網(wǎng)絡(luò)編程Windows Socket的啟動使

17、用Winsock API編制的網(wǎng)絡(luò)應(yīng)用程序中,在調(diào)用任何一個Winsock函數(shù)之前都必須檢查協(xié)議棧安裝情況,使用函數(shù)WSAStartup()完成操作。int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);wVersionRequested是一個WORD型(雙字節(jié)型)數(shù)值,指定使用的版本號,對Winsock2.2而言,此參數(shù)的值為0 x0202,也可以用宏MAKEWORD(2,2)來獲得lpWSAData是一個指向WSADATA結(jié)構(gòu)的指針,它返回關(guān)于Winsock實現(xiàn)的詳細(xì)信息2022/7/1937TCP/IP Socket網(wǎng)絡(luò)編程

18、Winsock啟動示例#include WORD wVersionRequested;WSADATA wsaData;wVersionRequested=MAKEWORD(2,2);if(WSAStartup(wVersionRequested,&wsaData)!=0)/Winsock初始化錯誤return;if(wsaData.wVersion!=wVersionRequested)/Winsock版本不匹配WSACleanup();return;/說明WinsockDLL正確加載,可以執(zhí)行以下代碼2022/7/1938TCP/IP Socket網(wǎng)絡(luò)編程創(chuàng)建套接口socket()應(yīng)用程序在

19、使用套接口通信前,必須要擁有一個套接口,使用socket()函數(shù)來給應(yīng)用程序創(chuàng)建一個套接口。SOCKET socket(int af,int type,int protocol);2022/7/1939TCP/IP Socket網(wǎng)絡(luò)編程socket()參數(shù)說明af參數(shù)說明套接字接口要使用的協(xié)議地址族,地址族與協(xié)議族含義相同。如果想建立一個TCP或UDP,只能用常量AF_INET表示使用互聯(lián)網(wǎng)協(xié)議(IP)地址。Winsock還支持其他協(xié)議,但一般很少使用。type參數(shù)描述套接口的類型,af是AF_INET的時候只能為SOCK_STREAM、SOCK_DGRAM或SOCK_RAWprotocol說

20、明該套接口使用的特定協(xié)議,當(dāng)協(xié)議地址族af和協(xié)議類型type確定后,協(xié)議字段可以使用的值是限定的協(xié)議地址族套接口類型套接口類型使用的值協(xié)議字段互聯(lián)網(wǎng)協(xié)議(IP)AF_INETTCPSOCK_STREAMIPPROTO_TCPUDPSOCK_DGRAMIPPROTO_UDPRawSOCK_RAWIPPROTO_RAWIPPROTO_ICMP2022/7/1940TCP/IP Socket網(wǎng)絡(luò)編程指定本地地址bind()當(dāng)socket()創(chuàng)建了一個套接口后,需要將該套接口與該主機(jī)上提供服務(wù)的某端口聯(lián)系在一起,bind()函數(shù)用于完成這樣的綁定。int bind(SOCKET s,const str

21、uct sockaddr FAR * name,int namelen);2022/7/1941TCP/IP Socket網(wǎng)絡(luò)編程bind()參數(shù)說明s標(biāo)識一個未綁定的套接口描述字,它是socket()函數(shù)調(diào)用成功時返回的值name是一個與指定協(xié)議有關(guān)的地址結(jié)構(gòu)指針,存儲了套接口的地址信息,Winsock中使用sockaddr_in結(jié)構(gòu)指定IP地址和端口信息struct sockaddr_inshort sin_family;u_short sin_port;struct in_addrsin_addr;charsin_zero8;sin_family一般為AF_INET,表示使用IP地址族;

22、sin_port是以網(wǎng)絡(luò)字節(jié)序表示的16位端口號;sin_addr是網(wǎng)絡(luò)字節(jié)序的32位IP地址;sin_zero字段一般不用,用0填充namelen表示地址參數(shù)(name)的長度IP地址參數(shù)為INADDR_ANY,則由系統(tǒng)內(nèi)核來自動指定,port為0,則由系統(tǒng)自動指派一個10245000之間惟一的端口號2022/7/1942TCP/IP Socket網(wǎng)絡(luò)編程bind()實例#include SOCKET s;sockaddr_in tcpaddr;int iSockErr;int port=5000; /端口號s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

23、tcpaddr.sin_family=AF_INET;tcpaddr.sin_port=htons(port);tcpaddr.sin_addr.s_addr=htonl(INADDR_ANY);if(bind(s,(LPSOCKADDR)&tcpaddr,sizeof(tcpaddr)=SOCKET_ERROR)iSockErr=WSAGetLastError();/根據(jù)不同的錯誤類型進(jìn)行不同的處理return;函數(shù)調(diào)用成功,進(jìn)行其他處理。2022/7/1943TCP/IP Socket網(wǎng)絡(luò)編程服務(wù)器端啟動監(jiān)聽listen()函數(shù)在一個服務(wù)器端用socket()調(diào)用成功創(chuàng)建了一個套接口,并用

24、bind()函數(shù)和一個指定的地址關(guān)聯(lián)后,就需要指示該套接口進(jìn)入監(jiān)聽連接請求狀態(tài),這需要通過listen()函數(shù)來實現(xiàn)int listen(SOCKET s,int backlog);s代表一個已綁定了地址,但還未建立連接的套接口描述字backlog指定了正在等待連接的最大隊列長度2022/7/1944TCP/IP Socket網(wǎng)絡(luò)編程客戶端請求連接connect()函數(shù)當(dāng)服務(wù)器端建立好套接口并與一個本地地址綁定后,就進(jìn)入監(jiān)聽狀態(tài),等待客戶發(fā)出連接請求。在客戶端套接口建立好之后,就調(diào)用connect()函數(shù)來與服務(wù)器建立連接。int connect(SOCKET s,const struct s

25、ockaddr FAR * name,int namelen);2022/7/1945TCP/IP Socket網(wǎng)絡(luò)編程connect()函數(shù)參數(shù)說明s將要建立連接的套接口描述字name是一個指向遠(yuǎn)端套接口地址結(jié)構(gòu)(sockaddr_in)的指針,表示s套接口欲與其建立一條連接namelen是服務(wù)器端的地址長度,即name的長度2022/7/1946TCP/IP Socket網(wǎng)絡(luò)編程Connect()函數(shù)的說明在客戶端使用該函數(shù)請求建立連接時,將激活建立連接的三次握手,用來建立一條到服務(wù)器TCP的連接。如果調(diào)用該函數(shù)前沒有調(diào)用bind()來綁定本地地址,則由系統(tǒng)隱式綁定一個地址到該套接口該函數(shù)

26、用在UDP的客戶端時,connect()函數(shù)并不是真正地發(fā)出建立請求連接的請求,調(diào)用將從本地操作系直接返回。這樣可以將服務(wù)器的地址信息保存下來,在后續(xù)UDP端口發(fā)送數(shù)據(jù)時,由套接口自動在發(fā)送函數(shù)中填入服務(wù)器地址,而不需要由應(yīng)用程序在調(diào)用發(fā)送函數(shù)時填入2022/7/1947TCP/IP Socket網(wǎng)絡(luò)編程服務(wù)器端接受連接accept()函數(shù)在服務(wù)器端通過listen()函數(shù)調(diào)用表示服務(wù)器進(jìn)入監(jiān)聽客戶的連接請求狀態(tài),而在服務(wù)器端調(diào)用accept()函數(shù)時表示可以接收來自客戶端由connect()發(fā)出的連接請求,雙方進(jìn)入連接狀態(tài)。SOCKET accept(SOCKET s,struct sock

27、addr FAR * addr,int FAR * addrlen);2022/7/1948TCP/IP Socket網(wǎng)絡(luò)編程accept()函數(shù)參數(shù)說明s標(biāo)識一個套接字,該套接口處于監(jiān)聽狀態(tài)addr是一個地址結(jié)構(gòu)的指針,用來存放發(fā)出連接請求的那個客戶機(jī)的IP地址信息addrlen指出客戶套接口地址結(jié)構(gòu)的長度函數(shù)說明:該函數(shù)用于面向連接的服務(wù)器端,在IP協(xié)議族中,只用于TCP服務(wù)器端2022/7/1949TCP/IP Socket網(wǎng)絡(luò)編程發(fā)送數(shù)據(jù)-send()函數(shù)在已經(jīng)建立連接的套接口上發(fā)送數(shù)據(jù),可以使用send()函數(shù)int send(SOCKET s,const char FAR * bu

28、f,int len,int flags);2022/7/1950TCP/IP Socket網(wǎng)絡(luò)編程send()函數(shù)參數(shù)說明s用于標(biāo)識已建立連接的套接字buf是一個字符緩沖區(qū),內(nèi)有將要發(fā)送的數(shù)據(jù)len即將發(fā)送的緩沖區(qū)中的字符數(shù)flags用于控制數(shù)據(jù)傳輸方式,0表示按正常方式發(fā)送數(shù)據(jù);宏MSG_DONTROUTE說明系統(tǒng)目標(biāo)主機(jī)就在直接連接的本地網(wǎng)絡(luò)中,無需路由選擇;MSG_OOB指出數(shù)據(jù)是按帶外數(shù)據(jù)發(fā)送的函數(shù)說明:send()函數(shù)適用于已建立連接的數(shù)據(jù)報或流式套接口發(fā)送數(shù)據(jù),對于數(shù)據(jù)報類型套接口必須注意發(fā)送數(shù)據(jù)長度不大于通信子網(wǎng)的IP包最大長度2022/7/1951TCP/IP Socket網(wǎng)絡(luò)

29、編程接收數(shù)據(jù)recv()函數(shù)對于已建立連接的套接口來說,要從套接口上接收數(shù)據(jù),就要使用recv()函數(shù)。int recv(SOCKET s,char FAR * buf,int len,int flags);2022/7/1952TCP/IP Socket網(wǎng)絡(luò)編程recv()函數(shù)參數(shù)說明s為已建立連接的套接口buf為用于接收數(shù)據(jù)的緩沖區(qū)len為緩沖區(qū)的長度flags指定調(diào)用的方式。0表示接收的是正常數(shù)據(jù),無特殊行為。MSG_PEEK表示會使有用的數(shù)據(jù)復(fù)制到所提供的接收端緩沖區(qū)內(nèi),但是沒有從系統(tǒng)緩沖區(qū)中將數(shù)據(jù)刪除。MSG_OOB表示處理帶外數(shù)據(jù)。2022/7/1953TCP/IP Socket網(wǎng)

30、絡(luò)編程無連接的套接口上接收數(shù)據(jù)-recvfrom()對于無連接的套接口來說,要從套接口上接收一個數(shù)據(jù)報并保存發(fā)送數(shù)據(jù)的源地址,就要使用recvfrom()函數(shù)。int recvfrom(SOCKET s,char FAR * buf,int len,int flags,struct sockaddr FAR * from,int FAR * fromlen);2022/7/1954TCP/IP Socket網(wǎng)絡(luò)編程recvfrom()函數(shù)參數(shù)說明s標(biāo)識一個套接口的描述字buf接收數(shù)據(jù)的緩沖區(qū)len接收數(shù)據(jù)緩沖區(qū)的長度flags調(diào)用操作方式,同recv()中的flagsfrom可選指針,指向裝有

31、源地址的緩沖區(qū)fromlen可選指針,指向from緩沖區(qū)的長度值函數(shù)說明:該函數(shù)的用法與有連接時recv()的用法一致,要注意的是該函數(shù)也可以用于有連接時數(shù)據(jù)的接收2022/7/1955TCP/IP Socket網(wǎng)絡(luò)編程在無連接套接口上發(fā)送數(shù)據(jù)-sendto()對于無連接的套接口來說,要從套接口上發(fā)送一個數(shù)據(jù)報,就要使用sendto()函數(shù)int sendto(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR * to,int tolen);2022/7/1956TCP/IP Socket網(wǎng)絡(luò)編程

32、sendto()函數(shù)參數(shù)說明s本機(jī)的套接字buf待發(fā)送數(shù)據(jù)的緩沖區(qū)len指明buf緩沖區(qū)中要發(fā)送的數(shù)據(jù)長度flags調(diào)用方式標(biāo)志位,同send()中的flagsto可選指針,指向接收數(shù)據(jù)的目的套接口地址tolen是to所指的地址的長度函數(shù)說明:該函數(shù)的使用方法類似send()函數(shù),當(dāng)用于無連接套接字接口,調(diào)用函數(shù)前要設(shè)置,指出目標(biāo)IP地址和目標(biāo)端口號。如果用于有連接的套接口時,則不能指定目標(biāo)地址和目標(biāo)端口,將to設(shè)置為空,地址長度設(shè)為0。當(dāng)然在有連接的情況下很少使用該函數(shù)2022/7/1957TCP/IP Socket網(wǎng)絡(luò)編程關(guān)閉讀寫通道-shutdown()函數(shù)在一個套接口上的讀寫操作完成后

33、,應(yīng)該首先使用shutdown()函數(shù)來關(guān)閉套接口的讀通道、寫通道或讀寫通道,這樣做的好處是當(dāng)雙方不再有數(shù)據(jù)要發(fā)送或接收時,可以通知對方,以防止數(shù)據(jù)丟失,并能“優(yōu)雅”地關(guān)閉連接。int shutdown(SOCKET s,int how);2022/7/1958TCP/IP Socket網(wǎng)絡(luò)編程shutdown()函數(shù)參數(shù)說明s標(biāo)識一個套接口的描述字how是一個標(biāo)志,用于描述禁止哪些操作,取值如下表所示關(guān)閉方式參數(shù)值說明SD_RECEIVE0表示不允許再調(diào)用接收函數(shù),它關(guān)閉讀通道。套接口接收緩沖區(qū)中的所有數(shù)據(jù)都被丟棄,并且有新數(shù)據(jù)到達(dá)套接口時,也被TCP協(xié)議層丟棄,但它對發(fā)送緩沖區(qū)沒有影響,進(jìn)

34、程仍然可以在套接口上發(fā)送數(shù)據(jù)SD_SEND1表示不允許再調(diào)用發(fā)送函數(shù),它關(guān)閉寫通道。在套接口發(fā)送緩沖區(qū)中的數(shù)據(jù)都被發(fā)送出去,得到接收端確認(rèn)之后,就生成一個FIN包關(guān)閉連接。但它對接收緩沖區(qū)沒有影響,進(jìn)程仍然可以在套接口上接收數(shù)據(jù)SD_BOTH2關(guān)閉讀寫通道,相當(dāng)于執(zhí)行了上面SD_RECEIVE和SD_SEND兩個命令2022/7/1959TCP/IP Socket網(wǎng)絡(luò)編程關(guān)閉套接口-closesocket()函數(shù)shutdown函數(shù)只關(guān)閉讀寫通道,并不關(guān)閉套接口,且套接口所占有的資源將被一直保留到closesocket()調(diào)用之前。一個套接口不再使用時一定要關(guān)閉這個套接口,以釋放與該套接口關(guān)聯(lián)

35、的所有資源,包括等候處理的數(shù)據(jù)。int closesocket(SOCKET s);參數(shù)s表示即將被關(guān)閉的套接口2022/7/1960TCP/IP Socket網(wǎng)絡(luò)編程IP地址轉(zhuǎn)換函數(shù)char * inet_ntoa ( struct in_addr in )in為傳入?yún)?shù),表示一個結(jié)構(gòu)型的IP主機(jī)地址,該函數(shù)將一個32位數(shù)字表示的IP地址轉(zhuǎn)換成點分十進(jìn)制IP地址字符串unsigned long inet_addr(const char FAR * cp)該函數(shù)將一個點分十進(jìn)制IP地址字符串轉(zhuǎn)換成32位數(shù)字表示的IP地址。兩函數(shù)互為反函數(shù)2022/7/1961TCP/IP Socket網(wǎng)絡(luò)編程

36、字節(jié)序轉(zhuǎn)換函數(shù)u_long htonl( u_long hostlong )4字節(jié)主機(jī)字節(jié)序表示的整數(shù)轉(zhuǎn)換為4字節(jié)相應(yīng)的網(wǎng)絡(luò)字節(jié)序表示的整數(shù)u_short htons( u_short hostshort )2字節(jié)主機(jī)字節(jié)序表示的整數(shù)轉(zhuǎn)換為2字節(jié)相應(yīng)的網(wǎng)絡(luò)字節(jié)序表示的整數(shù)u_long ntohl( u_long netlong )4字節(jié)網(wǎng)絡(luò)字節(jié)序表示的整數(shù)轉(zhuǎn)換為4字節(jié)相應(yīng)的主機(jī)字節(jié)序表示的整數(shù)u_short ntohs( u_short netshort )2字節(jié)網(wǎng)絡(luò)字節(jié)序表示的整數(shù)轉(zhuǎn)換為2字節(jié)相應(yīng)的主機(jī)字節(jié)序表示的整數(shù)2022/7/1962TCP/IP Socket網(wǎng)絡(luò)編程終止使用Winso

37、ck-WSACleanup()函數(shù)當(dāng)應(yīng)用程序不再使用Winsock API中的任何函數(shù)時,必須調(diào)用WSACleanup()將其從Windows Socket的實現(xiàn)中注銷,以釋放為此應(yīng)用程序或DLL分配的任何資源。int WSACleanup(void);函數(shù)說明:WSACleanup()函數(shù)是任何一個Winsock應(yīng)用程序在最后必須要調(diào)用的函數(shù)。在一個多線程的環(huán)境下,WSACleanup()函數(shù)中止了Windows Sockets在所有線程上的操作2022/7/1963TCP/IP Socket網(wǎng)絡(luò)編程TCP/IP網(wǎng)絡(luò)程序框架面向連接的C/S程序工作流程無連接的C/S程序工作流程2022/7/

38、1964TCP/IP Socket網(wǎng)絡(luò)編程面向連接的C/S程序工作流程(TCP)服務(wù)器端工作流程使用WSAStartup()函數(shù)檢查系統(tǒng)協(xié)議棧安裝情況使用socket()函數(shù)創(chuàng)建服務(wù)器端通信套接口使用bind()函數(shù)將創(chuàng)建的套接口與服務(wù)器地址綁定使用listen()函數(shù)使服務(wù)器套接口做好接收連接請求準(zhǔn)備使用accept()接收來自客戶端由connect()函數(shù)發(fā)出的連接請求根據(jù)連接請求建立連接后,使用send()函數(shù)發(fā)送數(shù)據(jù),或者使用recv()函數(shù)接收數(shù)據(jù)使用closesocket()函數(shù)關(guān)閉套接口(可以先用shutdown()函數(shù)先關(guān)閉讀寫通道)最后調(diào)用WSACleanup()函數(shù)結(jié)束Wi

39、nsock Sockets API2022/7/1965TCP/IP Socket網(wǎng)絡(luò)編程面向連接的C/S程序工作流程(TCP)客戶端程序工作流程使用WSAStartup()函數(shù)檢查系統(tǒng)協(xié)議棧安裝情況使用socket()函數(shù)創(chuàng)建客戶端套接口使用connect()函數(shù)發(fā)出也服務(wù)器建立連接的請求(調(diào)用前可以不用bind()端口號,由系統(tǒng)自動完成)連接建立后使用send()函數(shù)發(fā)送數(shù)據(jù),或使用recv()函數(shù)接收數(shù)據(jù)使用closesocet()函數(shù)關(guān)閉套接口最后調(diào)用WSACleanup()函數(shù),結(jié)束Winsock Sockets API2022/7/1966TCP/IP Socket網(wǎng)絡(luò)編程面向連接

40、的C/S程序工作流程(TCP)服務(wù)器與客戶端五元組的建立五元組服務(wù)器端五元組由socket()確定由服務(wù)器端調(diào)用bind()時確定由accept()確定客戶端五元組由socket()確定由客戶端的bind()調(diào)用確定。如果客戶端沒有進(jìn)行bind()調(diào)用,或調(diào)用了bind()但沒有指定具體地址或端口號,則由系統(tǒng)內(nèi)核自動確定地址和端口由connect()確定2022/7/1967TCP/IP Socket網(wǎng)絡(luò)編程面向連接的C/S程序工作流程圖(TCP)2022/7/1968TCP/IP Socket網(wǎng)絡(luò)編程無連接的C/S程序工作流程(UDP)無連接的數(shù)據(jù)報傳輸服務(wù)通信時,客戶端與服務(wù)器端所使用的函

41、數(shù)是類似的,其工作流程如下:使用WSAStartup()函數(shù)檢查系統(tǒng)協(xié)議棧的安裝情況使用socket()函數(shù)創(chuàng)建套接口,以確定協(xié)議類型調(diào)用bind()函數(shù)將創(chuàng)建的套接口與本地地址綁定,確定本地地址和本地端口號使用sendto()函數(shù)發(fā)送數(shù)據(jù),或者使用recvfrom()函數(shù)接收數(shù)據(jù)使用closesocket()函數(shù)關(guān)閉套接口調(diào)用WSACleanup()函數(shù),結(jié)束Windows Sockets API2022/7/1969TCP/IP Socket網(wǎng)絡(luò)編程無連接的C/S程序工作流程(UDP)注意事項:通信的一方可以不用bind()綁定地址和端口,由系統(tǒng)分配不綁定IP地址和端口號的一方必須首先向綁

42、定地址的一方發(fā)送數(shù)據(jù)無連接的應(yīng)用程序也可以調(diào)用connect()函數(shù),但是它并不向?qū)Ψ桨l(fā)出建立連接的請求,而是在本地返回,由內(nèi)核將connect()中指定的目標(biāo)IP地址和端口號記錄下來,在以后的通信中就可以使用面向連接的數(shù)據(jù)發(fā)送函數(shù)send()和數(shù)據(jù)接收函數(shù)recv()無連接的數(shù)據(jù)報傳輸過程中,作為服務(wù)器的一方必須先啟動無連接客戶端一般不調(diào)用connect(),在數(shù)據(jù)發(fā)送前客戶與服務(wù)器各自通過socket()和bind()建立了半相關(guān),發(fā)送數(shù)據(jù)時除指定本地套接口的地址外,還需要指定接收方套接口地址,從而在數(shù)據(jù)收發(fā)過程中動態(tài)建立全連接2022/7/1970TCP/IP Socket網(wǎng)絡(luò)編程無連接

43、的C/S程序工作流程圖(UDP)2022/7/1971TCP/IP Socket網(wǎng)絡(luò)編程阻塞通信與非阻塞通信阻塞方式:套接字進(jìn)行I/O操作時,函數(shù)要等待到相關(guān)的操作完成以后才能返回,對提高處理機(jī)的利用率不利,但編程簡單。非阻塞方式:套接字進(jìn)行I/O操作時,無論操作成功與否,調(diào)用都會立即返回。阻塞方式編程簡單,一個套接口的默認(rèn)操作模式為阻塞,可以調(diào)用函數(shù)ioctlsocket()進(jìn)行設(shè)置。2022/7/1972TCP/IP Socket網(wǎng)絡(luò)編程并發(fā)服務(wù)器2022/7/1973TCP/IP Socket網(wǎng)絡(luò)編程基于TCP的客戶/服務(wù)器服務(wù)器代碼/ server.cpp : 定義控制臺應(yīng)用程序的入口

44、點。#include stdafx.h#include #include #include #define DEFAULT_PORT 5050 /服務(wù)端默認(rèn)端口int _tmain(int argc, char* argv)intiPort = DEFAULT_PORT;WSADATAwsaData;SOCKETsListen,sAccept;intiLen; /客戶地址長度intiSend;/發(fā)送數(shù)據(jù)長度charbuf = I am a server;/要發(fā)送給客戶的信息struct sockaddr_in ser,cli;/服務(wù)器和客戶的地址if(WSAStartup(MAKEWORD(2

45、,2),&wsaData)!=0)printf(Failed to load Winsock.n);return -1;2022/7/1974TCP/IP Socket網(wǎng)絡(luò)編程基于TCP的客戶/服務(wù)器服務(wù)器代碼sListen = socket(AF_INET,SOCK_STREAM,0);/創(chuàng)建服務(wù)器端套接口if(sListen = INVALID_SOCKET)printf(socket() Failed: %dn,WSAGetLastError();return -1;/以下建立服務(wù)器端地址/使用IP地址族ser.sin_family = AF_INET;/使用htons()把雙字節(jié)主機(jī)序

46、端口號轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序端口號ser.sin_port = htons(iPort);/htonl()把一個四字節(jié)主機(jī)序IP地址轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序主機(jī)地址/使用系統(tǒng)指定的IP地址INADDR_ANYser.sin_addr.s_addr = htonl(INADDR_ANY);/bind()函數(shù)進(jìn)行套接定與地址的綁定if(bind(sListen,(LPSOCKADDR)&ser,sizeof(ser) = SOCKET_ERROR)printf(bind() Failed: %dn,WSAGetLastError();return -1;2022/7/1975TCP/IP Socket網(wǎng)絡(luò)編程基

47、于TCP的客戶/服務(wù)器服務(wù)器代碼/進(jìn)入監(jiān)聽狀態(tài)if(listen(sListen,5) = SOCKET_ERROR)printf(lisiten() Failed: %dn,WSAGetLastError();return -1;/初始化客戶地址長度參數(shù)iLen = sizeof(cli);/進(jìn)入一個無限循環(huán),等待客戶的連接請求while(1)sAccept = accept(sListen,(struct sockaddr *)&cli,&iLen);if(sAccept = INVALID_SOCKET)printf(accept() Failed: %dn,WSAGetLastErro

48、r();return -1;/輸出客戶IP地址和端口號printf(Accepted client IP:%s,port:%dn,inet_ntoa(cli.sin_addr),ntohs(cli.sin_port);2022/7/1976TCP/IP Socket網(wǎng)絡(luò)編程基于TCP的客戶/服務(wù)器服務(wù)器代碼/給連接的客戶發(fā)送信息iSend = send(sAccept,buf,sizeof(buf),0);if(iSend = SOCKET_ERROR)printf(send() Failed: %dn,WSAGetLastError();break;else if(iSend = 0)break;elseprintf(send() byte: %dn,iSend);closesocket(sAccept);closesocket(sListen);WSACleanup();return 0;2022/7/1977TCP/IP Socket網(wǎng)絡(luò)編程基于TCP的客戶/服務(wù)器客戶端代碼/ client.cpp : 定義控制

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論