歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux基礎知識 >> socket 基礎知識

socket 基礎知識

日期:2017/2/27 10:15:22   编辑:Linux基礎知識
進程通信的概念最初來源於單機系統,由於每個進程都在各自的地址范圍內運行,為了保證兩個相互通信的進程之間既不互相干擾,又協調一致的工作,操作系統為進程通信提供了相應設施,如UNIX BSD中的管道(pipe),有名管道(named pipe)和軟中斷信號(singal),UNIX system V的消息(message)、共享存儲區(shared memory)和信號量(semaphore)等,但都局限於用在本機進程之間通信。網間進程通信要解決的是不同主機進程間的通信問題(可把同機進程通信看作其中的特例)。為此,首先要解決的是網間進程標識問題。同一主機上,不同進程可以用進程號(pid)唯一標識。但在網絡環境下,各主機獨立分配的進程號不能唯一標識該進程。例如主機A賦予某進程號5,在B主機也可以存在5號進程,因此5號進程這句話就沒有意義了。其次,操作系統支持的網絡協議眾多,不同協議的工作方式不同,地址格式也不同。因此,網間進程通信還要解決多重協議的識別問題。為了解決上述問題,TCP/IP協議引入了下列幾個概念。

端口

網絡中可以被命名和尋址的通信端口是操作系統可分配的一種資源。按照OSI七層協議的描述,傳輸層與網絡層最大的區別是傳輸層提供進程通信能力。從這個意義上講,網絡通信的最終地址就不僅是主機地址了,還包括可以描述進程的某種標識。為此TCP/IP協議提出了協議端口的概念,用於標識通信的進程。

端口是一種抽象的軟件結構,包括一些數據結構和I/O緩沖區。應用程序即進程通過系統調用與某端口建立連接(binding)後,傳輸層傳給該端口的數據都被相應的進程所接收,相應進程發給傳輸層的數據都從該端口輸出。在TCP/IP協議的實現中,端口操作類似於一般的I/O操作,進程獲取一個端口,相當於獲取本地唯一的I/O文件,可以用一般的讀寫原語訪問。

類似於文件描述符,每個端口都擁有一個叫端口號的整數描述符,以區別不同端口。由於TCP/IP傳輸層的兩個協議TCP和UDP是兩個完全獨立的軟件模塊,因此各自的端口號也相互獨立。如TCP有一個255號端口,UDP也可以有一個255號端口,兩者並不沖突。

端口號的分配是一個重要問題,有兩種基本分配方式:第一種叫全局分配這是一種集中分配方式,由一個公認的中央機構根據用戶需要盡行統一分配,並將結果公布於眾,第二種是本地分配,又稱動態連接,即進程需要訪問傳輸層服務時,向本地操作系統提出申請,操作系統返回本地唯一的端口號,進程再通過合適的系統調用,將自己和該端口連接起來(綁定)。TCP/IP端口號的分配綜合了兩種方式。TCP/IP將端口號分為兩部分,少量的作為保留端口,以全局方式分配給服務進程。因此,每一個標准服務器都擁有一個全局公認的端口叫周知口,即使在不同的機器上,其端口號也相同。剩余的為自由端口,以本地方式進行分配。TCP和UDP規定,小於256的端口才能
作為保留端口。

地址

網絡通信中的兩個進程分別在兩個不同的機器上。在互連網絡中,兩台機器可以位於不同的網絡,這些網絡通過網際互連設備(網關,網橋,路由器)連接。因此需要三級尋址。

1。某一主機與多個網絡相連,必須指定一特定網絡地址;
2。網絡上美一台主機應有其唯一的地址;
3。美一主機上的每一進程應有在該主機上的唯一標識。

主機地址就是IP啦,不必多說。進程唯一標識符是十六位整數端口號。網絡字節順序不同的計算機存放多字節值的順序不同,有的機器在起始地址存放低位字節,有的則相反。為保證數據的正確性,在網絡協議中需指定網絡字節順序。TCP/IP協議使用16位整數和32位整數的高價先存格式,他們均含在協議的頭文件中。

連接

兩個進程間的通信鏈路稱為連接。連接在內部表現為一些緩沖區和一組協議機制,在外部表現出比無連接高的可靠性。

半相關

綜上所述,網絡中用一個三元組可以在全局中唯一標是一個進程:
(協議,本機地址,本地端口號)
這樣一個三元組,叫做一個半相關,他指定連接的每半部分。

全相關

一個完整的網間進程通信需要有兩個進程組成,並且只能使用同一種高層協議。也就是說TCP和UDP沒法通信。因此一個完整的網間進程通信需要一個五元組來標識:
(協議,本機地址,本地端口號,遠地地址,遠地端口號)
這樣一個五元組叫做一個全相關。

客戶機/服務器模式

