<TCP/IP網(wǎng)絡(luò)編程> Chap.5 基于TCP的服務(wù)器端/客戶端(2)

已知字符串長度情況下完善回聲客戶端

# gcc echo_client2.c -o eclient2
# ./eclient2 127.0.0.1 9190
Connected
Input message (Q to quit): orange
Message from server: orange
Input message (Q to quit): hhhhhhhhhhhhhhhhhhhhhhhhhhhh
Message from server: hhhhhhhhhhhhhhhhhhhhhhhhhhhh
Input message (Q to quit): q

服務(wù)端同上一章。


定義應(yīng)用層協(xié)議

原書中有些bug,服務(wù)端接收到的操作數(shù)個(gè)數(shù)沒有轉(zhuǎn)換成int。經(jīng)fix后代碼見附錄,運(yùn)行結(jié)果如下:

# ./opserver 9190
Connected client 1 
Connected client 2 
Connected client 3 
# ./opclient 127.0.0.1 9190
Connected
Input operand count: 3
Input operand: 1
Input operand: 5
Input operand: 9
Input operator: +
Operation result: 15
# ./opclient 127.0.0.1 9190
Connected
Input operand count: 4
Input operand: 16
Input operand: 8
Input operand: 4
Input operand: 2
Input operator: -
Operation result: 2
# ./opclient 127.0.0.1 9190
Connected
Input operand count: 2
Input operand: 5
Input operand: 7
Input operator: *
Operation result: 35


TCP原理

I/O緩沖特性:

  • I/O緩沖在每個(gè)TCP套接字中單獨(dú)存在。
  • I/O緩沖在創(chuàng)建套接字時(shí)自動生成。
  • 即使關(guān)閉套接字也會繼續(xù)傳遞輸出緩沖區(qū)中的遺留數(shù)據(jù)。
  • 關(guān)閉套接字將丟失輸入緩沖區(qū)中的遺留數(shù)據(jù)。


習(xí)題

  1. 請說明TCP套接字連接設(shè)置的三次握手過程。尤其是3次數(shù)據(jù)交換過程每次收發(fā)的數(shù)據(jù)內(nèi)容。
    1)A向B發(fā)起連接,發(fā)送SYN包(SYN=1,seg=X)
    2)B回復(fù)SYN_ACK包(SYN=1,ACK=1,seg=Y,ack number=X+1)
    3)最后A向B傳輸消息(ACK=1,seg=X+1,ack number=Y+1)
    從步驟3)開始A就可以攜帶應(yīng)用層數(shù)據(jù)了。
  2. TCP是可靠的數(shù)據(jù)傳輸協(xié)議,但在通過網(wǎng)絡(luò)通信的過程中可能丟失數(shù)據(jù)。請通過ACK和SEQ說明TCP通過何種機(jī)制保證丟失數(shù)據(jù)的可靠傳輸。
    SEQ是當(dāng)前數(shù)據(jù)起始字節(jié)的序號,加入收到對方返回的ACK剛好是SEQ+數(shù)據(jù)大?。ㄒ宰止?jié)為單位),則代表正確送達(dá),可以繼續(xù)發(fā)送后續(xù)數(shù)據(jù)包。反之,在計(jì)時(shí)器超時(shí)后進(jìn)行重傳。
  3. TCP套接字中調(diào)用write和read函數(shù)時(shí)數(shù)據(jù)如何移動?結(jié)合I/O緩沖進(jìn)行說明。
    write函數(shù)調(diào)用瞬間,數(shù)據(jù)將移至輸出緩沖;read函數(shù)調(diào)用瞬間,從輸入緩沖讀取數(shù)據(jù)。
  4. 對方主機(jī)的輸入緩沖剩余50字節(jié)空間時(shí),若本方主機(jī)通過write函數(shù)請求傳輸70 字節(jié),請問TCP如何處理這種情況?
    將70字節(jié)數(shù)據(jù)放入輸出緩沖,然后發(fā)送50字節(jié)到對方主機(jī),待對方主機(jī)的輸入緩沖又有剩余時(shí)再發(fā)送后面的字節(jié)。
  5. 第2章示例tcp_server.c和tcp_client.c中,客戶端接收服務(wù)器端傳輸?shù)淖址蟊阃顺觥,F(xiàn)更改程序,使服務(wù)器端和客戶端各傳遞1次字符串??紤]到使用TCP協(xié)議,所以傳遞字符串前先以4字節(jié)整數(shù)型方式傳遞字符串長度。連接時(shí)服務(wù)器端和客戶端數(shù)據(jù)傳輸格式如下。另外,不限制字符串傳輸順序及種類,但須進(jìn)行3次數(shù)據(jù)交換。
    代碼見附錄。
    0   0   0   6   H   e   l   l   o   ?
   |-- 字符串長度 --|------ 字符串?dāng)?shù)據(jù) ------|
