做印章的網(wǎng)站網(wǎng)站推廣服務(wù)
一、網(wǎng)絡(luò)編程介紹
c++編程的應(yīng)用場景在前面分析過,一個重要的方向就是網(wǎng)絡(luò)編程。一般來說,開發(fā)者說的服務(wù)端編程在c++方向上簡單的可以認為是網(wǎng)絡(luò)編程。首先需要說明的,本系列不對網(wǎng)絡(luò)編程的相關(guān)基礎(chǔ)知識展開詳細的說明,因為這種知識在書本上太多了。網(wǎng)絡(luò)上各種資料更是滿開飛,沒有必要拷貝來拷貝去的。特別是一些協(xié)議等的解析說明,如果不遇到特定的問題不會深入分析說明。
那么最應(yīng)該明白的網(wǎng)絡(luò)編程是什么?那么就得明白網(wǎng)絡(luò)是如何而來。網(wǎng)絡(luò),從名字上很好理解,一張把“經(jīng)絡(luò)”連接起來的大網(wǎng)。不過這個經(jīng)絡(luò)不是人體中的“經(jīng)絡(luò)”而是一個個節(jié)點,這個節(jié)點可以是虛擬的,也可以是物理的,也可以是混合的。它可以是一臺電腦,一個手機,一個終端,也可以是一個局域網(wǎng)、城域網(wǎng)等等。
計算機的網(wǎng)絡(luò)技術(shù)在計算機技術(shù)中算是比較早期的一種技術(shù)了,在60年代的中期就已經(jīng)開始在實際應(yīng)用了。但真正的普及是美國的國防用網(wǎng)絡(luò)。早期學(xué)習(xí)電腦的或者看過早期電影的,都聽說過某某黑客特別厲害,進入了五角大樓的網(wǎng)絡(luò),盜取了不少軍事資料??梢赃@樣講,計算機的網(wǎng)絡(luò)技術(shù)也是從美國開始興起的,然后在全世界開始普及。這也解釋了為什么現(xiàn)在最牛的互聯(lián)網(wǎng)公司基本都在美國的一個重要原因。比如耳熟能詳?shù)墓雀?、微軟、臉書以及推特等等?br /> 隨著PC的出現(xiàn)和發(fā)展,局域網(wǎng)(LAN)出現(xiàn)。美國Xerox公司首先推出了Ethernet網(wǎng),慢慢其成為了一種標準,大家都稱現(xiàn)在的局域網(wǎng)絡(luò)為以太網(wǎng)。有了局域就會有廣域網(wǎng)WAN。不過需要說明的是,所謂局域與廣域是一個相對概念,請大家一定要根據(jù)實際場景來確定。
網(wǎng)絡(luò)技術(shù)其實就是處理PC間連接通信的技術(shù)。從物理上講,如何識別網(wǎng)絡(luò)中的PC,如何與其它PC交換數(shù)據(jù)等等。首先需要用物理導(dǎo)線將各個PC連接起來,一開始是電纜,后來光纜,再后來又有無線技術(shù)。然后還要有路由器和交換機把數(shù)據(jù)將有的傳送到指定的PC。而為了實現(xiàn)上述的功能,就需要一系列的通信標準和通信協(xié)議。這就引出了網(wǎng)絡(luò)協(xié)議的五層模型(七層就是個學(xué)術(shù)的東西,沒啥實際應(yīng)用的意義)。而這個模型中,則包含是最常見的網(wǎng)絡(luò)編程中的TCP/IP、UDP、HTTP等最常見的網(wǎng)絡(luò)編程技術(shù)?;蛘哒f的不準確一些,對大多數(shù)的網(wǎng)絡(luò)編程人員來說,就是TCP/IP和UDP編程。在移動互聯(lián)網(wǎng)中,HTTP則更為普及的被使用。至于其它的技術(shù),基本都是相當專業(yè)的人員或者特定領(lǐng)域的開發(fā)者才會使用。
二、基本知識
這里不談較老的技術(shù)和很新的技術(shù),比如QUIC和HTTP3等。在網(wǎng)絡(luò)編程中,可以分成兩大類應(yīng)用,即B/S開發(fā)和C/S開發(fā)(P2P以后專門講),這里只談C/S開發(fā)。即本系列主要針對C/S開發(fā)中的TCP/IP編程以及UDP的編程。只要掌握了它們的編程,其它的編程基本都差不多。在TCP/IP和UDP編程中,需要掌握一些基本的知識:
1、服務(wù)器
這個概念是一個非常容易混淆的概念,一定要區(qū)別在不同的語境和環(huán)境下的定義。在網(wǎng)絡(luò)編程的語境下,一般是指承載網(wǎng)絡(luò)服務(wù)軟件的服務(wù)器電腦(硬件)。它可以分成網(wǎng)絡(luò)內(nèi)部自用,比如路由器、交換機等也可以只提供某種網(wǎng)絡(luò)服務(wù)的電腦如打印服務(wù)器、郵箱服務(wù)器等。
2、服務(wù)端
服務(wù)端或服務(wù)端軟件,也可以叫網(wǎng)絡(luò)服務(wù),在特定到C/S編程中,就是指提供連接服務(wù)的程序。一般來說,服務(wù)端是被接收連接的。
3、客戶端
客戶端在C/S編程中指發(fā)起連接的一端。
4、協(xié)議棧
協(xié)議棧(Protocol stack),又稱協(xié)議堆疊,是計算機網(wǎng)絡(luò)協(xié)議套件的一個具體的軟件實現(xiàn)。
5、伯克利套接字
伯克利套接字(Berkeley sockets),也稱為BSD Socket。其是一種使用C語言實現(xiàn)的網(wǎng)絡(luò)編程抽象接口?,F(xiàn)在幾乎成為了互聯(lián)網(wǎng)通信的標準接口。
6、五元組和三元組:
五元組包括:源IP地址,源端口,目的IP地址,目的端口和傳輸層協(xié)議。這等同于現(xiàn)實世界中的人和人之間的通信地址。
7、協(xié)議族
socket函數(shù)中的第一個參數(shù)中意義,也叫協(xié)議域。通常有AF_INET、AF_INET6、AF_LOCAL(或稱AF_UNIX,Unix域socket)、AF_ROUTE等。協(xié)議族確定socket的地址類型,即雙方必須使用相同的通信類型才可以進行以通信。如常見的AF_INET需要用32位(類似192.168.0.1)ipv4地址與16位端口號(最大65535)的組合、AF_UNIX需要用一個絕對路徑名作為地址。
當然,還有很多的基礎(chǔ)性的知識和名詞術(shù)語。網(wǎng)絡(luò)技術(shù)是一個發(fā)展了很多年的技術(shù),它既成熟又年輕。舉一個簡單的例子,當有一個人說他是搞服務(wù)端編程的,如何確定他的技術(shù)棧?其實這個定義非常難確定,網(wǎng)上一些大牛的說明其實也不能夠完全覆蓋相關(guān)的內(nèi)容,即他們的定義也是不嚴謹?shù)?。但僅從經(jīng)驗和學(xué)識來推斷,特定到C/c++中,它一般是指TCP/IP編程的相關(guān)技術(shù)棧(當然,它也不嚴謹)。
再舉一個實際的例子,大家去品一下上面這段話,至于能理解多少看自身了。在某電力部門,要求把服務(wù)端程序部署在終端上,把客戶端程序部署在服務(wù)器上??蛻舳艘?4*7運行,服務(wù)端可以允許斷線。
注意:再次說明,本系列不是對網(wǎng)絡(luò)編程技術(shù)基礎(chǔ)知識的詳細分析說明,是對c++在網(wǎng)絡(luò)編程上的應(yīng)用分析說明,所以只對相關(guān)的一些知識點進行指出和簡要的說明。更多的相關(guān)知識,請自行查閱下面提供的書籍和資料!
三、簡單示例
雖然網(wǎng)絡(luò)編程的例子多之又多,但這里還是要給一個簡單的例子:
服務(wù)端:
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>int main() {int server_fd, new_socket;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);char buffer[1024] = {0};const char* msg = "hello moto!";//創(chuàng)建socketif ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}//設(shè)置選項if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}//地址設(shè)置address.sin_family = AF_INET;address.sin_addr.s_addr = INADDR_ANY;address.sin_port = htons( 8888 );//綁定端口if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {perror("bind err");exit(EXIT_FAILURE);}//監(jiān)聽if (listen(server_fd, 5) < 0) {perror("listen");exit(EXIT_FAILURE);}//接受連接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {perror("accept err!");exit(EXIT_FAILURE);}send(new_socket , msg , strlen(msg) , 0 );printf("send msg ...\n");memset(buffer, '\0' , 1024);int ret = recv( new_socket , buffer, 1024,0);printf("%s\n",buffer );return 0;
}
客戶端:
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>int main() {int sock = 0, ret;struct sockaddr_in serv_addr;const char* msg = "hello !";char buffer[1024] = {0};//創(chuàng)建socketif ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {printf("\n Socket error \n");return -1;}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(8888);//轉(zhuǎn)換地址if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {printf("\n Invalid address \n");return -1;}//連接serverif (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {printf("\n Connection err \n");return -1;}send(sock , msg , strlen(msg) , 0 );printf("send msg !\n");ret = recv( sock , buffer, 1024,0);printf("%s\n",buffer );return 0;
}
寫這種測試的小例程有一個需要注意的地方,客戶端發(fā)送完成后,不要立即退出,否則可能服務(wù)端收不到相關(guān)的消息。
四、推薦的資料和書籍
一如在VC編程上侯捷教師是一個令開發(fā)者仰望的山峰,在網(wǎng)絡(luò)編程也有很多更高的高峰。比如常見的推薦的《TCP/IP詳解》三卷和《Unix網(wǎng)絡(luò)編程》兩卷的作者W. Richard Stevens(當然他寫的APUE也相當?shù)某雒?#xff09;。不過這些書的缺點也有,就是太老了。導(dǎo)致一些技術(shù)已經(jīng)落后而一些新技術(shù)沒有體現(xiàn)出來。其它國外的還有不少就不一一列舉。國內(nèi)也有幾個比較有名氣的網(wǎng)絡(luò)開發(fā)者,限定到本文這個場景非常推薦MUDUO庫的作者陳碩。當然就像江湖中一樣,肯定還有很多高手隱身不出。
學(xué)習(xí)網(wǎng)絡(luò)編程的書籍非常多,比如CSDN的孟巖大佬的“四書五經(jīng)”之說就是為多數(shù)大牛推薦的。這里簡單羅列一下:
1、TCP/IP詳解(三卷)(TCP/IP Illustrated)
2、Unix網(wǎng)絡(luò)編程(兩卷)(UNIX Network Programming)
3、TCP/IP高級編程(Effective TCP/IP Programming)
4、C++網(wǎng)絡(luò)編程(兩卷)(C++ Network Programming)
雖然這些書籍非常不錯,但對于初學(xué)者未必就合適,也推薦一些比較容易借鑒學(xué)習(xí)的書籍:
1、《Linux多線程服務(wù)端編程》 陳碩
2、《Linux高性能服務(wù)端編程》 游雙
3、《Windows網(wǎng)絡(luò)與通信程序設(shè)計》 王艷平
并不是說其它的書籍不值得推薦,是覺得這幾本書更容易被學(xué)習(xí)和接受。至于網(wǎng)絡(luò)上的資料就更多了,如陳碩、原網(wǎng)易的云風(fēng)等人的BLOG都非常值得一看。個人的建議是,要根據(jù)自己的實際情況來決定學(xué)習(xí)成長的路線,不要人云亦云。大牛們給的建議可能對大多數(shù)人都是非常好的,但具體到某些個體,可能會有所不妥。大家要知道如何不斷的根據(jù)大牛們的建議因地制宜的學(xué)習(xí)。
另外在網(wǎng)上還存在著大量的網(wǎng)絡(luò)框架如C++網(wǎng)絡(luò)編程中的ACE,還有l(wèi)ibevent,libuv,libev,libeio,libhv,asio,poco等等。畢竟網(wǎng)絡(luò)應(yīng)用是一個非常高頻的應(yīng)用,也是很多開發(fā)者想登頂?shù)南M?br /> 其實還有很多應(yīng)用程序中也有非常好的例子,比如REDIS,有時間推薦看看內(nèi)部如何跨平臺實現(xiàn)了網(wǎng)絡(luò)服務(wù)端的編程。
五、總結(jié)
網(wǎng)絡(luò)編程是一個復(fù)雜的應(yīng)用,一般來說,很難在一兩年內(nèi)達到熟練掌握的程度,更不要談精通了。通常,把基礎(chǔ)的網(wǎng)絡(luò)知識學(xué)習(xí)完成,頭腦中有一個相對完整的網(wǎng)絡(luò)編程概念,然后在實際應(yīng)用中不斷的加以印證,才能更快更好的掌握網(wǎng)絡(luò)編程。
網(wǎng)絡(luò)編程其實是一個簡單應(yīng)用易,復(fù)雜應(yīng)用極難的技術(shù)。它不僅是涉及到網(wǎng)絡(luò)相關(guān)的技術(shù),還包括內(nèi)存管理、多線(進)程以及異步編程等很多技術(shù),甚至是否需要跨平臺跨系統(tǒng)等。對大多數(shù)開發(fā)者言,網(wǎng)絡(luò)編程的應(yīng)用一般都是比較簡單的應(yīng)用,并發(fā)通常也就是十個量級左右,而且經(jīng)常類似于交互式通信那種情況。對多線程和異步的要求不高甚至沒有,對內(nèi)存管理和效率的要求也不嚴格。
但當真正到了C10K以上的編程時,復(fù)雜程度立刻便上來,導(dǎo)致很多開發(fā)者沒有一個過渡便直面這些復(fù)雜的應(yīng)用。也就是說,在網(wǎng)絡(luò)編程大多數(shù)的編程場景是要么簡單,要么復(fù)雜,中等的開發(fā)場景非常少。而且從設(shè)計上考慮,一旦到了中等的場景,優(yōu)秀的架構(gòu)師通常會考慮擴展的情況下設(shè)計成更為復(fù)雜的框架結(jié)構(gòu)。
復(fù)雜的網(wǎng)絡(luò)編程,導(dǎo)致很多的框架的出現(xiàn),而這些框架的出現(xiàn)更是切斷了大多數(shù)開發(fā)者對背后復(fù)雜結(jié)構(gòu)的理解,導(dǎo)致一個從初級網(wǎng)絡(luò)編程到高級網(wǎng)絡(luò)編程的連續(xù)而完整的流程,即要么只會簡單的編程,要么只會在框架下完成各種場景的應(yīng)用。
更何況,網(wǎng)絡(luò)編程的實際要求仍然在不斷的增長,這也是前面分析DPDK和XDP等的一些重要原因。換句話說,網(wǎng)絡(luò)編程的技術(shù)仍然在不斷的進步。所以,不斷的學(xué)習(xí)才能保證在網(wǎng)絡(luò)編程的方向上有更大的發(fā)展。