If you spend too much time thinking about a thing, you’ll never get it done. —Bruce Lee 學(xué)習(xí)網(wǎng)絡(luò)編程也一段時(shí)間了,剛開始看《UNIX網(wǎng)絡(luò)編程》的時(shí)候,,覺得這本厚厚的書好難?。】吹胶髞?,發(fā)現(xiàn)并沒有想象中的那么難,。如果你是新手,建議你看到第二部分結(jié)束后,,開始著手寫代碼,。不寫代碼肯定是不行的???00遍也沒有敲一遍實(shí)現(xiàn)一遍來的清楚,。敲完以后,帶著問題去看書,,你會(huì)更加有針對(duì)性,。提高的速度是飛快的,這也是學(xué)習(xí)任何一本書,、一門語言的唯一手段,。 寫這個(gè)博客也是因?yàn)閯傞_始學(xué)的時(shí)候,查了好多別人寫的東西,,百度了以后,,發(fā)現(xiàn)大家只是把所有的代碼一貼。并沒有講解每個(gè)函數(shù)的功能,。我甚至不知道哪個(gè)函數(shù)是哪個(gè)頭文件下的,。造成我對(duì)函數(shù)很不理解。下面我會(huì)對(duì)每個(gè)函數(shù)的功能,,和它的頭文件以及函數(shù)原型寫出來,,讓大家參考,第一次寫博客,,有什么錯(cuò)誤的地方,,希望大家指正,。可以在下面給我留言,,也是我繼續(xù)寫下去的動(dòng)力,。 我很希望和大家一起分享學(xué)習(xí)網(wǎng)絡(luò)編程遇到的種種困難與不順,也希望和大家一起討論其中遇到的問題,,一起成長(zhǎng),,如果你剛開始打算學(xué)習(xí)網(wǎng)絡(luò)編程,那這篇文章一定能給你一些幫助,。 我的郵箱:[email protected],,轉(zhuǎn)載請(qǐng)注明出處:http://www.cnblogs.com/yusenwu/p/4579167.html。 關(guān)于怎樣介紹這個(gè)簡(jiǎn)單的實(shí)例:(基本上涵蓋了《UNIX網(wǎng)絡(luò)編程》1-5章的內(nèi)容,,更深,,更細(xì)的,需要我們?cè)偌?xì)讀這本書) --> 1,、代碼展示,,功能介紹 --> 2、首先介紹一下客戶端和服務(wù)端中函數(shù)的功能以及函數(shù)的原形,。 --> 3,、關(guān)于連接三次握手和TCP連接關(guān)閉時(shí)候的分組交換 --> 4、IPv4,、IPv6套接字的地址結(jié)構(gòu) --> 5、一些好的學(xué)習(xí)網(wǎng)站總結(jié) --> 6,、代碼下載 --> 7,、總結(jié) --> 8、實(shí)現(xiàn)一個(gè)echo的實(shí)例,,代碼可以到Github上下載 client.c 按 Ctrl+C 復(fù)制代碼 按 Ctrl+C 復(fù)制代碼 -執(zhí)行:gcc client.c -o client 后啟動(dòng) ./client 客戶端程序 啟動(dòng)前先啟動(dòng)./server----------------------------------------- server.c 按 Ctrl+C 復(fù)制代碼 按 Ctrl+C 復(fù)制代碼 -執(zhí)行:gcc server.c -o server 后啟動(dòng) ./server 服務(wù)端程序-------------------------------------------------------
> 1,、代碼展示,功能介紹 上面這個(gè)簡(jiǎn)單的socket通信的代碼要實(shí)現(xiàn)的功能:從客戶端發(fā)送一條消息后,,服務(wù)端接收這條消息,,并在服務(wù)端顯示(recv msg from client:****)。
> 2,、首先介紹一下客戶端和服務(wù)端中函數(shù)的功能以及函數(shù)的原形,。 #include <sys/socket.h> int socket(int family, int type, int protocol); //指定期望的通信協(xié)議類型,返回的文件描述符和套接字描述符類似,,我們成為套接字描述符,,簡(jiǎn)稱sockfd family:協(xié)議族
type:套接字的類型
protocol:協(xié)議類型的常量或設(shè)置為0,以選擇給定的family和type組合的系統(tǒng)默認(rèn)值
#include<arpa/inet.h> int inet_pton(int family,const char *strptr,void *addrptr);//成功返回1,,格式不對(duì)返回0,,出錯(cuò)返回-1 #include <sys/socket.h> int connect(int sockfd,const struct sockaddr* servaddr,socklen_t addrlen);//用connect函數(shù)來建立與TCP服務(wù)器的連接 #include<unistd.h> int close(int sockfd);//關(guān)閉socket,,并終止TCP連接 #include <sys/socket.h> int bind(int sockfd,const struct* myaddr,socklen_t addrlen);//把本地協(xié)議地址賦予一個(gè)套接字。也就是將32位的IPv4或128位ipv6與16位的TCP或者UDP組合,。 #include<sys/socket.h> int listen(int sockfd,int backlog)//成功返回0,失敗返回-1 listen函數(shù)僅由TCP服務(wù)器調(diào)用 #include <sys/socket.h> int accept(int sockfd,struct sockaddr* cliaddr,socklen_t *addrlen);//成功返回描述符,失敗返回-1
總結(jié):我們學(xué)校的實(shí)驗(yàn)室是云計(jì)算實(shí)驗(yàn)室,,有很多的集群,,我在上面開了2臺(tái)虛擬機(jī),,在兩臺(tái)Linux系統(tǒng)上跑,??梢猿晒邮铡V灰獙P設(shè)置好即可,,注意,關(guān)掉防火墻:service iptables stop; > 3,、關(guān)于連接三次握手和TCP連接關(guān)閉時(shí)候的分組交換 三次握手: 為了更好的理解connect、bind、close三個(gè)函數(shù),了解一下TCP連接的建立和終止是很有必要的,。(請(qǐng)務(wù)必理解理解上面的所有的函數(shù)后,,再看這節(jié)),。 1,、服務(wù)器首先必須被打開,等待準(zhǔn)備接受外來的連接,。我們上面的例子用到了socket,、bind,、listen這3個(gè)函數(shù),。之后,我們稱為服務(wù)端被被動(dòng)打開了。 2,、客戶端是通過connect發(fā)起主動(dòng)打開,。
3,、主動(dòng)打開后,,客戶TCP發(fā)送了一個(gè)SYN(同步)分節(jié),,它告訴服務(wù)器客戶將在連接中只發(fā)送的數(shù)據(jù)的初始序列號(hào),SYN分節(jié)不攜帶數(shù)據(jù),。它發(fā)送的IP數(shù)據(jù)報(bào),,只有一個(gè)IP首部、一個(gè)TCP首部以及TCP選項(xiàng),。 4,、服務(wù)器必須確認(rèn)(ACK)客戶的SYN,,同時(shí)自己也發(fā)送一個(gè)SYN分節(jié),,它含有服務(wù)器將在同一連接中發(fā)送的數(shù)據(jù)的初始序列號(hào),。服務(wù)器在單個(gè)分節(jié)中發(fā)送SYN和對(duì)客戶SYN的ACK確認(rèn)(+1),。 5、客戶必須確認(rèn)服務(wù)器的SYN分節(jié),。 上面的過程稱為TCP的三次握手。 注:SYN(synchronous)是TCP/IP建立連接時(shí)使用的握手信號(hào),。在客戶機(jī)和服務(wù)器之間建立正常的TCP網(wǎng)絡(luò)連接時(shí),,客戶機(jī)首先發(fā)出一個(gè)SYN消息,,服務(wù)器使用SYN+ACK應(yīng)答表示接收到了這個(gè)消息,最后客戶機(jī)再以ACK消息響應(yīng),。這樣在客戶機(jī)和服務(wù)器之間才能建立起可靠的TCP連接,,數(shù)據(jù)才可以在客戶機(jī)和服務(wù)器之間傳遞
TCP連接終止 終止一個(gè)連接需要4個(gè)分節(jié)。 1,、通過調(diào)用close,,我們執(zhí)行主動(dòng)關(guān)閉,,TCP發(fā)送一個(gè)FIN(finish,表示結(jié)束),,表示數(shù)據(jù)發(fā)送完畢。 2,、對(duì)端接收到FIN后,,執(zhí)行被動(dòng)關(guān)閉。 3,、一段時(shí)候后,,接收到文件結(jié)束符的應(yīng)用進(jìn)程,將調(diào)用close關(guān)閉它的套接字,。于是套接字也發(fā)送一個(gè)了FIN,。 4、確認(rèn)這個(gè)FIN ACK+1 下圖很清楚的表達(dá)了,?! ?/span> 5、我們也稱它為TCP四次握手,。
> 4,、IPv4、IPv6套接字的地址結(jié)構(gòu) IPv4地址結(jié)構(gòu): 1 struct in_addr { 2 in_addr_t s_addr; 3 }; 4 5 struct sockaddr_in { 6 uint8_t sin_len; //無符號(hào)8位整型 7 sa_family_t sin_famliy; /*AF_INET*/ 8 in_port_t sin_port;
IPv6地址結(jié)構(gòu): struct in6_addr { uint8_t s6_addr[16]; }; #define SIN6_LEN struct sockaddr_in6 { uint8_t sin6_len; sa_family_t sin6_famliy; in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; };
> 5,、一些好的學(xué)習(xí)網(wǎng)站總結(jié) 1,、關(guān)于51CTO上的這個(gè)視頻http://edu.51cto.com/course/course_id-903.html,我買了,,但是講的非常爛,,建議大家不要購(gòu)買。教課的老師也就是照著書念,,還不如自己,。浪費(fèi)錢。 2,、http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html http://blog.csdn.net/hguisu/article/details/7445768/ http://www.oschina.net/code/snippet_97047_675 這幾篇博客不錯(cuò),,能帶你入門。 > 6,、代碼下載 Github: https://github.com/micwu/Demo > 7,、總結(jié) 學(xué)習(xí)之路是很蠻長(zhǎng)的。想要學(xué)好,,非常難,,需要長(zhǎng)期的積累。我也正在學(xué)習(xí)中,。經(jīng)過了很多的挫折,,但是有理想,,就一定能成功。希望大家想走Linux下服務(wù)器編程的同志們,,一起加油吧,。 > 8、echo實(shí)現(xiàn)
代碼下載:Github |
|