国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程

這篇具有很好參考價值的文章主要介紹了【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

??作者:一只大喵咪1201
??專欄:《網(wǎng)絡(luò)》
??格言:你只管努力,剩下的交給時間!
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

上篇文章中本喵介紹了UDP網(wǎng)絡(luò)通信的socket代碼,今天介紹TCP網(wǎng)絡(luò)通信的socket代碼。

??TCP網(wǎng)絡(luò)編程

??服務(wù)端實現(xiàn)

udp的網(wǎng)絡(luò)通信一樣,tcp通信也需要服務(wù)器指定端口號,IP地址同樣使用0.0.0.0,以便客戶端所有對服務(wù)器的網(wǎng)絡(luò)請求都能收到。

class tcpServe
{
public:
	  // 構(gòu)造函數(shù)
      tcpServe(const uint16_t &port)
      	: _port(port), _listensock(-1)
      {}
      // 服務(wù)器初始化
      void initServer()
      {}
      // 服務(wù)器運行
      void start()
      {}
      // 析構(gòu)函數(shù)
      ~tcpServe()
      {}
private:
      int _listensock; // 不是用來進行數(shù)據(jù)通信的,是用來監(jiān)聽鏈接到來的,獲取新連接
      uint16_t _port;
};

服務(wù)器類的框架如上面代碼所示,包括一個文件描述符istensock,還有一個端口號_port,這里本喵沒有寫IP地址的成員變量,因為會給它一個缺省值,所以沒有必要,后面本喵會詳細(xì)講解。

下面就是將tcpServe類中成員函數(shù)的具體邏輯寫出來了。

initServer()

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
首先是創(chuàng)建套接字,和udp一樣,使用系統(tǒng)調(diào)用socket,只是填的參數(shù)不一樣,第一個參數(shù)仍然是AF_INET表示網(wǎng)絡(luò)間通信,第二個參數(shù)這里使用的是SOCK_STREAN,表示面向字節(jié)流的,不再是面向用戶數(shù)據(jù)報了,第三個參數(shù)仍然是0。

創(chuàng)建套接字的結(jié)果使用日志函數(shù)logMessage()來記錄日志。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
然后就是將端口號和IP地址使用系統(tǒng)調(diào)用bind和操作系統(tǒng)綁定,填充的結(jié)構(gòu)體仍然是struct sockaddr_in,和之前的udp一樣,只是在填充IP地址的時候,本喵這里使用了INADDR_ANY,它的意義就是0.0.0.0

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
它在Linux中的定義如上圖所示,我們使用的0.0.0.0轉(zhuǎn)換成uint16_t以后就是0x00000000。

在使用bind進行綁定的時候,同樣需要將填充的結(jié)構(gòu)體強轉(zhuǎn)成struct sockaddr*,綁定的結(jié)果使用日志來記錄。

將套接字設(shè)置為listen狀態(tài)

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

第三步就是將套接字設(shè)置為監(jiān)聽狀態(tài),使用系統(tǒng)調(diào)用listen,如上圖所示。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
系統(tǒng)調(diào)用listen的作用是將套接字設(shè)置為監(jiān)聽狀態(tài),此時這個套接字和udp中的套接字不一樣,它不用來通信,只用來檢測客戶端的連接請求的。

第一個參數(shù)sockfd就是使用socket創(chuàng)建套接字返回的文件描述符,第二個參數(shù)這里本喵暫時不做講解,等后面會詳細(xì)講解,這里隨便給一個值就可以,不要太大,本喵這里給的是5。

設(shè)置成功返回0,設(shè)置失敗返回-1,并且設(shè)置錯誤碼,同樣使用日志來記錄設(shè)置結(jié)果。

以上三步就是初始化initServe中的內(nèi)容。

start()
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
第四步寫在start函數(shù)中,如上圖所示,使用accept來接收客戶端的連接請求,有點像udp中的recvfrom一樣,只是accept是用來接收套接字的連接請求,而recvfrom是接收套接字中的數(shù)據(jù)的。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
accept系統(tǒng)調(diào)用的參數(shù)和recvfrom中的一樣,如上圖所示,accept的作用就是接收來自套接字中的連接請求,也就是來自客戶端的連接請求。

返回值:

上面本喵說過,設(shè)置為listen狀態(tài)的套接字不用了通信,只是用來接收客戶端的網(wǎng)絡(luò)請求,具體體現(xiàn)在accept的返回值上。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
此時第一步中創(chuàng)建的套接字就像是一個門童,使用accept來接收客戶端的連接請求,如果有連接請求并且接收成功,那么會返回一個文件描述符fd。

這里的文件描述符sock和前面的_listensock不是一個東西,_listensock是我們創(chuàng)建的,是專門用來接收連接請求的,而accept返回的sock是操作系統(tǒng)在接收成功連接請求后新創(chuàng)建的套接字的文件描述符。

sock指向的文件描述符是服務(wù)端專門用來和客戶端通信的,所以每有一個客戶端向服務(wù)器發(fā)起連接請求,客戶端接收成功夠都會創(chuàng)建一個套接字用來一對一的提供服務(wù)。

  • _listensock:我們創(chuàng)建套接字返回的文件描述符,必須設(shè)置為listen狀態(tài),專門用來檢測客戶端的連接請求的。
  • sock:accept返回的文件描述符,是操作系統(tǒng)自動創(chuàng)建的套接字的文件描述符,該套接字專門用來和客戶端進行一對一網(wǎng)絡(luò)通信的。

