**高如下爲基,貴以賤爲本
互聯網技術的核心根基就是TCP/IP,TCP/IP的實現依賴於Linux socket API【咱們的項目大部分運行在上面】
沒有它們各類高大上牛逼的技術就無從創建起來。而這根基對你們所用的java,go,py,php,c,c++,nodejs...都是同樣的,只不過是基於Linux api作了各類各樣的封裝百家爭鳴,百花齊放,跟易經裏的陰陽構成64卦同樣,當你剛開始擼程序時,可能並不會以爲基礎的重要性,甚至可能幾年內一直是框架crud boy,你並不會察覺到基礎核心Linux socket api【通常來講linux內核的api不多變更,比較穩定,國內linux內核開發工程師估計也不會每天沒事幹,每天修改linux內核api】!
天天被各類新技術詞彙遮蔽雙眼,而基礎知識你一直的錯失和鄙視低估,就想一步飛龍在天,達到九五爻之位,並無「如下爲基」 「以賤爲本」 **
甚至對於其它知識點你都持「下賤之態」只想與天齊名,從不腳踏實地從坤作起。php
先給總結圖 你再看下面的內容
java
下面就是要告訴你所謂的牛逼技術究竟是什麼回事!!!
咱們測試一下數據庫,java,python,go,c/c++,php,redis,docker進行測試【測完你會發現點東西】
而後你再看圖比較好node
好啓動了,沒有什麼可說的,ELF文件啓動。
.ibd是建立數據表時生成的文件,沒啥可說的,DBA專業都知道
python
我畫線的地方調用了ACCEPT SOCKET API函數
調用了SENDTO,RECVFROM SOCKET API 函數 mysql
mysql怎麼實現咱們管不着,可是數據來回的傳輸依賴於LINUX SOCKET API,這些都是網絡接口API
調用了系統其它API函數庫,咱們看一下accept,sendto,recvfrom,setsockopt,getsockopt read,write,epoll相關函數
linux
啓動redis
測試
**epoll_wait 獲得就緒的文件描述符讀事件返回,而後調用read,其實跟RECVFROM功能同樣
它的數據是:3rn$3rnsetrn4rnbfzsrn5rn10000rn
這一堆數據被各類大佬稱爲 redis的二進制通訊請求協議!!!返回是+OKrn**
c++
它們的數據來回傳輸大部分用read,write函數來實現
面試
dockerd服務ELF文件調用的linux api相關函數庫
啓動docker服務,跟mysql同樣默認啓動一堆進程和線程
相關命令運行【對不起,我不喜歡背東西,你要是面試我時,問我docker有哪些命令選項,對不起我回家種地放牛了】
來用下測試
運行過程
都在調用connect,socket,getpeerame,setsockopt,getsockopt,accept,sendto等LINUX SOCKET API函數
docker調用的LINUX API 函數庫
redis
我直接複製粘粘給你運行對不起我背不了函數,要用就直接複製粘粘就行了
sql
go ELF 文件
來運行那個你們認爲的源碼文件
先運行哪一個函數,你本身看着辦哦
重點
熟悉的一批,socket 建立socket文件描述符,而後命名【把ip,端口綁定到此文件上】,而後監聽,並阻塞在accept函數上
好了,go就這樣子,它封裝的比較騷,go elf編譯器封裝的牛逼,語法換了一套就稱爲編譯型語言了。
py的語法就是好,隨便一擼就能夠了,簡直是粗暴又騷,語法嘛就這樣,長得跟少婦同樣
來先認識一下python elf文件 畢竟好多爬蟲大佬可能沒有見過
.php .py .go .java裏的東西只是個文本內容,大家嘛叫源碼,我沒有文化,只能叫ascii text ^_^
啓動測試
有沒有發現,熟悉的一批
好了,到這裏夠意思了。
這麼簡單的語言,你去學語法就好了,簡單又粗暴誰不喜歡呢。我都喜歡。 ^_^
測試源碼
cat GreetingServer.java import java.net.*; import java.io.*; public class GreetingServer extends Thread { private ServerSocket serverSocket; public GreetingServer(int port) throws IOException { serverSocket = new ServerSocket(port); serverSocket.setSoTimeout(100000000); } public void run() { while(true) { try { System.out.println("等待遠程鏈接,端口號爲:" + serverSocket.getLocalPort() + "..."); Socket server = serverSocket.accept(); System.out.println("遠程主機地址:" + server.getRemoteSocketAddress()); DataInputStream in = new DataInputStream(server.getInputStream()); System.out.println(in.readUTF()); DataOutputStream out = new DataOutputStream(server.getOutputStream()); out.writeUTF("謝謝鏈接我:" + server.getLocalSocketAddress() + "\nGoodbye!"); server.close(); }catch(SocketTimeoutException s) { System.out.println("Socket timed out!"); break; }catch(IOException e) { e.printStackTrace(); break; } } } public static void main(String [] args) { int port = Integer.parseInt(args[0]); try { Thread t = new GreetingServer(port); t.run(); }catch(IOException e) { e.printStackTrace(); } } }
看一下java elf文件,我相信java大佬確定知道我就不費話了
編譯一下
我沒有學過java,可是看一下報錯就知道了,對不對,這麼明顯的提示,我phper都曉得 ^_^
編譯ok
編譯好是啥文件
啓動java程序開始測試
有沒有發現,熟悉的一批
好了,就這麼多就好了,沒有必要再截圖了。
看接下,咱們擼c[c++同樣]
大家應該看出點熟悉的地方了 int main(int argc,char *argv[]) { if(argc<=2){ printf("useage:%s ip_address port_number\n",basename(argv[0])); return 1; } const char *ip = argv[1]; int port = atoi(argv[2]); int ret = 0; struct sockaddr_in address; bzero(&address,sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port = htons(port); int listenfd = socket(PF_INET,SOCK_STREAM,0); assert(listenfd>=0); ret = bind(listenfd,(struct sockaddr*)&address,sizeof(address)); assert(ret!=-1); ret = listen(listenfd,5); assert(ret!=-1); bzero(&address,sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET,ip,&address.sin_addr); address.sin_port = htons(port); int udpfd = socket(PF_INET,SOCK_DGRAM,0); assert(udpfd>=0); ret = bind(udpfd,(struct sockaddr*)&address,sizeof(address)); assert(ret!=-1); struct epoll_event events[MAX_EVENT_NUMBER]; int epollfd = epoll_create(5); assert(epollfd!=-1); addfd(epollfd,listenfd); addfd(epollfd,udpfd); while(1){ int number = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1); if(number<0){ printf("epoll failre\n"); break; } for(int i=0;i<number;i++){ int sockfd = events[i].data.fd; if(sockfd ==listenfd){ struct sockaddr_in client_address; socklen_t client_addrlength = sizeof(client_address); int connfd = accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength); addfd(epollfd,connfd); } else if(sockfd == udpfd){ char buf[UDP_BUFFER_SIZE]; memset(buf,0,UDP_BUFFER_SIZE); struct sockaddr_in client_address; socklen_t client_addrlength = sizeof(client_address); ret = recvfrom(udpfd,buf,UDP_BUFFER_SIZE-1,0,(struct sockaddr*)&client_address,&client_addrlength); if(ret>0){ sendto(udpfd,buf,UDP_BUFFER_SIZE-1,0,(struct sockaddr*)&client_address,client_addrlength); } } else if(events[i].events & EPOLLIN){ char buf[TCP_BUFFER_SIZE]; while(1){ memset(buf,0,TCP_BUFFER_SIZE); ret = recv(sockfd,buf,TCP_BUFFER_SIZE-1,0); if(ret<0){ if((errno==EAGAIN)||(errno=EWOULDBLOCK)){ break; } close(sockfd); break; } else if(ret==0){ close(sockfd); } else{ send(sockfd,buf,ret,0); } } }else{ printf("something else happened\n"); } } } close(listenfd); return 0; }
而後編譯,編譯好就這樣
測試
好了,都不用我廢話了,接下來仍是測試下php吧,我以爲,雖然有的朋友以爲php咋樣咋樣,拍黃片嘛,在打黃打非的壓力之下固然沒啥好名聲了。
看下php elf文件
啓動並測試跟蹤
好了,不用我廢話,你們也知道是怎麼回事了。
這些api函數怎麼用呢?
man socket
linux socket api 是全部語言,數據庫等應用的核心低層技術知識,你框架掌握的再6,沒有多少意義,語言掌握得再6也只是工具分佈式,集羣,高大上的技術都要TCP/IP支持,而它的實現就是網絡編程,各語言寫法不一樣,可是核心基礎知識沒有變化,正所謂天下大事必做於細天下難事必做於易,一上來擼c/c++,java若是不合適你,那麼上來就擼PHP掌握了共通的知識再換語言又何妨呢?