Linux程序間通訊 使用流套接字

2021-08-27 14:35:36 字數 4580 閱讀 1874

前面說到的程序間的通訊,所通訊的程序都是在同一臺計算機上的,而使用socket進行通訊的程序可以是同一臺計算機的程序,也是可以是通過網路連線起來的不同計算機上的程序。通常我們使用socket進行網路程式設計,這裡將會簡單地講述如何使用socket進行簡單的網路程式設計。

一、什麼是socket

socket,即套接字是一種通訊機制,憑藉這種機制,客戶/伺服器(即要進行通訊的程序)系統的開發工作既可以在本地單機上進行,也可以跨網路進行。也就是說它可以讓不在同一臺計算機但通過網路連線計算機上的程序進行通訊。也因為這樣,套接字明確地將客戶端和伺服器區分開來。

二、套接字的屬性

套接字的特性由3個屬性確定,它們分別是:域、型別和協議。

1、套接字的域

它指定套接字通訊中使用的網路介質,最常見的套接字域是af_inet,它指的是internet網路。當客戶使用套接字進行跨網路的連線時,它就需要用到伺服器計算機的ip位址和埠來指定一台聯網機器上的某個特定服務,所以在使用socket作為通訊的終點,伺服器應用程式必須在開始通訊之前繫結乙個埠,伺服器在指定的埠等待客戶的連線。另乙個域af_unix表示unix檔案系統,它就是檔案輸入/輸出,而它的位址就是檔名。

2、套接字型別

網際網路提供了兩種通訊機制:流(stream)和資料報(datagram),因而套接字的型別也就分為流套接字和資料報套接字。這裡主要講流套接字。

流套接字由型別sock_stream指定,它們是在af_inet域中通過tcp/ip連線實現,同時也是af_unix中常用的套接字型別。流套接字提供的是乙個有序、可靠、雙向位元組流的連線,因此傳送的資料可以確保不會丟失、重複或亂序到達,而且它還有一定的出錯後重新傳送的機制。

與流套接字相對的是由型別sock_dgram指定的資料報套接字,它不需要建立連線和維持乙個連線,它們在af_inet中通常是通過udp/ip協議實現的。它對可以傳送的資料的長度有限制,資料報作為乙個單獨的網路訊息被傳輸,它可能會丟失、複製或錯亂到達,udp不是乙個可靠的協議,但是它的速度比較高,因為它並一需要總是要建立和維持乙個連線。

3、套接字協議

只要底層的傳輸機制允許不止乙個協議來提供要求的套接字型別,我們就可以為套接字選擇乙個特定的協議。通常只需要使用預設值。

三、套接字位址

每個套接字都有其自己的位址格式,對於af_unix域套接字來說,它的位址由結構sockaddr_un來描述,該結構定義在標頭檔案sys/un.h中,它的定義如下:

struct sockaddr_un;

struct sockaddr_in;
而in_addr被定義為:

struct in_addr;
四、基於流套接字的客戶/伺服器的工作流程

使用socket進行程序通訊的程序採用的客戶/伺服器系統是如何工作的呢?

1、伺服器端

首先伺服器應用程式用系統呼叫socket來建立乙個套接安,它是系統分配給該伺服器程序的類似檔案描述符的資源,它不能與其他的程序共享。

接下來,伺服器程序會給套接字起個名字,我們使用系統呼叫bind來給套接字命名。然後伺服器程序就開始等待客戶連線到這個套接字。

然後,系統呼叫listen來建立乙個佇列並將其用於存放來自客戶的進入連線。

最後,伺服器通過系統呼叫accept來接受客戶的連線。它會建立乙個與原有的命名套接不同的新套接字,這個套接字只用於與這個特定客戶端進行通訊,而命名套接字(即原先的套接字)則被保留下來繼續處理來自其他客戶的連線。

2、客戶端

基於socket的客戶端比伺服器端簡單,同樣,客戶應用程式首先呼叫socket來建立乙個未命名的套接字,然後將伺服器的命名套接字作為乙個位址來呼叫connect與伺服器建立連線。

一旦連線建立,我們就可以像使用底層的檔案描述符那樣用套接字來實現雙向資料的通訊。

五、流式socket的介面及作用

socket的介面函式宣告在標頭檔案sys/types.h和sys/socket.h中。

1、建立套接字——socket系統呼叫

該函式用來建立乙個套接字,並返回乙個描述符,該描述符可以用來訪問該套接字,它的原型如下:

int socket(int domain, int type, int protocol);
函式中的三個引數分別對應前面所說的三個套接字屬性。protocol引數設定為0表示使用預設協議。

2、命名(繫結)套接字——bind系統呼叫

該函式把通過socket呼叫建立的套接字命名,從而讓它可以被其他程序使用。對於af_unix,呼叫該函式後套接字就會關聯到乙個檔案系統路徑名,對於af_inet,則會關聯到乙個ip埠號。函式原型如下:

int bind( int socket, const struct sockaddr *address, size_t address_len);
成功時返回0,失敗時返回-1;