如果accept接收連接請求失敗,則返回-1,并且設(shè)置錯誤碼。這里的失敗并不是致命的,就像門童拉客一樣,拉客失敗也沒有什么,繼續(xù)進行下一次拉客就行。

所以accept失敗也沒有什么,繼續(xù)接收下一個連接請求即可,所以本喵在代碼中,如果接收失敗,使用了continue繼續(xù)接收連接請求。

服務(wù)器的服務(wù)函數(shù):

至此,進行tcp網(wǎng)絡(luò)通信的所有準(zhǔn)備工作已經(jīng)做完,接下來就是進行具體的服務(wù)了,也就是讀取客戶端發(fā)送來的數(shù)據(jù)并做相應(yīng)的處理了。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

如上圖代碼所示,就是服務(wù)器指向的具體服務(wù)函數(shù)。

客戶端讀取客戶端發(fā)送來的數(shù)據(jù)時,是從accept返回的文件描述符sock指向的套接字中讀取數(shù)據(jù)的,因為這個套接字是專門用來服務(wù)客戶端的。

  • 讀取數(shù)據(jù)時,使用的是read系統(tǒng)調(diào)用,和讀取普通文件一模一樣。

數(shù)據(jù)讀取成功后,做一些處理,先將讀取的數(shù)據(jù)打印一下,然后加一個serve[echo]回顯,再給客戶端發(fā)送過去。

  • 發(fā)送數(shù)據(jù)時,使用的是write系統(tǒng)調(diào)用,寫入的也是sock指向的套接字,同樣與向普通文件中寫入數(shù)據(jù)一模一樣。

在讀取普通文件的時候,如果文件被讀完了,read會返回0,表示文件的內(nèi)容被讀取完畢。

但是在使用read讀取tcp套接字的時候,如果讀取到0,表示客戶端關(guān)閉了它的套接字,代表著客戶端不再進行網(wǎng)絡(luò)通信了,此時服務(wù)端就可以結(jié)束這次通信了,也就是將sock指向的套接字關(guān)閉。


以上代碼都是在tcpServe.hpp中寫的,都是tcpServe類中的成員函數(shù)以及成員變量,它是對服務(wù)器的一個抽象表示。

tcpServe.cpp

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
同樣使用智能指針unique_ptr來管理這個服務(wù)器,和udp網(wǎng)絡(luò)通信一樣。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
運行服務(wù)器以后,通過日志信息可以看到,套接字創(chuàng)建成功,bind成功,并且成功將套接字設(shè)置成了listen狀態(tài)。

之后服務(wù)器就阻塞不動了,此時它應(yīng)該執(zhí)行的是accept函數(shù),也就是應(yīng)該正在接收來自客戶端的網(wǎng)絡(luò)請求。但是它此時阻塞不動了,這是因為目前沒有網(wǎng)絡(luò)連接請求到來。

  • accept是阻塞執(zhí)行的,在沒有網(wǎng)絡(luò)連接請求的時候,會阻塞等待,直到客戶端的網(wǎng)絡(luò)連接請求到來。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
使用指令netstat -nltp可以查看當(dāng)前機器上的tcp網(wǎng)絡(luò)通信進程,如上圖所示。

綠色框中的就是我們前面寫的tcp服務(wù)器進程,其中IP地址是0.0.0.0,如上圖藍(lán)色框中所示,端口號是8080,還可以看到進程的pid22099,進程名字是./tcpserve,說明我們寫的tcp服務(wù)器沒有問題,成功的運行了起來。

??客戶端實現(xiàn)

class tcpClient
{
public:
	// 構(gòu)造函數(shù)
    tcpClinet(const string& serverip, const uint16_t serverport)
    	:_serverip(serverip), _serverport(serverport), _sockfd(-1)
    {}
    // 客戶端初始化
    void initClient()
    {}
    // 客戶端啟動
    void start()
    {}
    // 析構(gòu)函數(shù)
    ~tcpClinet()
    {}
private:
	string _serverip;
    uint16_t _serverport;
    int _sockfd;
};

客戶端需要的成員變量和udp中一樣,也是需要服務(wù)端的IP地址,服務(wù)端的端口號,以及客戶端自己創(chuàng)建套接字的文件描述符_sockfd。成員函數(shù)和服務(wù)端類似,接下來要做的就是實現(xiàn)具體的邏輯。

initClient()

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
首先創(chuàng)建套接字,如果失敗直接打印錯誤信息,客戶端沒有使用日志來記錄。和udp一樣,tcp通信的客戶端也不需要顯式綁定,同樣也是由系統(tǒng)自動去綁定。

start()

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
第三步要發(fā)起連接,使用的系統(tǒng)調(diào)用是connect。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
用法和recfrom以及accept非常類似,第一個參數(shù)是創(chuàng)建的套接字的文件描述符,第二個參數(shù)是填充的struct sockaddr_in結(jié)構(gòu)體,在傳參的時候,需要強轉(zhuǎn)為struct sockaddr*類型,第三個參數(shù)是結(jié)構(gòu)體的大小。發(fā)起請求成功返回0,失敗返回-1。