# gcc tri_server.c -o tserver
# ./tserver 9191
Connected client 1 
Message from client: Hello?
Input message: Hi!
Message from client: This is Xiao.
Input message: I'm Yao.
Message from client: Nice to meet you!
Input message: Me, too.
# gcc tri_client.c -o tclient
# ./tclient 127.0.0.1 9191
Connected
Input message: Hello?
Message from server: Hi!
Input message: This is Xiao.
Message from server: I'm Yao.
Input message: Nice to meet you!   
Message from server: Me, too.
  1. 創(chuàng)建收發(fā)文件的服務(wù)器端/客戶端,實(shí)現(xiàn)順序如下。
    a. 客戶端接受用戶輸入的傳輸文件名。
    b. 客戶端請求服務(wù)器端傳輸該文件名所指文件。
    c. 如果指定文件存在,服務(wù)器端就將其發(fā)送給客戶端;反之,則斷開連接。
    代碼見附錄。
# gcc file_server.c -o fserver
# ./fserver 9190
Connected client
# gcc file_client.c -o fclient
# ./fclient 127.0.0.1 9190
Connected
Input file name: exercise6


我的問題

  1. 把int存到char型數(shù)組中后發(fā)生了什么?
  2. fgetc(stdin)的作用?
    刪除stdin中的"\n"字符,因?yàn)榍懊孀x取操作數(shù)的時(shí)候,最后有一個(gè)回車,他不能被當(dāng)做運(yùn)算符讀進(jìn)來。而前面讀操作數(shù)之前為什么不fgetc一下呢?因?yàn)樽x取的是%d,它會自動找到整數(shù)來讀取,忽略先導(dǎo)的空白符(指空格符、制表符、回車符)。但當(dāng)讀取的是%c的時(shí)候,scanf把緩沖區(qū)的第一個(gè)字符返回回去,不管是什么,所以如果不fgetc就會讀取出“\n”。
  3. seq與ack number的關(guān)系?
    書中的seq與ack number有錯誤。以圖5-4為例進(jìn)行改正。
A                                           B
|    --- seq 1200 (100 bytes data) -->      |
|         <-- ack number 1300 ---           |
|    --- seq 1300 (100 bytes data) -->      |
|         <-- ack number 1400 ---           |
  1. C語言如果不初始化局部整型變量,里面的值是什么?
    與編譯器有關(guān)。對GCC來說,局部整型變量里的值是隨機(jī)的。所以初始化是必需的。
  2. 為什么要用fgets讀取用戶輸入,而不是scanf?
    scanf遇空白符(空格、回車、制表符)即終止讀取,無法一次性讀取完整的一個(gè)句子。而fgets每次讀取一行。


附錄

[1] 關(guān)于int整數(shù)轉(zhuǎn)換存儲到字符數(shù)組
[2] scanf用法及scanf中有\(zhòng)n的問題
[3] TCP連接建立的三次握手過程可以攜帶數(shù)據(jù)嗎?
[4] Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容