本章首先編寫了1個伺服器回射程式,1個客戶傳送程式。隨後根據各類問題,進行相應的改進。這裡記錄一下 改進的過程。
伺服器程式很簡單, 大概是以下幾步:
建立套接字->繫結位址結構->監聽
進入while迴圈, 做accpet等待連線建立->一旦連線建立成功, 返回乙個connecfd套接字, 並fork乙個子程序
父程序關閉connecfd套接字,繼續進入accpet等待連線
子程序執行回射函式-> 回射函式是乙個while迴圈,不斷從客戶套接字中read對應的資料,並傳送回去。 當read返回<=0即輸入了eof或read出錯時, 退出迴圈,輸出報錯資訊
#include "unp.h"
void str_echo(int sockfd)
if(n < 0 && errno == eintr)
else if (n < 0)
}int main(int argc, char **argv)
close(connfd);
}}
客戶程式:
建立套接字->與要發往的伺服器位址進行connect
當connect返回時,說明連線建立成功,執行傳送函式
傳送函式是1個while迴圈。每次在標準輸入上fgets讀取一行,然後傳送給伺服器,
傳送之後readline伺服器上發回的資料,並輸出。
如果readline返回錯誤,則報錯。
#include "unp.h"
#include void str_cli(file *fp, int sockfd)
}int main(int argc, char **argv)
sockfd = socket(af_inet, sock_stream, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = af_inet;
servaddr.sin_port = htons(serv_port);
inet_pton(af_inet, argv[1], &servaddr.sin_addr);
connect(sockfd, (sa *) &servaddr, sizeof(servaddr));
str_cli(stdin, sockfd);
exit(0);
}
正常終止:
當我們在客戶程序上輸入eof關閉(ctrl +d)時,fgets讀入空指標->退出while迴圈->退出函式->程式執行完畢,
程序關閉
->程序關閉時,自動關閉開啟的所有套接字,於是客戶tcp傳送fin給伺服器,進行四次揮手。
注意:連線中止後,通過netstat可以檢視到客戶套接字此時正處於timewait狀態,大概好幾秒之後才真正關閉。
存在的問題:伺服器子程序因為readline收到fin而退出,結束,但是父程序並沒有處理子程序結束的操作
所以,子程序變成了僵死程序,並沒有真正的被清除,其空間和副本被保留,如果忽略該處理,記憶體會被耗盡。
改進a——處理僵死程序:
在伺服器程序開啟監聽之後, 加入signal(sigchld,sig_chld),即程序開啟對「子程序終止」訊號的捕捉
一旦捕捉到,則執行sig_chld函式
sig_chld函式: 該函式中執行了wait函式,等待1個子程序返回,並**對應狀態資訊。
注意1:這個訊號的捕捉一定是父程序才能捕捉得到。
注意2:當該訊號捕捉到時,父程序正阻塞於accept上,此時執行了訊號中斷,於是accpet出錯
返回的錯誤是「中斷錯誤」
所以伺服器**中,在accpet返回的是錯誤且錯誤是中斷錯誤時, 要繼續執行while迴圈做accpet
而不是直接結束整個程序
存在的問題:當有多個子程序同時終止時,會在同一時間內產生多個sigchld訊號, 導致wait的接受存在不確定性
改進b——處理多個子程序終止的情況
在sig_chld訊號處理函式中, 加入while迴圈,並執行不阻塞的waitpid,用迴圈依次將死掉的子程序乙個個取出。
#include "unp.h"
void str_echo(int sockfd)
if(n < 0 && errno == eintr)
else if (n < 0) }
void sig_chld(int signo)
int main(int argc, char **argv)
if( (childpid = fork()) ==0)
close(connfd);
}}
存在的問題: 如果突然kill掉伺服器子程序, 雖然伺服器作為結束發起方,傳送了fin給客戶,客戶也回應了ack
但根據四次揮手的協議,客戶要發完要發的資料,才會傳送fin
這時候客戶阻塞在 讀取終端輸入上。只有當我們輸入字串,讓客戶端端傳送時,客戶才會收到伺服器發回的rst
然後才執行fin傳送。
這個問題應該由select和poll解決
伺服器的主機崩潰(類似於網路斷開,不是程序關閉)
此時客戶沒有收到fin等資訊,於是會不斷進行重傳,直到超時,相應目的地不可達。
伺服器主機崩潰後又重啟
此時程序已經在崩潰後不存在了,但是並沒有傳送fin等操作, 但主機上的tcp仍會收到客戶發來的tcp
此時會自動相應乙個rst
伺服器關機
關機與崩潰不同,關機時,會用init程序來關閉所有程序,並關閉所有描述符,使得客戶能夠檢測到。
傳送二進位制資料
可能會因為大小端不同,出現問題。
第五章 讀書筆記
第五章 搭建s3c6410開發板的測試環境 一.s3c6410開發板簡介.s3c6410是三星公司推出的一款低功耗,高價效比的risc處理器,它基於arm11核心,可廣泛應用於移動 和通用處理器等領域。該處理器有乙個非常先進的3d加速器,能實現4m s的3d加速 二.安裝串列埠除錯工具 minico...
C Template 讀書筆記 第五章
內容 技巧性基礎知識 關鍵字 typename template this 模板的模板引數 零初始化 字串的模板實參 具體內容描述 1.對模板使用typename 場景 template class test 這裡需要增加typename,需要標記告訴編譯器這個是宣告乙個模板引數型別t裡面的subt...
C 讀書筆記 第五章 語句
空語句 程式某處語法上需要一條語句而邏輯上不需要 建議使用時加注釋 while cin s s sought 空塊的作用等同於空語句 上面的 也可以用 代替 懸垂 else switch case關鍵字和它對應的值一起被稱為case標籤,case標籤必須是整形常量表示式 case 3.14 錯誤 不...