用法非常熟悉,只是作用不同,connect的作用就是在套接字中發(fā)起一個網(wǎng)絡(luò)請求,這個網(wǎng)絡(luò)請求服務(wù)端的監(jiān)聽套接字可以檢測到。

請求發(fā)起成功夠就開始通信了,同樣使用系統(tǒng)調(diào)用readwrite向套接字中讀取和寫入數(shù)據(jù),和操作普通文件一樣。

這個客戶端程序中,先從標(biāo)準(zhǔn)輸入獲取用戶從鍵盤上輸入的數(shù)據(jù),然后通過write寫入到套接字中,也就是發(fā)給服務(wù)器,然后使用read從套接字中讀取服務(wù)端回顯的信息并且打印出來。


以上就是客戶端的代碼,同樣放在一個類中,在使用的時候直接實例化后就可以使用。

tcpClient.cpp

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
同樣使用智能指針來管理客戶端對象,具體的不再講解。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
服務(wù)端進程跑起來后,創(chuàng)建套接字,綁定以及將套接字設(shè)置成監(jiān)聽狀態(tài),當(dāng)這里準(zhǔn)備工作做完以后,在接收連接請求的時候會阻塞等待連接請求的到來。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
在客戶端進程跑起來后,服務(wù)端立刻接收到了連接請求,并且創(chuàng)建了一個套接字用戶服務(wù)客戶端,此時客戶端和服務(wù)端就可以進行網(wǎng)絡(luò)通信了。

客戶端發(fā)送什么,服務(wù)端就收到什么,然后再經(jīng)過加工將數(shù)據(jù)返回給客戶端。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
使用指令netstat -anlp可以查看當(dāng)前機器上運行的網(wǎng)絡(luò)通信進程,如上圖所示。

  • 紅色框中的是服務(wù)器進程,本地環(huán)回IP地址是127.0.0.1,端口號是8080,與其連接的客戶端端口號是40428。
  • 綠色框中的是客戶端進程,本地環(huán)回IP地址仍然是127.0.0.1,端口號是40428,與其連接的服務(wù)器端口號是8080。

由于本喵是在一臺機器上測試的,所以查看網(wǎng)絡(luò)通信進程的時候,可以同時看到服務(wù)器的和客戶端的。


【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

在服務(wù)器運行起來后,第一個客戶端可以成功建立連接,第二個客戶端就無法連接了,處于阻塞等待狀態(tài)。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
這是因為第一個客戶端連接連接后,服務(wù)器就陷入了死循環(huán),如上圖代碼所示。

start中有一個while(1),用來不斷接收接收來自客戶端的連接請求,連接成功后進入具體的服務(wù)函數(shù)serviceIO,在這個函數(shù)中也有一個while(1)循環(huán),不斷進行客戶端和服務(wù)端的網(wǎng)絡(luò)IO。

所以當(dāng)?shù)谝粋€客戶端連接成功后,服務(wù)器就陷入了serviceIO的死循環(huán)中,當(dāng)新的客戶端發(fā)起連接請求時,服務(wù)器無法accept到,所以表現(xiàn)出來的就是上圖所示的現(xiàn)象。

這是本喵為了測試而寫的測試代碼。真正的tcp網(wǎng)絡(luò)通信中肯定不能這樣,而是要滿足多個客戶端都能和服務(wù)端連接成功。

??多進程版本

為了實現(xiàn)多個客戶端都能和服務(wù)器建立連接,第一種策略就是采用多進程的形式,服務(wù)器每建立一個和客戶端的連接請求就創(chuàng)建一個新的進程,用來一對一服務(wù)客戶端。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
start函數(shù)中,accept連接后,開始進行具體的服務(wù),也就是調(diào)用serviceIO函數(shù),之前是直接調(diào)用,此時需要用fork創(chuàng)建一個子進程,讓子進程去調(diào)用serviecIO函數(shù),如上圖綠色框中所示。

  • 子進程會繼承父進程的一切,所以父進程中監(jiān)聽套接字的文件描述符_listensock也會被繼承下來
  • 為了防止子進程進行誤操作以及一定程度上節(jié)省資源,在子進程中將_listnesock指向的監(jiān)聽套接字關(guān)閉。

為了避免子進程造成內(nèi)存泄漏,當(dāng)子進程退出以后,父進程需要回收子進程資源,可以使用waitpid來回收子進程,有阻塞等待和非阻塞等待,這里本喵采用阻塞等待,如上圖第二個紅色框。

但是子進程執(zhí)行的serviceIO是一個死循環(huán),如果子進程沒有退出的話,父進程就會一直阻塞在waitpid處等待,當(dāng)有新的客戶端請求連接時同樣無法accept到,就變成和之前的一樣了。

  • 使用waitpid等待子進程退出時,一般不建議使用非阻塞的方式。

為了解決這個問題,在子進程中再次創(chuàng)建子進程,如上圖藍(lán)色框中所示,子進程fork后,又創(chuàng)建出一個子進程,該子進程是上一層父進程的孫子進程。

