協議

為進行網絡中的數據交換而建立的規則、標準或約定(=語義+語法+規則)。

不同層具有不同的協議

OSI/ISO七層參考模型
OSI(Open Systern Interconnection)參考模型將網絡的不同功能劃分為7層。

?????????????????? 分層???????????????????????????????????????????????????????????????????????????????????????????????????協議

應用層?????????————處理網絡應用????????????? 遠程登錄協議Telnet、文件傳輸協議FTP?、
????????????????????????????????????????????????????????????????????????超文本傳輸協議HTTP、域名服務DNS、
????????????????????????????????????????????????????????????????????????簡單郵件傳輸協議SMTP、郵局協議POP3等

表示層???????? ————數據表示

會話層??????? ?————?主機間通信

傳輸層????????————端到端的連接?????????????傳輸控制協議TCP(面向連接的可靠連接協議)、
?????????????????????????????????????????????????????????????????用戶數據報協議UDP?(無連接的不可靠連接協議)??????????????????????????

網絡層???????————尋址和最短路徑??????????????網際協議IP、Internet互聯網控制報文協議ICMP、
??????????????????????????????????????????????????????????????????????????????Internet組管理協議IGMP

數據鏈路層?————?介質訪問(接入)

物理層?????? ??————二進制傳輸


通信實體的對等層之間不允許直接通信。

各層之間是嚴格單向依賴。

上層(Server User)使用下層提供的服務。
下層(Server? Provider)向上層提供服務。

對等層通信的實質:
對等層之間虛擬通信。
下層向上層提供服務,實際通信在最底層完成。

數據封裝
一臺計算機要發送數據到另一臺計算機,數據首先必須打包,
打包的過程稱為封裝

封裝就是在數據前面加上特定的協議頭部,或者在數據后面加上特定的協議尾部。

OSI參考模型中。對等層協議之間交換的信息單元統稱為協議數據單元(PDU,Protocal? Data Unit)

OSI參考模型中每一層都要依靠下一層提供的服務。
為了提供服務,下層把上層的PDU作為本層的數據來封裝,然后加入本層的頭部(和尾部)。
頭部中含有完成數據傳輸所需的控制信息。

這樣,數據自上而下遞交的過程實際上就是不斷封裝的過程。
到達目的地后自下而上遞交的過程,就是不斷拆封的過程。
由此可知,在物理線路上傳輸的數據,其外在實際上被包封了多層“信封”。

但是,某一層只能識別由對等層封裝的“信封”,
而對于被封裝在“信封”內部的數據僅僅是拆封后將其提交給上層,
本層不做任何處理。

TCP/IP模型
TCP/IP模型包含4個層次:
?應用層
?傳輸層
?網絡層
?網絡接口

TCP/IP與OSI參考模型的對應關系

TCP/IP模型??????????????????????????????????????????????????????????????????????????????????????????OSI模型

?應用層????????????????????????????????????????????????????????????????????????????????????????????????????應用層
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????表示層
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????會話層

?傳輸層?????????????????????????????????????????????????????????????????????????????????????????????????????傳輸層

?網絡層?????????????????????????????????????????????????????????????????????????????????????????????????????網絡層

?網絡接口????????????????????????????????????????????????????????????????????????????????????????????????數據鏈路層
??????????????????????????????????????????????????????????????????????????????????????????????????????????????????物理層



端口
按照OSI七層模型的描述,傳輸層提供進程(應用程序)通信的能力。
為了能標示通信實體中進行通信的進程,TCP/IP協議提出了協議端口(protocal port,簡稱端口)的概念。

端口是一種抽象的軟件結構(包括一些數據結構和I/O緩沖區)。
應用程序通過系統調用與某端口建立連接(binding)后,傳輸層傳給該端口的數據都被相應的進程所接收,
相應進程發給傳輸層的數據都通過該端口輸出。

端口用一個整數型標識符來表示,即端口號。
端口號和協議相關,TCP/IP傳輸層的2個協議TCP和UDP是完全獨立的2個軟件模塊,因此各自的端口號相互獨立。

端口使用一個16位的數字來表示,它的范圍是0~65535
數字比1024小的端口保留給預定義的服務。例如:http使用80端口。

套接字(socket)的引入
為了能方便的開發網絡應用軟件,由美國伯克利大學在Unix上推出了一種應用程序訪問通信協議的操作系統調用socket(套接字)。socket的出現,讓程序員可以很方便的訪問TCP/IP,從而開發各種網絡應用程序。

隨著Unix的應用推廣,套接字在編寫網絡軟件中得到了極大的普及。
后來,套接字又被引入到Windows等操作系統,成為開發網絡應用程序的非常有效快捷的工具。

套接字存在于通信區域中。
通信區域也叫地址族,它是一個抽象的概念,主要用于將通過套接字通信的進程的共有特性綜合在一起。
套接字通常只和同一區域的套接字交換數據(也可能跨區域通信,但只在執行了某種轉換進程后才可以)。
Windows? Sockets只支持一個通信區域:網際域(AF_INET),這個域被使用網際協議簇通信的進程使用。

