在學習linux程式設計時,學會網路程式設計是必不可少的,而linux網路程式設計一般通過socket(套接字)介面實現。在學習socket程式設計之前,我們首先要了解相關網路協議。
linux中繼續使用tcp/ip的網路層結構,即從下到上分為物理層,資料鏈路層,網路層,傳輸層 ,會話層,表示層,應用層。其中,傳輸層在實現通訊服務時發揮了重要作用。傳輸層定義了tcp以及udp協議。tcp是面向連線的通訊協議,提供可靠的資料傳送。tcp將源主機應用層的資料分為多個分段,將每個分段傳輸到網際層,網際層將資料封裝為ip資料報,併發送到目的主機。
網路結構模式分為兩種:客戶機/伺服器模式以及瀏覽器/伺服器模式,在這裡主要圍繞客戶機/伺服器模式展開。乙個完整的tcp程式設計流程如下:伺服器呼叫socket,bind,listen函式完成初始化,接著呼叫accept函式阻塞等待,此時伺服器處於監聽埠的狀態。客戶端呼叫socket函式進行初始化,接著呼叫connect函式發出syn段並阻塞,等待伺服器應答。伺服器應答乙個syn-ack段,客戶端收到後從connect函式返回,同時應答乙個ack段,伺服器收到後從accept函式返回。此時,連線已經成功建立,可以開始傳輸資料了。一般由客戶端發出請求,伺服器處理請求,進行一問一答的方式。所以,伺服器從accept函式返回後,呼叫read函式讀取客戶端的請求,如果沒有請求就阻塞等待。客戶端呼叫write函式傳送請求,伺服器收到請求後從read函式返回,對客戶端的請求進行處理,在此期間伺服器段接著呼叫read函式阻塞等待客戶端的下一條請求。客戶端,伺服器之間傳送,傳輸資料可以用send,recv函式實現。最後,資料傳輸完畢,客戶端呼叫close函式關閉連線,伺服器的read函式就會返回0,伺服器就知道客戶端關閉了連線,也呼叫close函式關閉連線。
套接字是一種通訊機制,用於描述ip位址和埠,是一種特殊的i/o。我們常用流式套接字,即sock_stream,它提供了乙個可靠的,面向連線的資料傳輸服務,資料無差錯無重複地傳送且按傳送順序接受。
int socket(int domain, int type, int protocol) #用於建立乙個新的套接字
#domain又稱為協議族,決定了套接字的位址型別以及在通訊中必須採用對應的位址,常用套接字有af_inet,af_inet6…af_inet決定了要用ipv4位址(32位)與埠號(16位)的組合。
#type指定了套接字型別,常用的套接字型別有sock_stream,sock_dgrom等
#protocol用於指定協議,常用的協議有:ipproto_tcp(tcp協議),ipptoto_udp(udp協議)等,一般置為0,表示使用預設協議。
int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen) #將乙個套接字繫結到乙個位址上,使得客戶端可以連線
#sockfd:上乙個socket呼叫中獲得的檔案描述符
#addr指向包含繫結位址的結構的指標
#addrlen指的是位址結構的大小
乙個struct sockaddr_in 結構如下:
struct sockaddr_in servaddr; //結構體定義
bzero(&servaddr, sizeof(servaddr)); //結構體清零
servaddr.sin_family = af_inet; //設定位址型別為af_inet
servaddr.sin_addr.s_addr = htonl(inaddr_any);//設定網路位址為inaddr_any
servaddr.sin_port = htons(6666); //設定埠號為6666
int listen(int sockfd, int backlog)
#sockfd:socket呼叫中獲得的檔案描述符
#backlog:sockfd掛起的已連線佇列可以增長的最大長度
int accept(int sockfd, struct sockaddr * addr, socklen_t * addrlen) #建立客戶端程式對該套接字的連線
#sockfd:socket呼叫中獲得的檔案描述符
#addr:指向連線對端的位址,即客戶端位址
#addrlen指定位址結構的大小
int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen) #用於客戶端建立連線,發起三次握手過程。如果連線不能立刻建立起來,connect呼叫會阻塞一段不確定的倒計時時間,這段倒計時時間結束後這次連線就會失敗。
#sockfd:socket呼叫中獲得的檔案描述符
#addr指向伺服器位址
#addrlen指定位址結構的大小
int send(int sockfd, const void * buf, size_t len, int flags) #用於傳送資料
#sockfd:socket呼叫中獲得的檔案描述符
#buf:指向傳送資料的指標
#len:資料的長度
#flags:一般置為0
int recv(int sockfd, const void * buf, size_t len, int flags)
#sockfd:socket呼叫中獲得的檔案描述符
#buf:要讀取資訊的緩衝
#len:緩衝的最大長度
#flags:一般置為0
int close(int fd) #釋放系統分配給套接字的資源,關閉連線
#fd:檔案描述符,在socket程式設計中指sockfd
//伺服器端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define serv_port 6666
#define buf_size 5000
#define file_name_max_size 500
void
fatal
(char
*string)
intmain()
close
(fd)
;close
(sa);}
return0;
}
//客戶端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define serv_port 6666
#define buf_size 5000
#define path " "
//定義檔案位置
#define dest_ip "127.0.0.1"
//ip位址設定為本機
void
fatal
(char
*s)int
main()
c =connect
(listenfd,
(struct sockaddr *
)&cliaddr,
sizeof
(cliaddr));
if(c <0)
fatal
("connect failed");
send
(listenfd, path,
strlen
(path),0
);while(1
)return0;
}
以上程式實現了客戶端與伺服器建立連線,客戶端請求乙個文件並顯示。 Linux核心網路協議棧8 socket監聽
幾個問題 了解以下幾個問題的同學可以直接忽略下文 1 listen 庫函式主要做了什麼?2 什麼是最大併發連線請求數?3 什麼是等待連線佇列?socket 監聽相對還是比較簡單的,先看下應用程式 listen server sockfd,5 其中,第乙個引數 server sockfd為服務端 so...
LINUX程式設計 socket程式設計
什麼是套接字 套接字是一種通訊過程,它使客戶 伺服器系統的開發工作既可以在本地單機上進行,也可以跨網路進行。套接字建立過程 1,建立乙個套接字,這是分配給該伺服器程序的乙個作業系統資源,套接字由伺服器通過系統呼叫socket建立出來的,所以其它程序將不能對它進行訪問。2,給套接字起個名字,用系統呼叫...
SOCKET程式設計(LINUX)
現在的網路程式設計幾乎都是用的socket 本地的程序間通訊 ipc 有很多種方式,但可以總結為下面4類 2.我們要討論的是網路中程序之間如何通訊?在本地可以通過程序pid來唯一標識乙個程序,但是在網路中這是行不通的。三元組 ip位址,協議,埠 就可以標識網路的程序了,網路中的程序通訊就可以利用這個...