孫子進程一經(jīng)創(chuàng)建,它的父進程就退出,父進程之后的代碼也就是servicIO由孫子進程來執(zhí)行,孫子進程執(zhí)行完服務(wù)函數(shù)后,關(guān)閉當(dāng)前套接字,并且退出,此時祖父進程就可以繼續(xù)循環(huán)accept了。

  • 這里將原本父進程要執(zhí)行的代碼轉(zhuǎn)交給孫子進程去執(zhí)行,祖父進程從容獲得自己,可以繼續(xù)去accept。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

可以看到,此時兩個客戶端就可以同時和服務(wù)器建立連接,并且進行通信了,而且兩個客戶端之間互不影響,因為在服務(wù)端,每個客戶端都存在一個套接字進行一對一服務(wù)。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
使用指令ps ajx查看當(dāng)前機器上的進程時,可以看到名字為tcpserve的進程有3個,第一個進程就是祖父進程,pid為15959。

后面兩個進程是孫子進程,每個進程對應(yīng)著一個客戶端,它們各自的pid值不一樣,但是ppid都是1,表示操作系統(tǒng)。

  • 由于孫子進程的父進程退出了,所以兩個孫子進程變成了孤兒進程由操作系統(tǒng)領(lǐng)養(yǎng),它兩的資源也由操作系統(tǒng)負(fù)責(zé)回收。

此時就可以實現(xiàn)多客戶端和服務(wù)器之間的網(wǎng)絡(luò)通信了,每多一個客戶端就會在服務(wù)器上多創(chuàng)建一個進程,和一個套接字用來專門進行一對一服務(wù)。

但是多進程版本仍然存在缺陷,每創(chuàng)建一個進程的開銷是很大的,需要創(chuàng)建并維護進程地址空間,頁表,以及相應(yīng)的物理內(nèi)存。

??多線程版本

將多進程改變成多線程就能在一定程度上解決資源消耗大的問題,因為從線程和主線程是共用一份進程地址空間以及頁表的。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
將原本的多進程代碼改成如上圖所示的多線程代碼。

在使用pthread_create創(chuàng)建多線程的時候,傳入的可執(zhí)行任務(wù)不能有this指針,但是調(diào)用的具體服務(wù)函數(shù)serviceIO需要this指針。

  • 創(chuàng)建ThreadData用來存放新線程需要的參數(shù)

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
如上圖所示,結(jié)構(gòu)體中存在用于進行通信套接字的文件描述符_sock,以及服務(wù)器對象tcpserve的指針_self。

  • 新線程執(zhí)行的任務(wù)threadRoutine使用static修飾。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
從線程執(zhí)行完后的線程資源同樣需要回收,如果在主線程使用pthread_join等待回收資源的話,同樣會造成主線程無法accept

所以在從線程中,首先就是使用pthread_detach分離,讓操作系統(tǒng)來回收該線程的資源,主線程可以繼續(xù)去accept新的連接請求。

threadRoutine中通過服務(wù)器對象的_self指針來調(diào)用serveicIO,此時就可以多個客戶端向服務(wù)器發(fā)起連接請求了。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
可以看到,結(jié)果和多進程版本一樣,多個客戶端可以同時和服務(wù)器進行通信,每個客戶端在服務(wù)器中對應(yīng)一個線程和一個套接字。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
通過指令ps -aL來查看當(dāng)前機器上的線程,可以看到此時存在3個名字為tcpserve的線程。

  • 其中PID和LWP相同的是主線程,是用來accept新客戶端的網(wǎng)絡(luò)連接請求的。
  • PID和LWP不同的是兩個從線程,是專門用來用來給客戶端提供一對一服務(wù)的。

此時每有一個新的客戶端發(fā)起連接請求,服務(wù)器就會新創(chuàng)建一個線程。但是這樣同樣也有缺陷,在創(chuàng)建線程的時候同樣會存在很大的系統(tǒng)開銷。

??線程池版本

最好的方式就是使用線程池,預(yù)先創(chuàng)建一批線程,每有一個客戶端發(fā)起連接請求,就派一個線程去處理。

  • 線程池就直接使用前面本喵寫過的基于環(huán)形隊列的線程池,不再講解線程池。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

在服務(wù)器accept之前,將線程池運行起來,如上圖紅色框中所示,當(dāng)服務(wù)器accept新的連接請求后,將系統(tǒng)創(chuàng)建的用于服務(wù)的套接字文件描述符和serviceIO任務(wù)推送到線程池中,讓線程池分配線程去執(zhí)行任務(wù)。

Task.hpp

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
Task類稍作修改,成員變量包含用于通信的套接字文件描述符和回調(diào)函數(shù)。

  • 這里本喵將serviceIO放在了Task.hpp中,不再是一個類成員函數(shù)。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
此時將服務(wù)器運行起來以后,除了創(chuàng)建套接字等準(zhǔn)備工作外,還有線程池中會起來10個線程,這10個線程就是專門用來服務(wù)客戶端的。

兩個客戶端發(fā)送的信息服務(wù)端都能收到并且給對應(yīng)的回顯,而且互不影響,和前面多進程和多線程效果一樣。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
可以看到,此時服務(wù)器上存在10個從線程,主線程仍然在不停的accept,每有一個客戶端發(fā)起連接請求時,線程池就會安排一個線程去服務(wù),而不會再創(chuàng)建新的線程。

??日志功能

之前本喵在調(diào)用系統(tǒng)調(diào)用或者庫函數(shù)等有返回值的函數(shù)時,會根據(jù)返回值打印一些信息來表示該感受的調(diào)用結(jié)果,有時甚至?xí)褂缅e誤碼。

