Linux嵌入式之 網路程式設計socket

2021-07-11 05:37:47 字數 3616 閱讀 8453

socket是應用層與tcp/ip協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,

socket其實就是乙個門面模式,它把複雜的tcp/ip協議族隱藏在socket介面後面,對使用者來說,

一組簡單的介面就是全部,讓socket去組織資料,以符合指定的協議。

門面模式,用自己的話說,就是系統對外界提供單一的介面,外部不需要了解內部的實現

socket起源於unix,而unix/linux基本哲學之一就是「一切皆檔案」,

都可以用「開啟open –> 讀寫write/read –> 關閉close」模式來操作。

我的理解就是socket就是該模式的乙個實現,socket即是一種特殊的檔案,一些socket函式就是對

其進行的操作(讀/寫io、開啟、關閉)

tcp/ip(transmission control protocol/internet protocol)即傳輸控制協議/網間協議,

是乙個工業標準的協議集,它是為廣域網(wans)設計的。

udp(user data protocol,使用者資料報協議)是與tcp相對應的協議。它是屬於tcp/ip協議族中的一種。

要實現網路中程序之間的通訊,那麼就要解決乙個問題,如何唯一標識乙個程序?

否則,通訊就無從談起。在本地可以通過程序pid來唯一標識乙個程序,但是在網路中這是行不通的。

其實tcp/ip協議族已經幫我們解決了這個問題,網路層的「ip位址」可以唯一標識網路中的主機,而

傳輸層的「協議+埠」可以唯一標識主機中的應用程式(程序)。這樣利用三元組(ip位址,協議,埠)

就可以標識網路的程序了,網路中的程序通訊就可以利用這個標誌與其它程序進行互動。

使用tcp/ip協議的應用程式通常採用應用程式設計介面:unix  bsd的套接字(socket)和

unix system v的tli(已經被淘汰),來實現網路程序之間的通訊。就目前而言,幾乎所有的應用程式都是採用socket,

而現在又是網路時代,網路中程序通訊是無處不在。

int socket(int domain, int type, int protocol);

socket函式對應於普通檔案的開啟操作。普通檔案的開啟操作返回乙個檔案描述字,

而socket()用於建立乙個socket描述符(socket descriptor),它唯一標識乙個socket。

這個socket描述字跟檔案描述字一樣,後續的操作都有用到它,把它作為引數,通過它來進行一些讀寫操作。

正如可以給fopen的傳入不同引數值,以開啟不同的檔案。建立socket的時候,也可以指定不同的引數建立

不同的socket描述符,socket函式的三個引數分別為:

domain:即協議域,又稱為協議族(family)。常用的協議族有,af_inet、af_inet6、

af_local(或稱af_unix,unix域socket)、af_route等等。協議族 決定了socket的位址型別,

在通訊中必須採用對應的位址,如af_inet決定了要用ipv4位址(32位的)與埠號(16位的)的組合、

sock_stream、sock_dgram、sock_raw、sock_packet、sock_seqpacket等等

protocol:故名思意,就是指定協議。常用的協議有:

ipproto_tcp、ipptoto_udp、ipproto_sctp、ipproto_tipc等,它們分別對應

tcp傳輸協議、udp 傳輸協議、stcp傳輸協議、tipc傳輸協議

注意:並不是上面的type和protocol可以隨意組合的,如sock_stream不可以跟ipproto_udp組合。

當protocol為0時,會自動選擇type型別對應的預設協議。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind()函式把乙個位址族中的特定位址賦給socket。例如對應af_inet、af_inet6就是把乙個ipv4或ipv6位址和埠號組合賦給socket。即將位址、埠和socket返回的描述符做乙個繫結

sockfd:即socket描述字,它是通過socket()函式建立了,唯一標識乙個socket。bind()函式就是將給這個描述字繫結乙個名字。

addr:乙個const struct sockaddr *指標,指向要繫結給sockfd的協議位址。這個位址結構根據位址建立socket時的位址協議族的不同而不同。

如如ipv4對應的是:

struct sockaddr_in ;

/* internet address. */

struct in_addr ;

ipv6對應的是:

struct sockaddr_in6 ;

struct in6_addr ;

如果作為乙個伺服器,在呼叫socket()、bind()之後就會呼叫listen()來監聽這個socket,如果客戶端這時呼叫connect()發出連線請求,伺服器端就會接收到這個請 求。

int listen(int sockfd, int backlog);

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

listen函式的第乙個引數即為要監聽的socket描述字,第二個引數為相應socket可以排隊的最大連線個數。socket()函式建立的socket預設是乙個主動型別的,

listen函式將socket變為被動型別的,等待客戶的連線請求。

connect函式的第乙個引數即為客戶端的socket描述字,第二引數為伺服器的socket位址,第三個引數為socket位址的長度。客戶端通過呼叫connect函式來建立與 tcp伺服器的連線。

tcp伺服器端依次呼叫socket()、bind()、listen()之後,就會監聽指定的socket位址了。tcp客戶端依次呼叫socket()、connect()之後就想tcp伺服器傳送了乙個連 接請求。tcp伺服器監聽到這個請求之後,就會呼叫accept()函式取接收請求,這樣連線就建立好了。之後就可以開始網路i/o操作了,即類同於普通檔案的讀寫i/o操 作。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept函式的第乙個引數為伺服器的socket描述字,第二個引數為指向struct sockaddr *的指標,用於返回客戶端的協議位址,第三個引數為協議位址的長度。

如果accpet成功,那麼其返回值是由核心自動生成的乙個全新的描述字,代表與返回客戶的tcp連線。即返回的fd與客戶端socket返回的fd一一對應,這樣就能進行通訊了

伺服器與客戶已經建立好連線了之後。就可以呼叫網路i/o進行讀寫操作了,即實現了網咯中不同程序之間的通訊!

int read(int fd, void *buf, size_t count);

int write(int fd, const void *buf, size_t count);

當然用完socket之後肯定是要關閉的

嵌入式Linux網路程式設計

osi 七層模型 理想模型 應用層 表示層 會話層 傳輸層 網路層 資料鏈路層 物理層 tcp ip 四層模型 廣泛應用 應用層 傳輸層 網路層 internet 網路介面層 hw 網絡卡 對應關係 tcp ip模型各層對應的協議 應用層協議 http ftp telnet 傳輸層協議 埠號工作在該...

嵌入式Linux網路程式設計(一)

網路協議 國際標準組織 iso 制定了osi模型,把網路通訊分為7層。而tcp ip將網路通訊分為4層 應用層,傳輸層,網路互連層,網路介面層。socket介面是tcp ip網路的api,定義了許多函式和例子。1 結構體sockaddr struct sockaddr sa family 一般是af...

嵌入式程式設計

1 interrupt double compute area double radis 1 isr不能返回乙個值。2 isr不能傳遞引數。3 在許多處理器中浮點是不可重入的。4 printf 經常有重入和效能上的問題,所以一般不使用printf 2.volatile 1 volatile的語法和c...