廢話不多說,開始聽我**。哈哈
所謂網路程式,就是寫的程式能通過網路進行通訊(就是互動資料),所以要想程式間能進行通訊,至少要執行兩個例項(其中,乙個例項為伺服器,乙個為客戶端)。一般來說,伺服器例項只要乙個,客戶端例項可以多個。伺服器和客戶端的例項可以是同乙個程式(該程式既是伺服器,又是客戶端,一般用於區域網),也可以是不同的程式(伺服器乙個程式,客戶端乙個程式)。
首先,個人建議先了解一下tcp協議,以及tcp鏈結建立的三次握手、斷開的四次揮手。期間伺服器和客戶端狀態變化建議了解比較好,這裡不做講解,感興趣的可以去看看。
服務端(只要記住六步):
1)建立套接字(socket)
2)繫結位址(bind)
3)監聽(listen)
4)輪詢等待客戶端的接入(select | accept)
5)接收,傳送訊息(recv | send)
6)關閉(close)
#define _winsock_deprecated_no_warnings
#include
#pragma comment(lib, 「ws2_32.lib」)
int main()
//6)關閉
closesocket(s);
return 0;客戶端(只要記住四步)
1)建立套接字(scoket)
2)連線伺服器(connect)
3)接收,傳送訊息(recv | send)
4)關閉(close)
#define _winsock_deprecated_no_warnings
#include #include #pragma comment(lib, "ws2_32.lib")
int main()
; int ret = recv(s, szbuf, 1024, 0);
szbuf[ret] = '\0';
printf("%s\n", szbuf);
//4)關閉
closesocket(s);
return 0;
}
上述**是基於winsocket編寫的,visual studio編輯可直接執行。為了便於理解,很多異常情況沒有判斷。 看了上面客戶端,和伺服器的**是不是覺得很容易?但是上訴程式只能保證乙個客戶端進行正常互動。為什麼呢?原因就是伺服器中的accept函式是阻塞函式,也就是當有新的客戶端連線到伺服器時,accept才會返回,否則一直處於等待狀態。那麼如何解決呢?這裡可能很多同僚也知道,使用select模式輪詢,或者epoll模式(linux獨有)。這裡給大家科普一下,早期還沒有select模式和epoll模式的時候,是如何解決阻塞的呢?是用執行緒處理的,當時最早的魔獸世界伺服器據說是用執行緒處理的阻塞問題。因為accept,recv,send三個函式都是阻塞函式,所以服務端至少建立2倍的客戶端+1的執行緒數量。這是在沒有select和epoll模式的做法。但是執行緒多了,不僅消耗作業系統的資源,而且會讓程式變得很複雜,不是很好維護。下面給出select模式下的,服務端和客戶端**。
服務端:
#define _winsock_deprecated_no_warnings
#include #pragma comment(lib, "ws2_32.lib")
bool iscanwrite(socket s)
return false;
}int main()
; ret = select(smax + 1, &fdread, null, null, &t_out);
if (ret > 0) }}
//防止獨佔cpu
sleep(10);
}//6)關閉
closesocket(s);
return 0;
}
客戶端:
#define _winsock_deprecated_no_warnings
#include #include #pragma comment(lib, "ws2_32.lib")
bool iscanread(socket s)
return false;
}int main()
; int ret = recv(s, szbuf, 1024, 0);
szbuf[ret] = '\0';
printf("%s\n", szbuf);
}//防止獨佔cpu
sleep(10);
}//4)關閉
closesocket(s);
return 0;
}
上述就是阻塞模式和非阻塞模式的**,這裡非阻塞模式只給了select模型,至於epoll模型,可以自行科普(epoll和select模型是有區別,根據不同的情況選擇不同的模式,這裡不做說明)。
還是個人建議先了解一下udp協議,相對於tcp協議比較而言,udp協議簡單的多。
服務端(只要記住四步):
1)建立套接字(socket)
2)繫結位址(bind)
3)接收,傳送訊息(recv | send)
4)關閉(close)
#define _winsock_deprecated_no_warnings
#include #include #pragma comment(lib, "ws2_32.lib")
int main()
; int ret = recvfrom(s, szbuf, 1024, 0, (sockaddr*)&addr, &addr_len);
if (ret > 0)
//防止cpu空轉
sleep(10);
}//4)關閉
closesocket(s);
return 0;
}
客戶端(只要記住三步):
1)建立套接字(socket)
2)接收,傳送訊息(recv | send)
3)關閉(close)
#define _winsock_deprecated_no_warnings
#include #include #pragma comment(lib, "ws2_32.lib")
int main()
套接字屬性?其實套接字本身是還有很多屬性的,如果僅僅以為掌握上述的select**就算掌握的話,那你可就太天真了。上述本人給的select模式**,預設是非阻塞的;其實也可以把select設定成超時阻塞模式,這就需要知道套接字屬性欄位了。下面我例舉部分屬性字段,主要目的是讓知道套接字有屬性就行,具體哪些可以網上查閱。
//下面是winsocket的屬性,主要是命名不一樣,linux下也有,可能是別的命名方式
fionbio //阻塞模式
so_linger //linger演算法(節約流量,不知道的網上科普)
so_sndbuf //協議棧(這個概念不是很清楚的,先放一放,或者去科普,因為隨著你寫的越多,你就慢慢明白了)的傳送緩衝區大小
so_rcvbuf //協議棧的接收緩衝區大小
so_sndtimeo //傳送超時
so_rcvtimeo //接收超時
so_reuseaddr //重用位址
tcp_nodelay //延時傳送(如果開啟,就可能會產生黏包)
//等等,還有很多字段,但是常用(本人常用)的就這麼幾個
網路知識之TCP UDP篇
我們學習過什麼是 資料報 理解資料報,對於網路管理的網路安全具有至關重要的意義。比 如,防火牆的作用本質就是檢測網路中的資料報,判斷其是否違反了預先設定的規則,如果違反就加以阻止。圖1就是瑞星個人版防火牆軟體設定規則的介面。細心 的讀者會發現,圖1中的 協議 欄中有 tcp udp 等名詞,它們是什...
Web前端 HTML篇(其一)
常用檔案命名 html的特性 路徑問題 html的構成是由一種標籤的 構成,標籤分為雙標籤和單標籤,雙標籤的書寫方式是,後面的標籤是以尖括號加乙個 接標籤結尾。h1 p 乙個標準的html檔案的構成是由由圈起來的頭部和主體構成,這是w3c的規定html標準。head body hmtl 標題標籤 首...
網路的經濟基礎篇 之一 TCP UDP
udp的資料部分是可選的 以位元組 8 bit 為單位,包括header和data,也就是說length的最小值是8。計算方法和ipv4中的checksum一樣,但是ipv4中的檢驗只覆蓋header,而udp和tcp的檢驗則覆蓋它們的header和data。udp的檢驗和是可選的,而tcp的檢驗和...