今天本喵來介紹一下日志,日志就是專門用來記錄程序的執(zhí)行信息的,這部分代碼放在log.hpp中,同樣可以作為一個小組件。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
函數(shù)logMessage就是用來記錄日志的,其中level表示日志等級,message是傳入的具體日志信息。

日志等級也就是程序運行過程中結(jié)果的重要程度:

  • DEBUG:表示調(diào)試信息,這是程序員在調(diào)試代碼時看的。
  • NORMAL:表示正常信息,就是代碼的運行結(jié)果是符合預(yù)期的。
  • WARING:表示警告信息,存在問題但只是警告,可以暫不處理。
  • ERROR:表示錯誤信息,代表代碼運行出現(xiàn)了錯誤,需要及時處理。
  • FATAL:表示致命信息,代表代碼出現(xiàn)了致命錯誤,無法運行下去了。

這些等級是我們?nèi)藶閯澐值模煌燃墝?yīng)的處理方式也是由我們自己控制的,比如發(fā)生ERROR時,是結(jié)束程序還是繼續(xù)運行,都是由我們自己控制的。

這是我本喵前面代碼使用的日志記錄函數(shù),真正的日志記錄肯定不可能這么簡單。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
如上圖所示,真正的日志函數(shù)采用的是可變參數(shù),如上圖所示代碼。

  • 注意:C語言的可變參數(shù)和可變模板參數(shù)不一樣。

logMessage函數(shù)的第三個參數(shù)...就表示可變參數(shù),本質(zhì)上是占位符,它的參數(shù)個數(shù)以及類型都是可以變化的。

參數(shù)列表的構(gòu)成:

  • 參數(shù)分為兩個部分:固定參數(shù)和可變參數(shù),至少有一個固定參數(shù),聲明和普通函數(shù)一樣。

實現(xiàn)原理:

C語言中使用 va_list 系列變參宏實現(xiàn)變參函數(shù),此處va意為variable-argument(可變參數(shù))。

typedef char * va_list;
// 把 n 圓整到 sizeof(int) 的倍數(shù)
#define _INTSIZEOF(n)       ( (sizeof(n)+sizeof(int)-1) & ~(sizeof(int)-1) ) 
// 初始化 ap 指針,使其指向第一個可變參數(shù)。v 是變參列表的前一個參數(shù)
#define va_start(ap,v)      ( ap = (va_list)&v + _INTSIZEOF(v) ) 
// 該宏返回當(dāng)前變參值,并使 ap 指向列表中的下個變參
#define va_arg(ap, type)    ( *(type *)((ap += _INTSIZEOF(type)) - _INTSIZEOF(type)) ) 
// /將指針 ap 置為無效,結(jié)束變參的獲取
#define va_end(ap)             ( ap = (va_list)0 )

這是stdarg.h頭文件中的定義,可以看到和可變參數(shù)有關(guān)的都是宏。

va_list本質(zhì)上就是一個char*類型的指針,指向的變量大小是一個字節(jié)。

  • _INTSIZEOF(n):_INTSIZEOF進行內(nèi)存地址對齊,按照sizeof(int)即棧粒度對齊,參數(shù)在內(nèi)存中的地址均為sizeof(int)=4的倍數(shù)。例如,若1≤sizeof(n)≤4,則_INTSIZEOF(n)=4;若5≤sizeof(n)≤8,則_INTSIZEOF(n)=8。
  • va_start(ap,v):根據(jù)va_list中的參數(shù) v 在棧中的內(nèi)存地址,加上_INTSIZEOF(v)占內(nèi)存大小后,使 ap 指向 v 的下一個參數(shù)。用這個宏初始化 ap 指針,v 是最后一個固定參數(shù),初始化的結(jié)果是 ap 指向第一個變參。

其他那兩個本喵就不介紹了,遇到了自行查閱就好。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

這一系列帶v的輸出函數(shù),最后一個參數(shù)類型是va_list,倒數(shù)第二個參數(shù)是format,也就是最后一個固定參數(shù)。

這一族函數(shù)就是專門用來處理可變參數(shù)的,這里本喵使用的是vsnprintf,將可變參數(shù)的內(nèi)容全部放入到logcontent中。

例如logMessage(NORMAL, "create socket success");,這里面的字符串被當(dāng)作了可變參數(shù),因為只有一個字符串,所以將其傳給了最后一個固定參數(shù)format

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
在我們的服務(wù)器中,在套接字創(chuàng)建成功后的日志信息中,增加_listensock,以可變參數(shù)的形式傳給logMessage,如上圖紅色框中所示。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

可以看到,成功打印出了監(jiān)聽套接字的文件描述符,如上圖綠色小框中所示,在前面還有日志的前綴信息[日志等級][時間戳][pid]。

日志不僅可以將數(shù)據(jù)打印到屏幕上,而且還可以輸出到文件中,將屏蔽掉的代碼解除注釋。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
將日志等級為NORMALDEBUG以及WARNING放入到LOG_NORMAL定義的文件路徑中。

將日志等級為ERRORFATAL的放入到LOG_ERROR定義的文件路徑中。

