什么是TCP/IP------本課程的主要部分
TCP/IP如何工作-----TCP/IP軟件結構與實現
如何用TCP/IP-------TCP/IP應用程序編程接口
前面說過,TCP/IP標準并不指定應用程序與TCP/IP協議軟件的接口,但并不是說沒有提供任何指導,首先,它指定了一些必須具有的操作。這包括:
–為通信指定本地資源
–指定本地和遠程通信端點
–初始化連接(客戶端)
–等待連接(服務器端)
–發送和接收數據
–生成緊急數據
–中斷通信
–……
–在通信結束時釋放本地資源
同時,TCP/IP標準還指定了一個概念層接口,它是作為一個闡述如何使用TCP/IP的例子,它包含了一系列過程和函數,標準建議了每個過程和函數所需要的參數及其所執行操作的語義,但沒有進一步指定數據表示的細節。
仔細的接口通常由操作系統來定義,只要完成TCP/IP標準中的功能,可以有不同的細節選擇。這樣不同的操作系統的應用程序編程接口是各不同的。
–Berkeley Software Distribution UNIX 的 Socket 接口是廣泛使用的
–Windows的接口定義Winsock接口
–System V的接口定義TLI接口
–……
操作系統提供的應用程序編程接口又分為兩類:
–直接由操作系統內核提供的系統調用
BSD UNIX socket
–在操作系統外以庫函數的方式提供的各種可調用函數
Windows socket
一、系統調用
–當應用程序要進行系統調用,首先是把控制交到系統調用接口,接口再把控制轉到操作系統,由操作系統調用相應的內部進程來執行請求的操作,內部進程完成后,操作系統再通過調用接口把控制權返回應用程序
在TCP/IP協議加入操作系統后,操作系統可以有兩種方式來幫助應用程序訪問內核的TCP/IP協議
–用一種新的系統調用
–用通常的I/O調用來訪問TCP/IP
完全用第一種方案較少,因為這樣要把所有的概念操作都重新設計
采用第二種方案:通過重載通常的I/O調用使得訪問協議與通常的I/O一樣。
較多采用混合方法:易重載的重載,不易重載的用新函數。
UNIX的基本的I/O函數(一般設備或文件的I/O操作)
–open:為I/O操作準備設備或文件
–close:終止使用前面打開的設備和文件
–read:從輸入設備或文件獲取數據
–write:向輸出設備或文件傳輸數據
–lseek:移到設備或文件指定的位置
–ioctl:控制設備或訪問它的軟件
一旦打開某個設備或文件,就給它分配一個描述號,
–int desc;
–desc=open(“filename”,O_RDWR,0)
在后面,應用程序將使用 desc 來對該文件進行標識并進行讀寫操作
–read(desc,buffer,128)
完成相關操作后,關閉
–close (desc)
–在BSD UNIX中,使用重載上述的I/O調用來實現對協議的部分訪問。同時又一些功能不能重載,需要設計一些新的函數
BSD UNIX Socket 使用混合模式
BSD UNIX Socket 在設計時還考慮到支持多種通信協議,因此,協議族名稱往往是一些函數的參數。TCP/IP是一個單一的協議族
BSD UNIX Socket 要求必須使用服務類型來指定操作而不是指定某個協。
以下為幾個在完成socket進程通信機制中需要的系統調用(以下以BSD UNIX為例)
sockid=socket(family,type,protocol) //創建socket
–其中: family:地址族,即協議族
–Type:協議服務類型
–Protocol:具體協議
–sockid:UNIX用于標識該socket的整數,
bind(sockid,localaddr,addrlen)
//將本地socket地址(本地地址,本地端口)與所創建的scoket號聯系起來,
–其中localaddr:指向socket地址結構的指針,TCP/IP的socket地址結構:
struct sockadd_in{
u_short sin_family; //指明協議族
u-short sin_port; //端口號
struct in_addr sin_addr; //IP地址
char sin_zero[8]; //未用
}
–addrlen:地址結構的長度(以字節為單位)
connect(sockid, destaddr, paddrlen)
//用于建立socket連接
–sockid:欲建立連接的本地socket號
–destaddr:指向對方socket地址結構的指針
–paddrlen:對方socket地址長度
listen(sockid,quelen)
//服務器用于確認它愿意建立客戶請求的連接
–sockid:本地socket號,服務器將從它上面接收客戶請求
–quelen:請求隊列的長度,
newsock=accept(sockid, clientaddr, paddrlen)
//用于面向連接的服務器建立socket連接
–sockid:欲建立連接的本地socket號
–clientaddr:指向客戶socket地址結構的指針
–paddrlen: 客戶socket地址長度
–newsock:一個新的socket號
發送數據的系統調用(write)
–面向連接
write(sockid,buff,bufflen)//緩沖發送
writev(sockid,iovector,vectorlen)//集中發送
send(sockid,buff,bufflen,flags)//可控緩沖發送
–面向無連接
sendto(sockid,buff,bufflen,flags,dstadd,addrlen)//可控緩沖發送
sendmsg(sockid,message,flags)//可控緩沖發送
接收數據的系統調用(read)
–與發送的調用是一一對應的,有些參數所不同
其它與socket有關的系統調用
此外socket調用中還有一些給程序員用的實用函數,例如整數轉換函數等等以實現不同體系結構的兼容性。因為BSD UNIX socket調用是支持多協議族的。(這也是socket函數復雜、受到批評的一個原因)
調用的時序關系:
利用socket實現并發服務器的例子:
int initsockid,newsockid;
if((initsockid=socket(…))<0)
error(“cant creat scoket”);
if(bind(initsockid,localaddr,addrlen)<0
error(“bind error”);
if(listen(initsockid,5)<0)
error(“listen error”);
for(;;){
newsockid=accept(initsockid,…)
if(newsockit<0)
error(“accept error”);
if(fork()==0){
close(initsockid);
do(newsockid);
exit(o);
}
close(newsockid);
}
除了完成socket的系統功能調用,BSD UNIX還提供了一套預定義的符號常量和數據結構聲明,應用程序可以用它們來聲明數據、指定變量。例如:符號常量SOCK_DGRAM 和 SOCK_STREAM分別說明采用樹舉報服務還是流服務
這些聲明定義在兩個頭文件中:
–#include
#include
二、在操作系統外以庫函數的方式提供可調用函數
Winsock API函數
–WSAStartup:初始化scoket庫
–WSACleanup: 終止使用scoket庫
–scoket:創建
–connect:
–closesocket:
–bind
–listen
–accept
–……
其它
舉報/反饋