# 網路程式設計 HW04 學生: 1084837廖經翰 ## 1. 使用wireshark抓python echo client 連至 python echo server過程中所有的封包,並統計總共的封包數。 python echo client 連至 python echo server過程中的所有封包: <center><img style="margin-top:auto;border:1px #eee;width:100%;" src="https://i.imgur.com/KIGxZR4.png" /></center> <br> 建立連線的封包(3個封包): <center><img style="margin-top:auto;border:1px #eee;width:100%;" src="https://i.imgur.com/dgq8kka.png" /></center> <br> 來回傳送hello的封包(5次hello*4=20個封包): <center><img style="margin-top:auto;border:1px #eee;width:100%;" src="https://i.imgur.com/Ug4TaXR.png" /></center> <br> 結束連線的封包(4個封包): <center><img style="margin-top:auto;border:1px #eee;width:100%;" src="https://i.imgur.com/QZ0X5aq.png" /></center> <br> 總結: 藍色框的部分為建立連線的封包(3個),紅色框為來回傳送hello的封包(5*4=20個),綠色框為結束連線的封包(4個),所以 python echo client 連至 python echo server 過程中所有總共的封包數為3+20+4=27個封包。 <center><img style="margin-top:auto;border:1px #eee;width:100%;" src="https://i.imgur.com/rl1tD2D.png" /></center> <br> ## 2. 實作Simple TCP/IP Server 這次的作業我是用C寫的程式,主要是模擬TCP/IP Server的四種服務,也就是Discard、Daytime、Quote、Chargen,這四種服務我個別寫四個程式來執行,每個服務都會有相對應的功能。 ### (1)丟棄服務 (Discard) 第一個程式主要的功能就是實作出Discard server,Discard server只需要去接收client傳過來的內容(使用者輸入字元)就好,不需要回傳東西給client。 執行畫面: <center>Server</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/xm4f8SC.png" /></center> <br> <center>client</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/SBinJIv.png" /></center> <br> client啟動: telnet localhost 1234 server程式碼: ```C= #include<stdio.h> #include<string.h> #include<winsock.h> #include<conio.h> int main() { SOCKET sd , clnt_sd; WSADATA wsadata; struct sockaddr_in serv , clnt; int n; char str[100]; //接收client所傳的內容 WSAStartup( 0x101, &wsadata ); sd = socket( AF_INET , SOCK_STREAM , 0 ); //開啟一個TCP socket serv.sin_family = AF_INET; //使用IPv4 serv.sin_port = htons( 1234 ); //設定port number serv.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //設定ip address bind( sd, (struct sockaddr *) &serv, sizeof(serv) ); //將socket綁定serv的資訊 listen(sd,5); //server開始監聽或等待client //實作discard server,所以不需要回傳東西給client while(1) { int clnt_len = sizeof( clnt ); printf( "Server waits...\n" ); clnt_sd = accept( sd, (struct sockaddr *) &clnt, &clnt_len ); //server收到連線 while(1) { n = recv( clnt_sd, str, 100, 0); //接收client傳送的內容 if( n > 0 && str[0] == '.' ) //當按.就停止服務 { break; } str[n] = '\0'; //加入停止符號 printf( "Server recveive: %s\n", str ); //輸出client所傳的內容 } closesocket( clnt_sd ); //關閉server與該client的socket } //關閉server的服務 closesocket( sd ); WSACleanup(); system("pause"); return 0; } ``` ### (2)日期時間服務 (Daytime) 第二個程式主要的功能就是實作出Daytime server,Daytime server只需要在server端印出目前電腦的時間,並且把目前的時間回傳給client端後,連線自動斷掉。 執行畫面: <center>Server</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/9aIw2xM.png" /></center> <br> <center>client</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/mN3nk7d.png" /></center> <br> client啟動: telnet localhost 1234 server程式碼: ```C= #include<stdio.h> #include<string.h> #include<winsock.h> #include<conio.h> #include<time.h> int main() { SOCKET sd , clnt_sd; WSADATA wsadata; struct sockaddr_in serv , clnt; WSAStartup( 0x101, &wsadata ); sd = socket( AF_INET , SOCK_STREAM , 0 ); //開啟一個TCP socket serv.sin_family = AF_INET; //使用IPv4 serv.sin_port = htons( 1234 ); //設定port number serv.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //設定ip address bind( sd, (struct sockaddr *) &serv, sizeof(serv) ); //將socket綁定serv的資訊 listen(sd,5); //server開始監聽或等待client //實作daytime server,所以只需要在server端印出時間,並且把時間回傳給client端 while(1) { int clnt_len = sizeof( clnt ); printf( "Server waits...\n" ); clnt_sd = accept( sd, (struct sockaddr *) &clnt, &clnt_len ); //server收到連線 //時間的struct time_t rawtime; struct tm * timeinfo; time( &rawtime ); timeinfo = localtime( &rawtime ); printf( "Server sends time: %s\n", asctime(timeinfo) ); //在server端輸出目前的時間 send(clnt_sd, asctime(timeinfo), strlen( asctime(timeinfo) )+1, 0); //把目前的時間回傳給client端 closesocket( clnt_sd ); //關閉server與該client的socket } //關閉server的服務 closesocket( sd ); WSACleanup(); system("pause"); return 0; } ``` ### (3)每日一句 (QUOTE) 第三個程式主要的功能就是實作出QUOTE server,QUOTE server只需要在server端印出每日一句,並且把每日一句回傳給client端後,連線自動斷掉。 執行畫面: <center>Server</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/hog0FsZ.png" /></center> <br> <center>client</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/MVR9K2U.png" /></center> <br> client啟動: telnet localhost 1234 server程式碼: ```C= #include<stdio.h> #include<string.h> #include<winsock.h> #include<conio.h> #include<time.h> int main() { //存每日一句的array char quote_array[200][400] = {"武力無法維持和平,只有相互理解可以。","如果你害怕失敗,那你很有可能會失敗。", "勝利是留給凡事都準備好的人,但一般人都以為只是運氣好。", "時常提醒自己是有人愛的、不孤單的,快樂就會油然而生。", "我們跌倒的地方,是我們人生旅途上的墊腳石。", "天生好手能贏得比賽,但團隊合作才能贏得冠軍。", "一天一蘋果,醫生遠離我。", "人生就像騎單車,要保持平衡,就必須一直向前。", "一個從未犯錯的人,是因為他不曾嘗試新鮮事物。", "學習過去,活在當下,憧憬未來。重要的是不要停止發問。"}; SOCKET sd , clnt_sd; WSADATA wsadata; struct sockaddr_in serv , clnt; WSAStartup( 0x101, &wsadata ); sd = socket( AF_INET , SOCK_STREAM , 0 ); //開啟一個TCP socket serv.sin_family = AF_INET; //使用IPv4 serv.sin_port = htons( 1234 ); //設定port number serv.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //設定ip address bind( sd, (struct sockaddr *) &serv, sizeof(serv) ); //將socket綁定serv的資訊 listen(sd,5); //server開始監聽或等待client //實作quote server,所以只需要在server端印出每日一句,並且把每日一句回傳給client端 while(1) { int clnt_len = sizeof( clnt ); printf( "Server waits...\n" ); clnt_sd = accept( sd, (struct sockaddr *) &clnt, &clnt_len ); //server收到連線 //設定0~9的隨機語句 srand( time(NULL) ); int random_num = rand() % 10; printf( "Server sends goodwords: %s\n", quote_array[random_num] ); //在server端輸出每日一句 send(clnt_sd, quote_array[random_num], strlen( quote_array[random_num] )+1, 0); //把每日一句回傳給client端 closesocket( clnt_sd ); //關閉server與該client的socket } //關閉server的服務 closesocket( sd ); WSACleanup(); system("pause"); return 0; } ``` ### (4)字元產生器 (CHARGEN) 第四個程式主要的功能就是實作出Chargen server,Chargen server只需要在server端一直印出asc code,並且把asc code回傳給client端,當按ctrl+c的時候才會把程式中止並且連線斷掉。 執行畫面: <center>Server</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/seN55vN.png" /></center> <br> <center>client</center> <center><img style="margin-top:auto;border:1px #eee;width:70%;" src="https://i.imgur.com/gAhZ4k7.png" /></center> <br> client啟動: telnet localhost 1234 server程式碼: ```C= #include<stdio.h> #include<string.h> #include<winsock.h> #include<conio.h> #include<time.h> int main() { char asc_code[100] = "“!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefg”"; int count = 0; SOCKET sd , clnt_sd; WSADATA wsadata; struct sockaddr_in serv , clnt; WSAStartup( 0x101, &wsadata ); sd = socket( AF_INET , SOCK_STREAM , 0 ); //開啟一個TCP socket serv.sin_family = AF_INET; //使用IPv4 serv.sin_port = htons( 1234 ); //設定port number serv.sin_addr.s_addr = inet_addr( "127.0.0.1" ); //設定ip address bind( sd, (struct sockaddr *) &serv, sizeof(serv) ); //將socket綁定serv的資訊 listen(sd,5); //server開始監聽或等待client //實作chargen server,所以只需要在server端一直印出asc code,並且把asc code回傳給client端 while(1) { int clnt_len = sizeof( clnt ); printf( "Server waits...\n" ); clnt_sd = accept( sd, (struct sockaddr *) &clnt, &clnt_len ); //server收到連線 //這裡跑無限迴圈,按下crtl+c就可以停止程式 while(1) { printf( "%s\n", asc_code ); //在server端一直輸出asc code send(clnt_sd, asc_code, strlen( asc_code )+1, 0); //把asc code回傳給client端 } closesocket( clnt_sd ); //關閉server與該client的socket } //關閉server的服務 closesocket( sd ); WSACleanup(); system("pause"); return 0; } ``` ## 3. 本週心得 上一次的課程老師講解的是client端的部分,但這一次老師講解是server端的部分,我覺得網路程式最累的地方就是不但要寫server端的程式,還要寫client端的程式,而且server端與client端必須要程式相容才可以順利執行,只要有一邊出問題可能就會有不如預期的結果,我覺得每次老師講解的內容都非常的好了解,我也很喜歡並且期待每個星期三都可以上老師的網路程式設計,因為每一次上老師的網路程式設計都可以學到新的東西與新的工具,而且老師講得又非常的清楚與詳細,因為課程是使用錄影帶的方式來教學,這樣如果之後忘記或是想要複習的話還是可以重新看老師的教學影片,這樣的教學模式讓我覺得學習這堂課起來非常的扎實,謝謝老師。 ### 作者: 廖經翰