兩個文件都是以追加寫入的方式打開,寫入完畢后再關(guān)閉文件。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
在服務(wù)器中偽造出一些不同等級的日志信息,如上圖所示。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
服務(wù)器運行后,日志信息不僅打印在屏幕上,而且還輸出到了日志文件log.errorlog.txt中。

??守護進程

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
將服務(wù)器進程運行起來,如上圖所示,再查看當(dāng)前服務(wù)器上的網(wǎng)絡(luò)進程以及進程。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
可以看到,IP地址為0.0.0.0,端口號為8080,進程名為tcpserve的進程是存在的。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

  • 直接關(guān)掉Xshell會話窗口,不退出進程。
    【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
    此時再查看名為tcpserve的進程,已經(jīng)看不到了,說明它已經(jīng)退出了,但是我們明明沒有讓它退出啊,只是關(guān)掉了Xshell的窗口而已。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

  • 每一個Xshell窗口都會在服務(wù)器上創(chuàng)建一個會話,準(zhǔn)確的說會運行一個名字為bash的進程。
  • 每一個會話中最多只有一個前臺任務(wù),可以有多個后臺任務(wù)(包括0個)。

當(dāng)Xshell的窗口關(guān)閉后,服務(wù)器上對應(yīng)的會話就會結(jié)束,bash進程就退出了,bash維護的所有進程都會退出。所以關(guān)掉Xshell窗口后tcpserve進程就會退出。

這樣就存在一個問題,提供網(wǎng)絡(luò)服務(wù)的服務(wù)器難道運行了tcpserve就不能干別的了嗎?肯定不是。要想關(guān)掉Xshelltcpserve不退出,只能讓tcpserve自成一個會話。

  • 自成一個會話的進程就被叫做守護進程,也叫做精靈進程。

前后臺進程組:

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
上圖中,sleep 10000 | sleep 20000 | sleep 30000是通過管道一起創(chuàng)建的3個進程,這三個進程組成一個進程組,也被叫做一個作業(yè)。后面又加了&表示這個作業(yè)是后臺進程。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
使用指令jobs可以查看當(dāng)前機器上的作業(yè),如上圖所示,有3個作業(yè)在運行,而且都是后臺進程。

  • 前面的數(shù)組是進程組的編號,如上圖所示的【1】【2】【3】。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
通過指令gb+進程組編號,可以將后臺進程變成前臺進程,如上圖所示,此時Xshell窗口就阻塞住了,在做延時,我們無法輸入其他東西。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
將該進程組暫停后,繼續(xù)使用jobs可以看到,進程組1后面的&沒有了,表示這是一個前臺進程,只是暫停了而已。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
使用指令bg+進程組編號,可以將進程組設(shè)置為后臺進程,如上圖所示,此時進程組1后面的&又有了,并且進程運行了起來,也不再阻塞了,可以在窗口中繼續(xù)輸入指令了。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

可以看到,9個sleep進程的pid值都不同,因為它們是獨立的進程。

  • PGID表示進程組的ID,其中PID和PGID值相同的進程是這個進程組的組長。

PGID中本喵畫了三個框,每個框中有3個相同的PGID,所以此時就有3組進程,和前面使用管道創(chuàng)建的進程組結(jié)果一樣。

但是所有進程的PPID都是16496,這個進程就是bash,所以說,bash就是當(dāng)前會話中所有進程的父進程。

還有一個SID,表示會話ID,所有進程的SID都相同,因為它們同屬于一個會話。

  • PPID和SID之所以相同,是因為會話的本質(zhì)就是bash

??變成守護進程

要想讓會話關(guān)閉以后進程還在運行,就需要讓這個進程自成一個會話,也就是成為守護進程。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
系統(tǒng)調(diào)用setsid的作用就是將調(diào)用該函數(shù)的進程變成守護進程,也就是創(chuàng)建一個新的會話,這個會話中只有當(dāng)前進程。

  • 注意:調(diào)用系統(tǒng)調(diào)用setsid的進程在調(diào)用之前不能是進程組的組長,否則無法創(chuàng)建新的會話,也就無法成為守護進程。

如果調(diào)用成功,則返回新的會話id(SID),調(diào)用失敗,則返回-1,并且設(shè)置錯誤碼。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
如上圖代碼,daemonself就是讓我們的tcpserve變成守護進程,總共分為四步。

  1. 讓調(diào)用進程忽略異常信號

調(diào)用進程會變成守護進程,形成一個獨立的會話,此時它的具體運行情況我們是無法得知的。但是它有可能會受到異常信號的干擾而導(dǎo)致進程退出,此時我們根本不知道它退出了。

所以要忽略掉異常信號,尤其是管道信號,因為網(wǎng)絡(luò)服務(wù)程序就是在套接字中讀寫數(shù)據(jù),所以使用signal系統(tǒng)調(diào)用忽略掉SIGPIPE信號。

  1. 讓自己不是組長

setsid系統(tǒng)調(diào)用要求調(diào)用的進程不能是進程組的組長,所以要想辦法讓我們的tcpserve不是組長。

同樣采用if(fork()>0) exit(0)的策略,當(dāng)前進程退出,將后續(xù)代碼交給它的子進程,此時原本的組長就退出了,子進程成為孤兒進程被操作系統(tǒng)收養(yǎng)也就不是組長了。

