Linux下的C語言開發 網路程式設計

2021-07-14 12:30:11 字數 4573 閱讀 7254



在開始介紹網路程式設計的方法之前,我們可以回憶一下計算機網路的相關知識。目前為止,我們使用的最多網路協議還是tcp/ip網路。通常來說,我們習慣上稱為tcp/ip協議棧。至於協議棧分成幾層,有兩種說法。一種是五層,一種是七層,我個人本身也比較傾向於五層的劃分方法。大家可以通過下面的圖看看協議棧是怎麼劃分的。

5、應用層

4、傳輸層

3、網路層

2、資料鏈路層

1、物理層

網路的不同層次實現網路的不同功能。物理層主要實現報文的成幀處理;資料鏈路層完成對報文的優先順序的管理,同時實現二層**和流量控制;網路層實現路由和**的功能,一方面它需要實現對報文的fragment處理,另外一方面它還需要對路由資訊進行處理和儲存;傳輸層實現報文的傳送和接受,它利用計數、時序、定時器、重發等機制實現對報文的準確傳送,當然這都是tcp的傳送機制,而udp一般是不保證報文正確傳送和接收的;應用層就是根據傳輸層的埠資訊呼叫不同的程式來處理傳輸的內容,埠8080是http報文,埠21是ftp報文等等。上面的邏輯稍顯複雜,朋友們可以這麼理解,

物理層關心的是如何把電氣訊號變成一段報文;資料鏈路層關心的是mac位址、vlan、優先順序等;網路層關心的是ip位址,下一跳ip;傳輸層關心的是埠資源;應用層關心的是報文組裝、解析、渲染、儲存、執行等等。

目前關於tcp/ip完整協議棧的**很多,其中我認為寫得比較好的還是linux核心/net/ipv4下面的**。如果朋友們對ipv6的**感興趣,也可以看看/net/ipv6的**。檔案如果朋友們對整個協議棧的**結構理解得不是很清楚,可以參考《linux網路分析與開發》這本書。

當然,作為應用層,我們的其實考慮的不用這麼複雜。對於網路程式編寫人員來講,所有網路的資源只要和乙個socket關聯在一起就可以了。當然在socket可用之前,我們需要為它配置埠資訊和ip位址。配置完了之後,我們就可以慢慢等待報文的收發了。所以一般來說,作為伺服器端口的處理流程是這樣的,

a) 建立socket

b) 繫結socket到特定的ip位址

c) 對socket進行偵聽處理

d) 接受socket,表明有客戶端和伺服器連線

e) 和客戶端迴圈收發報文

f) 關閉socket

作為伺服器程式而言,它要對特定的埠進行繫結和偵聽處理,這樣稍顯複雜。但是如果是編寫客戶端的程式,一切的一切就變得非常簡單了,

a) 建立socket

b) 鏈結伺服器端位址

c) 和伺服器端的socket收發報文

上面只是對網路程式設計做了乙個基本的介紹,但是好多的東西還是沒有涉及到,比如說:(1) 什麼時候該使用udp,什麼時候該使用tcp?(2) 如何把多執行緒和網路程式設計聯絡在一起? (3) 如何把多程序和網路程式設計聯絡在一起? (4) 如何利用select函式、epoll_create機制、非阻塞函式提高socket的併發處理效率? (5) linux核心是怎麼實現tcp/ip協議的? (6) 我們自己是否也可以實現協議的處理流程等等?

這裡給出在linux下的簡單socket網路程式設計的例項,使用tcp協議進行通訊,服務端進行監聽,在收到客戶端的連線後,傳送資料給客戶端;客戶端在接受到資料後列印出來,然後關閉。程式裡有詳細的說明,其中對具體的結構體和函式的實現可以參考其他資料。

移植時服務端可以不用更改,編譯後可直接執行;客戶端將ip改為伺服器的位址,然後編譯執行。可以使用netstat 進行檢視相應的執行狀態。

/*************************************

檔名: server.c

linux 下socket網路程式設計簡例 - 服務端程式

伺服器端口設為 0x8888 (埠和位址可根據實際情況更改,或者使用引數傳入)

伺服器位址設為 192.168.1.104

*/#include #include #include #include #include #include int main()

printf("socket ok !\r\n");

/* 填充伺服器埠位址資訊,以便下面使用此位址和埠監聽 */

bzero(&s_add,sizeof(struct sockaddr_in));