網絡字節順序
不同的計算機存放多字節值的順序不同,
有的機器在起始地址存放低位字節(低位先存),比如基于Inter的CPU,即我們常用的PC機。
有的機器在起始地址存放高位字節(高位先存)。
為保證傳輸數據的正確性,在網絡協議中需指定網絡字節順序。
TCP/IP協議使用16位整數和32位整數的高位先存格式。

客戶機/服務器模式
在TCP/IP網絡應用中,通信的2個進程間相互作用的主要模式是客戶機/服務器模式(client/server),
即客戶向服務器提出請求,服務器接收到請求后,提供相應的服務。

客戶機/服務器模式的建立基于2點:
1。建立網絡的原因是網絡中軟硬件資源、運算能力和信息不對稱等,需要共享,
從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。
2.網間進程通信完全是異步的,相互通信的進程間即不存在父子關系,又不共享內存緩沖區,
因此需要一種機制為希望通信的進程建立聯系,為2者的數據交換提供同步,
這就是基于客戶機/服務器模式的TCP/IP。

客戶機/服務器模式在操作過程中采用的是主動請求的方式。
服務器:
首先服務器方要先啟動,并根據請求提供相應的服務:
1.打開一個通信通道并告知本地主機,它愿意在某一地址及端口上接收客戶請求。
2.等待客戶請求到達該端口。
3.接收到重復服務請求,處理該請求并發送應答信號。
接收到并發服務請求,要激活一個新的進程(或線程)來處理這個客戶的請求。
新進程(或線程)處理此客戶請求,并不需要對其它請求作出應答。
服務完成后,關閉此新進程與客戶的通信鏈路,并終止。
4.返回第2步,等待另一客戶請求。
5.關閉服務器。

客戶機:
1.打開一個通信信道,并連接到服務器所在主機的指定端口。
2.向服務器發請求報文,等待并接收應答;繼續提出請求。
3.請求結束后,關閉通信信道并終止。


Windows Sockets的實現
Windows Sockets是Microsoft Windows的網絡程序設計接口,
它是從Berkeley Sockets展而來的,以動態鏈接庫的形式提供給我們使用。
Windows Sockets在繼承了Berkeley Sockets主要特征的基礎上,又對它進行了擴充。
這些擴充主要是提供了一些異步函數,并增加了符合Windows消息驅動特性的網絡事件異步選擇機制。

Windows??Sockets 1.1和Berkeley Sockets都是基于TCP/IP的。
Windows??? Sockets? 2 從Windows Sockets? 1.1發展而來,與協議無關并向下兼容,
可以使用任何底層傳輸協議提供的通信能力,來為上層應用程序完成網絡數據通訊,
而不關心底層網絡鏈路的通信情況,真正實現了底層網絡通訊對應用程序的透明(?)



套接字的類型
1.流式套接字(SOCK_STREAM)
??????提供面向連接、可靠的數據傳輸服務,數據無差錯無重復的發送,且按發送順序接收。
2.數據報套接字(SOCK_DGRAM)
??????提供無連接服務。數據包以獨立包形式發送,數據可能丟失、重復,且接收順序混亂。
3.原始套接字(SOCK_RAM)

基于TCP(面向連接)的socket編程
服務器端程序:
1.創建套接字(socket)。
2.將套接字綁定到一個本地地址和端口上(bind)。?
3.將套接字設為監聽模式,準備接收客戶請求(listen)。
4.等待客戶請求到來;當請求到來后,接收連接請求,返回一個新的對應于此次連接的套接字(accept)。
5.用返回的套接字和客戶端進行通信(send/recv)。
6.返回,等待另一客戶請求。
7.關閉套接字(close)。???

客戶端程序:
1.創建套接字(socket)。
2.向服務器發出連接請求(connect)。
3.和服務器端進行通信(send/recv)。
4.關閉套接字?(close)。

基于(UDP)面向無連接的socket編程
服務器端程序:
1.創建套接字(socket)。
2.將套接字綁定到一個本地地址和端口上(bind)。
3.等待接收數據(recvfrom)。
4.關閉套接字(close)。

客戶端程序:
1.創建套接字(socket)。
2.向服務器發送數據(sendto)。
3.關閉套接字(close)。