子進程再調(diào)用setsid變成守護進程,自成一個會話。

  • 守護進程本質(zhì)上就是一個孤兒進程。
  1. 關(guān)閉或者重定向以前進程默認(rèn)打開的文件

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

在Linux中存在一個黑洞文件/dev/null,向該文件中寫入的內(nèi)容會被全部丟棄,從該文件中讀取內(nèi)容時什么也讀不到而且不會發(fā)生錯誤。

每個進程都會默認(rèn)打開文件描述符為0,1,2的三個文件,而守護進程是脫離終端的,沒有顯示器,沒有鍵盤等,所以要對這三個文件做處理。

  • 最好的方式就是將黑洞文件/dev/null重定向到這三個文件。
  • 如果無法重定向,那就只能關(guān)閉這三個文件了。
  1. 進程執(zhí)行路徑發(fā)生更改(可選)
    【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

每一進程都有一個cwd數(shù)據(jù),用來記錄當(dāng)前進程的所屬路徑,所以默認(rèn)情況下,進程文件所在的路徑就是當(dāng)前目錄。

成為守護進程后,如果需要更改tcpserve的執(zhí)行路徑,就可以通過系統(tǒng)調(diào)用chdir來改變cwd屬性,從而更改路徑。這里給的缺省值null

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux

如上圖所示,在tcpserve.cpp中調(diào)用daemonself,將tcpserve服務(wù)進程變成守護進程。
【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
在運行服務(wù)端程序后,服務(wù)器進程初始化,然后變成守護進程并且開始運行(這一點我們看不到)。當(dāng)前會話并沒有阻塞,仍然可以數(shù)據(jù)其他指令。

查看當(dāng)前服務(wù)器上的進程時,可以看到守護進程tcpserve的存在,并且它的PPID是1(操作系統(tǒng)),PID,PGID以及SID三者都是11251。

  • 守護進程自成會話,自成進程組,和終端設(shè)備無關(guān)。

【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
此時本喵的服務(wù)器仍然可以干其他任務(wù),tcpserve守護進程也在運行,并且自行按照我們寫的邏輯來接收客戶端的連接請求并進行網(wǎng)絡(luò)通信。


【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程,網(wǎng)絡(luò),網(wǎng)絡(luò),tcp/ip,linux
雖然有一個系統(tǒng)調(diào)用daemon可以讓一個進程變成守護進程,但是它并不太好用,實際應(yīng)用中都通過setsid自己實現(xiàn)daemon的,就像我們上面寫的一樣。

??總結(jié)

現(xiàn)在TCP網(wǎng)絡(luò)通信也見過了,雖然不知道原理,但是我們知道套接字的存在,以及網(wǎng)絡(luò)通信的代碼過程,和現(xiàn)象。除此之外本喵還介紹了常用小組件日志,以及如何讓一個進程變成守護進程。文章來源地址http://www.zghlxwxcb.cn/news/detail-595529.html