在TCP/IP網絡應用中,通信的兩個進程相互作用的主要模式是客戶機/服務器模式,即客戶端向服務器發出請求,服務器接收到請求後提供相應的服務客戶機/服務器模式的建立基於以下兩點:首先,建立網絡的起因是網絡中軟、硬件資源、運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。其次,網間進程通信完全是異步的,相互通信的進程間既不存在父子關系,又不共享內存緩沖區,因此需要一種機制為希望通信的進程間建立一種聯系,為二者的數據交換提供同步,這就是基於客戶機/服務器模式的TCP/IP。

客戶機/服務器模式在操作過程中采取的是主動請求方式:

首先服務器方要啟動,並根據請求提供相應服務:
1。打開一通信通道並告知本地主機,它願意在某一公認地址端口上(周知口,如http為80)接受客戶請求。
2。等待客戶請求到達該端口。
3。接收到重復服務請求,處理該請求並發送應答信號。接收並發服務請求,要激活一新進程來處理這個客戶請求。新進程處理此客戶請求,並不需要對其他請求做出應答。服務完成後,關閉此新進程與客戶的通信鏈路,並終止。
4。返回第二步,等待另外的客戶請求
5。關閉服務器。

客戶方:
1。打開一通信通道,並連接到服務器所在主機的特定端口。
2。向服務器發出服務請求報文,等待並接收應答;繼續提出請求。
3。請求結束後關閉通信通道並終止。
從上面的描述過程可知:
1。客戶與服務器進程的作用是非對稱的。因此編碼不同。
2。服務進程一般是先於客戶請求啟動的。只要系統運行,該進程一直存在,直到正常終止或者強迫終止。

套接字SOCKET和perl的socket編程

在UNIX世界中,網絡應用編程界面有兩類:BSD的套接字SOCKET和SYSTEM V的TLI.由於Sun公司采用了支持TCP/IP的BSD系統,TCP/IP的應用有了更大發展其網絡應用編程界面Socket在網絡編程中已成為標准。並且也早已經進入了MS的世界。

TCP/IP的Socket提供下列三種類型的套接字

1。流式套接字(SOCKET_STREAM)

提供了一個面向連接,可靠的數據傳輸服務,數據無差錯,無重復的發送且按發送順序接收。內設流量控制,避免數據流超限;數據被看作是字節流,無長度限制。FTP協議即采用流式套接字。

2。數據報式套接字(SOCKET_DGRAM)

提供了一個無連接服務。數據包以獨立包形式被發送,不提供無錯保證,數據可能丟失或重復,並且接收順序無序。網絡文件系統NFS使用數據報式套接字。

3。原始式套接字(SOCKET_RAW)

該接口允許對較低層次協議,如IP、ICMP直接訪問。常用於檢驗新的協議實現或訪問現有服務中配置的新設備。

基本套接字調用

創建套接字--socket();
綁定本機端口--bind();
建立連接--connect(),accept();
偵聽端口--listen();
數據傳輸--send(),recv();
輸入/輸出多路復用--select();
關閉套接字--closesocket();

不論何種語言,和socket打交道都是這一組調用只是在格式上有一點點差別。我只使用過c和perl,再加上這裡又不讓出現與perl無關的東西,那下面就主要討論PERL的socket編程啦:

創建建套接字:
socket(SOC_VARIABLE,DOMAIN_FLAG,connectType,num) #相應的C語言調用為so
ckid=socket(af,type,protocol)
參數含義如下:
SOC_VARIABLE是用於建立套接的句柄,相當於c裡面的sockid號;
DOMAIN_FLAG叫域標記,在C裡相當於af--address family,地址族。地址族和域是一個概念,其實就是平常所說的域。UNIX支持的域類型有
AF-UNIX; UNIX內部地址
AF-INET; TCP/IP地址
AF-NS; Xerox NS地址
AF-APPLETALK; Apple的Appletalk地址
而dos/windows支持的域地址族只有AF-INET.所以大部分的socket編程都只用到它。
connectType(c裡的type)就是前面所說的三種socket類型。
num相當於c裡面的protocol那大家一看就明白了這是協議號,用來指定SOCKET請求所希望的協議,這個參數不一定起作用,當前兩個參數可以確定協議時可以取值為零。
所以,一個完整的PERL的建立socket如下
socket(THESCK,AF-INET,SOCKET_STREAM,getprotocolbyname(''tcp''));
#c語言: int sockid;
# sockid = socket(AF-INET,SOCKET_STREAM,0);


補充:
Socket建立連接的過程

Linuxaid.com.cn 01-09-12 14:34 100p luster
--------------------------------------------------------------------------------


Socket建立連接的過程

建立過程如下:(connection-oriented)
server 方過程 client 方過程

socket() socket()
| |
bind() bind()
| |
listen() |
| |
accept()<------------------connect()
| |
recv()/send() <----------> send()/recv()

如果socket被置為block式,則connect()一直等到連接建立或出錯返回,否則立即返回.
出錯時返回-1, 錯誤碼在errno中.
如果讀寫一個沒有建立連接的socket則 返回-1, errno為EBADF.
Copyright © Linux教程網 All Rights Reserved