3、建立套接字佇列(監聽)——listen系統呼叫

該函式用來建立乙個佇列來儲存未處理的請求。成功時返回0,失敗時返回-1,其原型如下:

int listen(int socket, int backlog);
backlog用於指定佇列的長度,等待處理的進入連線的個數最多不能超過這個數字,否則往後的連線將被拒絕,導致客戶的連線請求失敗。呼叫後,程式一直會監聽這個ip埠,如果有連線請求,就把它加入到這個佇列中。

4、接受連線——accept系統呼叫

該系統呼叫用來等待客戶建立對該套接字的連線。accept系統呼叫只有當客戶程式試圖連線到由socket引數指定的套接字上時才返回,也就是說,如果套接字佇列中沒有未處理的連線,accept將阻塞直到有客戶建立連線為止。accept函式將建立乙個新套接字來與該客戶進行通訊,並且返回新套接字的描述符,新套接字的型別和伺服器監聽套接字型別是一樣的。它的原型如下:

int accept(int socket, struct sockaddr *address, size_t *address_len);
address為連線客戶端的位址,引數address_len指定客戶結構的長度,如果客戶位址的長度超過這個值,它將會截斷。

5、請求連線——connect系統呼叫

該系統呼叫用來讓客戶程式通過在乙個未命名套接字和伺服器監聽套接字之間建立連線的方法來連線到伺服器。它的原型如下:

int connect(int socket, const struct sockaddr *address, size_t address_len);
引數socket指定的套接字連線到引數addres指定的伺服器套接字。成功時返回0,失敗時返回-1.

6、關閉socket——close系統呼叫

該系統呼叫用來終止伺服器和客戶上的套接字連線,我們應該總是在連線的兩端(伺服器和客戶)關閉套接字。

六、程序使用流式socket進行通訊

下面用多個客戶程式和乙個伺服器程式來展示程序間如何利用套接字進行通訊。

sockserver.c是乙個伺服器程式,它首先建立套接字,然後繫結乙個埠再監聽套接字,忽略子程序的停止訊息等,然後它進入迴圈,一直迴圈檢查是否有客戶連線到伺服器,如果有,則呼叫fork建立乙個子程序來處理請求。利用read系統呼叫來讀取客戶端發來的資訊,利用write系統呼叫來向客戶端傳送資訊。這個伺服器的工作非常簡單,就是把客戶發過來的字元+1,再傳送回給客戶。

sockclient.c是乙個客戶程式,它同樣要先建立套接,然後連線到指定ip埠伺服器,如果連線成功,就用write來傳送資訊給伺服器,再用read獲取伺服器處理後的資訊,再輸出。

伺服器sockserver.c的源**如下:

#include #include #include #include #include #include #include int main()

else}}

客戶sockclient.c的源**如下:

#include #include #include #include #include #include #include int main()

//傳送請求給伺服器

write(sockfd, &ch, 1);

//從伺服器獲取資料

read(sockfd, &ch, 1);

printf("char form server = %c\n", ch);

close(sockfd);

exit(0);

}

執行結果如下:

在本例子中,我們啟動了乙個伺服器程式和三個客戶程式,從執行的結果來看,客戶端傳送給伺服器程式的所有請求都得到了處理,即把a變成了b。對於伺服器和客戶程式之間使用的read和write系統呼叫跟使用命名管道時阻塞的read、write系統呼叫一樣。例如客戶程式呼叫read時,如果伺服器程式沒有向指定的客戶程式的socket中寫入資訊,則read呼叫會一直阻塞。

七、流式套接字給我印象

給我的感覺是流式套接字很像命名管道,但是它卻可以使不在同一臺計算機而通過網路連線的不同計算機上的程序進行通訊,功能真是非常的強大。

Linux程序間通訊 使用資料報套接字

前一篇文章,linux程序間通訊 使用流套接字 一 簡單回顧 什麼是資料報套接字。socket,即套接字是一種通訊機制,憑藉這種機制,客戶 伺服器 即要進行通訊的程序 系統的開發工作既可以在本地單機上進行,也可以跨網路進行。也就是說它可以讓不在同一臺計算機但通過網路連線計算機上的程序進行通訊。也因為...

Linux程序間通訊 使用資料報套接字

前一篇文章,linux程序間通訊 使用流套接字介紹了一些有關socket 套接字 的一些基本內容,並講解了流套接字的使用,這篇文章將會給大家講講,資料報套接字的使用。一 簡單回顧 什麼是資料報套接字。socket,即套接字是一種通訊機制,憑藉這種機制,客戶 伺服器 即要進行通訊的程序 系統的開發工作...

Linux程序間通訊 使用匿名管道

在前面,介紹了一種程序間的通訊方式 使用訊號,我們建立通知事件,並通過它引起響應,但傳遞的資訊只是乙個訊號值。這裡將介紹另一種程序間通訊的方式 匿名管道,通過它程序間可以交換更多有用的資料。一 什麼是管道 如果你使用過linux的命令,那麼對於管道這個名詞你一定不會感覺到陌生,因為我們通常通過符號 ...