到了這里,關(guān)于【網(wǎng)絡(luò)】socket——TCP網(wǎng)絡(luò)通信 | 日志功能 | 守護進程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Unity】Socket網(wǎng)絡(luò)通信(TCP) - 最基礎(chǔ)的客戶端通信流程

    【Unity】Socket網(wǎng)絡(luò)通信(TCP) - 最基礎(chǔ)的客戶端通信流程

    這篇文章主要內(nèi)容是客戶端與服務(wù)器通信的內(nèi)容,服務(wù)端代碼可以看我的這一篇文章【Unity】Socket網(wǎng)絡(luò)通信(TCP) - 最基礎(chǔ)的C#服務(wù)端通信流程 客戶端與服務(wù)器的整個流程比較相似,客戶端會更加簡單一些: 創(chuàng)建socket 連接服務(wù)器 收發(fā)消息 釋放socket,關(guān)閉連接 和服務(wù)端創(chuàng)建

    2024年02月03日
    瀏覽(26)
  • 使用 python socket 實現(xiàn)UDP/TCP網(wǎng)絡(luò)通信

    使用 python socket 實現(xiàn)UDP/TCP網(wǎng)絡(luò)通信

    目錄 目錄 1.socket簡介 2.創(chuàng)建socket 2.1創(chuàng)建UDPSocket 2.2創(chuàng)建TCPSocket 3.使用UDPSocket發(fā)送數(shù)據(jù)并接收 4.使用UDPSocket發(fā)送廣播 5.UDPSocket聊天器 (多線程實現(xiàn)消息的收發(fā)功能) 6.使用TCPSocket建立客戶端 7.使用TCPSocket建立服務(wù)端 ? ? ? ?socket(簡稱:套接字),是支持TCP和UDP(網(wǎng)絡(luò)傳輸方式

    2023年04月10日
    瀏覽(25)
  • 【Unity】Socket網(wǎng)絡(luò)通信(TCP) - 最基礎(chǔ)的C#服務(wù)端通信流程

    【Unity】Socket網(wǎng)絡(luò)通信(TCP) - 最基礎(chǔ)的C#服務(wù)端通信流程

    我這里新建了一個C#控制臺項目來寫服務(wù)端代碼。 下面是基于C# Socket的最基礎(chǔ)服務(wù)端通信流程: 創(chuàng)建服務(wù)端Socket對象 綁定IP地址和端口 設(shè)置最大監(jiān)聽客戶端數(shù)量 等待客戶端連接 收發(fā)消息 釋放連接 基于上面流程就能實現(xiàn)一個最簡單并且能和客戶端通信的服務(wù)器程序,每個步

    2023年04月16日
    瀏覽(31)
  • 網(wǎng)絡(luò)編程day1——進程間通信-socket套接字

    ????????基本特征:socket是一種接口技術(shù),被抽象了一種文件操作,可以讓同一計算機中的不同進程之間通信,也可以讓不同計算機中的進程之間通信(網(wǎng)絡(luò)通信) ? ? ? ? 進程A? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????????????? 進程B ? ? 創(chuàng)建socket對象

    2024年02月10日
    瀏覽(107)
  • tcp/udp socket 網(wǎng)絡(luò)通信中超時時間的設(shè)置

    1.connect函數(shù)的超時時間設(shè)置只對TCP有效 UDP由于是無連接的connect都會返回success 有兩種方法: 第一種方法 默認(rèn)的socket是阻塞模式 我們只需要設(shè)置其為非阻塞模式,然后調(diào)用select去查詢其狀態(tài) 代碼如下:? 第二種是 默認(rèn)其為阻塞模式? 通過setsockopt 函數(shù)設(shè)置TCP_SYNCNT 值 頭文件

    2024年02月15日
    瀏覽(32)
  • UNIX網(wǎng)絡(luò)編程:socket & fork()多進程 實現(xiàn)clients/server通信

    UNIX網(wǎng)絡(luò)編程:socket & fork()多進程 實現(xiàn)clients/server通信

    UNIX網(wǎng)絡(luò)編程:socket實現(xiàn)client/server通信 隨筆簡單介紹了TCP Server服務(wù)單客戶端的socket通信,但是并未涉及多客戶端通信。 對于網(wǎng)絡(luò)編程肯定涉及到多客戶端通信和并發(fā)編程 (指在同時有大量的客戶鏈接到同一服務(wù)器),故本隨筆補充這部分知識。 而且并發(fā)并發(fā)編程涉及到多進程

    2024年02月06日
    瀏覽(23)
  • Linux網(wǎng)絡(luò)編程:socket & fork()多進程 實現(xiàn)clients/server通信

    Linux網(wǎng)絡(luò)編程:socket & fork()多進程 實現(xiàn)clients/server通信

    UNIX網(wǎng)絡(luò)編程:socket實現(xiàn)client/server通信 隨筆簡單介紹了TCP Server服務(wù)單客戶端的socket通信,但是并未涉及多客戶端通信。 對于網(wǎng)絡(luò)編程肯定涉及到多客戶端通信和并發(fā)編程 (指在同時有大量的客戶鏈接到同一服務(wù)器),故本隨筆補充這部分知識。 而且并發(fā)并發(fā)編程涉及到多進程

    2024年02月05日
    瀏覽(28)
  • Linux網(wǎng)絡(luò)編程:socket、客戶端服務(wù)器端使用socket通信(TCP)

    Linux網(wǎng)絡(luò)編程:socket、客戶端服務(wù)器端使用socket通信(TCP)

    socket(套接字),用于網(wǎng)絡(luò)中不同主機間進程的通信。 socket是一個偽文件,包含讀緩沖區(qū)、寫緩沖區(qū)。 socket必須成對出現(xiàn)。 socket可以建立主機進程間的通信,但需要協(xié)議(IPV4、IPV6等)、port端口、IP地址。 ??????? ?(1)創(chuàng)建流式socket套接字。 ? ? ? ? ? ? ? ? a)此s

    2024年02月11日
    瀏覽(34)
  • 「網(wǎng)絡(luò)編程」第二講:網(wǎng)絡(luò)編程socket套接字(三)_ 簡單TCP網(wǎng)絡(luò)通信程序的實現(xiàn)

    「網(wǎng)絡(luò)編程」第二講:網(wǎng)絡(luò)編程socket套接字(三)_ 簡單TCP網(wǎng)絡(luò)通信程序的實現(xiàn)

    「前言」文章是關(guān)于網(wǎng)絡(luò)編程的socket套接字方面的,上一篇是網(wǎng)絡(luò)編程socket套接字(二),下面開始講解!? 「歸屬專欄」網(wǎng)絡(luò)編程 「主頁鏈接」個人主頁 「筆者」楓葉先生(fy) 「楓葉先生有點文青病」「每篇一句」 I?do?not?know?where?to?go,but?I?have?been?on?the?road. 我不知

    2024年02月11日
    瀏覽(29)
  • Socket網(wǎng)絡(luò)編程(TCP/IP)實現(xiàn)服務(wù)器/客戶端通信。

    Socket網(wǎng)絡(luò)編程(TCP/IP)實現(xiàn)服務(wù)器/客戶端通信。

    一.前言 回顧之前進程間通信(無名管道,有名管道,消息隊列,共享內(nèi)存,信號,信號量),都是在同一主機由內(nèi)核來完成的通信。 那不同主機間該怎么通信呢? 可以使用Socket編程來實現(xiàn)。 Socket編程可以通過網(wǎng)絡(luò)來實現(xiàn)實現(xiàn)不同主機之間的通訊。 二.Socket編程的網(wǎng)絡(luò)模型如

    2024年02月08日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包