相關函數說明
int? WSAStartup(WORD wVersionRequested? , LPWSADATA?????? ?lpWSAData);
wVersionRequested參數用于指定準備加載的Winsock庫的版本。
高位字節指定所需要的Winsock庫的副版本,而低字節則是主版本。
可用MAKEWORD(?x , y )(其中x是高位字節,y是低位字節)方便地獲得wVersionRequested的正確值。
lpWSAData參數是指向WSADATA結構的指針,
WSAStartup用其加載的庫版本有關的信息填在這個結構中。
WSADATA結構定義如下:
typedef struct WSADate
{
??????WORD??? wVersion;
??????WORD???? wHighVersion;
??????char??????szDescription [WSADESCRIPTION_LEN+1];
??????char????? szSystemStatus[WSASYS_STATUS_LEN+1];
??????unsigned?? short? iMaxSockets;
??????unsigned???short? iMaxUdpDg;
??????char??? FAR*?? lpVendorInfo;
}WSADATA, *LPWSADATA;
??????WSAStartup把第一個字段wVersion設成打算使用的Winsock的版本,wHighVersion參數容納的是現有的Winsock庫的最高版本。記住,兩個字段中,高位字節代表的是Winsock副版本,而低字節代表的是Winsock庫的主版本。szDescription和szSystemStatus這兩個字段由特定的Winsock實施方案設定,事實上沒有用。不要使用下面這兩個字段:iMaxSocks和iMaxUdpDg.,它們是假定同時最多可打開多少套接字和數據報的最大長度。然而,要知道數據報的最大長度應該通過WSAEnumProtocols關。最后,lpvendorInfo字段是為Winsock實施方案有關的指定廠商信息預留的。任何一個Win32平臺上都沒有使用這個字段。
?????????如果Winsock.dll或底層網絡子系統沒有被正確初始化或沒有被找到,WSAStartup將返回WSASYSNOTREADY。此外這個函數允許你的應用程序協商使用某種版本的Winsock規范,如果請求的版本等于或高于DLL所支持的最高版本與請求版本中較小的那個。反之,如果請求的版本低于DLL所支持的最低版本,WSAStartup將返回WSAVERNOTSUPPORTED。關于WSAStartup更詳細的信息,請查閱MSDN中的相關部分。
????????對于每一個WSAStartup的成功調用(成功加載Winsock DLL后),在最后都對應一個WSACleanUp調用,以便釋放為該應用程序分配的資源。

SOCKET? socket(int af, int? type,? int? protocal);
該函數接收3個參數。
第一個參數af指定地址族,對于TCP/IP協議的套接字,它只能是AF_INET(也可寫成PF_INET)。
第二個參數指定Socket類型,對于1.1版本的Socket,它只支持2種類型的套接字,SOCK_STREAM指定產生流式套接字,SOCK_DGRAM產生數據報套接字。
第三個參數是與特定地址家族相關的協議,自動為你選擇一個合適的協議。這是推薦使用的一種選擇協議的方法。
如果這個函數調用成功,它將返回一個新的SOCKET數據類型的套接字描述符。如果調用失敗,這個函數就會返回一個INVALID_SOCKET,錯誤信息可以通過WSAGEtLastError函數返回。

int bind(SOCKET? s,?? const?? struct?? sockaddr? FAR? *? name,? int?? namelen);
第一個參數s指定要綁定的套接字,
第二個參數指定了該套接字的本地地址信息,是指向sockaddr結構的指針變量,由于該地質結構是為所有的地址家族準備的,這個結構可能(通常會)隨所使用的網絡協議不同而不同,所以,
要用第三個參數指定該地址結構的長度。
sockaddr結構定義如下:
struct? sockaddr
{
??????u_short?? sa_family;
??????char??????? sa_data[14];
}
sockaddr的第一個字段sa_family指定該地址家族,在這里必須設為
AF_INET.sa_data僅僅是表示要求一塊內存分配區,起到占位的作用,該區域中指定與協議相關的具體地址信息。由于實際要求的只是內存區,所以對于不同的協議家族,用不同的結構來替換 sockaddr。除了sa_family外,sockaddr是按網絡字節順序表示的。在TCP/IP中,我們可以用sockaddr_in結構替換sockaddr,以方便我們填寫地址信息。
sockaddr_in的定義如下:
struct?? sockaddr_in
{
??????short???????????????????????sin_family;
????????unsigned????short?????sin_port;
?????????struct?????????in_addr??????sin_addr;
?????????char?? sin_size[8];
}
?????????其中,sin_family表示地址族,對于IP地址,sin_family成員將一直是AF_INET。成員sin_port指定的是將要分配給套接字的端口。成員sin_addr給出的是套接字的主機IP地址。而成員sin_zero只是一個填充數,以使sockaddr_in結構和sockaddr結構的長度一樣。如果這個函數調用成功,它將返回0。如果調用失敗,這個函數就會返回一個SOCKET_ERROR,錯誤信息可以通過WSAGetLastError函數返回。
??????將IP地址指定為INADDR_ANY,允許套接字向任何分配給本地機器的IP地址發送或接收數據。多數情況下,每個機器只有一個IP地址,但有的機器可能會有多個網卡,每個網卡都可有自己的IP,用INADDR_ANY可以簡化應用程序的編寫。將地址指定為INADDR_ANY,允許一個獨立應用接受發自多個接口的回應,如果我們只想讓套接字使用多個IP中的一個,就必須指定實際地址,要做到這一點,可以用inet_addr()函數,這個函數需要一個字符串做為其參數,該字符串指定了以點分十進制格式表示的IP地址(如:192.168.0.16).而且inet_addr()函數會返回一個適合分配給S_addr的u_long類型的數值。inet_ntoa()函數會完成相反的轉換,它接受一個in_addr結構類型的參數并返回一個以點分十進制格式表示的IP地址字符串。