s_add.sin_family=af_inet;

s_add.sin_addr.s_addr=htonl(inaddr_any); /* 這裡位址使用全0,即所有 */

s_add.sin_port=htons(portnum);

/* 使用bind進行繫結埠 */

if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))

printf("bind ok !\r\n");

/* 開始監聽相應的埠 */

if(-1 == listen(sfp,5))

printf("listen ok\r\n");

while(1)

printf("accept ok!\r\nserver start get connect from %#x : %#x\r\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));

/* 這裡使用write向客戶端傳送資訊,也可以嘗試使用其他函式實現 */

if(-1 == write(nfp,"hello,welcome to my server \r\n",32))

printf("write ok!\r\n");

close(nfp);

}close(sfp);

return 0;

}

/*************************************

檔名: client.c

linux 下socket網路程式設計簡例 - 客戶端程式

伺服器端口設為 0x8888 (埠和位址可根據實際情況更改,或者使用引數傳入)

伺服器位址設為 192.168.1.104

*/#include #include #include #include #include #include int main()

; /* 接受緩衝區 */

struct sockaddr_in s_add,c_add; /* 儲存服務端和本端的ip、埠等資訊結構體 */

unsigned short portnum=0x8888; /* 服務端使用的通訊埠,可以更改,需和服務端相同 */

printf("hello,welcome to client !\r\n");

/* 建立socket 使用網際網路,tcp流傳輸 */

cfd = socket(af_inet, sock_stream, 0);

if(-1 == cfd)

printf("socket ok !\r\n");

/* 構造伺服器端的ip和埠資訊,具體結構體可以查資料 */

bzero(&s_add,sizeof(struct sockaddr_in));

s_add.sin_family=af_inet;

s_add.sin_addr.s_addr= inet_addr("192.168.1.104"); /* ip轉換為4位元組整形,使用時需要根據服務端ip進行更改 */

s_add.sin_port=htons(portnum); /* 這裡htons是將short型資料字節序由主機型轉換為網路型,其實就是

將2位元組資料的前後兩個位元組倒換,和對應的ntohs效果、實質相同,只不過名字不同。htonl和ntohl是

操作的4位元組整形。將0x12345678變為0x78563412,名字不同,內容兩兩相同,一般情況下網路為大端,

ppc的cpu為大端,x86的cpu為小端,arm的可以配置大小端,需要保證接收時位元組序正確。

*/printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port); /* 這裡列印出的是小端

和我們平時看到的是相反的。 */

/* 客戶端連線伺服器,引數依次為socket檔案描述符,位址資訊,位址結構大小 */

if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))

printf("connect ok !\r\n");

/*連線成功,從服務端接收字元*/

if(-1 == (recbytes = read(cfd,buffer,1024)))

printf("read ok\r\nrec:\r\n");

buffer[recbytes]='\0';

printf("%s\r\n",buffer);

getchar(); /* 此句為使程式暫停在此處,可以使用netstat檢視當前的連線 */

close(cfd); /* 關閉連線,本次通訊完成 */

return 0;

}

執行截圖

linux下的C語言開發(網路程式設計)

在開始介紹網路程式設計的方法之前,我們可以回憶一下計算機網路的相關知識。目前為止,我們使用的最多網路協議還是tcp ip網路。通常來說,我們習慣上稱為tcp ip協議棧。至於協議棧分成幾層,有兩種說法。一種是五層,一種是七層,我個人本身也比較傾向於五層的劃分方法。大家可以通過下面的圖看看協議棧是怎麼...

linux下的C語言開發(網路程式設計)

在開始介紹網路程式設計的方法之前,我們可以回憶一下計算機網路的相關知識。目前為止,我們使用的最多網路協議還是tcp ip網路。通常來說,我們習慣上稱為tcp ip協議棧。至於協議棧分成幾層,有兩種說法。一種是五層,一種是七層,我個人本身也比較傾向於五層的劃分方法。大家可以通過下面的圖看看協議棧是怎麼...

linux下的C語言開發 網路程式設計

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!在開始介紹網路程式設計的方法之前,我們可以回憶一下計算機網路的相關知識。目前為止,我們使用的最多網路協議還是tcp ip網路。通常來說,我們習慣上稱為tcp ip協議棧。至於協議棧分成幾層,有兩種說法。一種是五層,一種是七層,我個人本身也比較傾向於...