# 網路程式設計 w3
## 第一題 使用wireshark抓封包
- 請使用wireshark抓當telnet echo server時,分別鍵入ncyu並按下enter鍵結束,請截圖顯示此過程的所有的tcp封包,並統計共有幾個。

- 封包總共顯示23個
- TCP三次交握:3個

- n訊息傳送 :4個

- c訊息傳送 :4個

- y訊息傳送 :4個

- u訊息傳送 :4個

- TCP四次揮手:4個

## 第二題 5種服務的示範程式
- 程式碼
```C++=
#include <iostream>
#include <cstring>
#include <iomanip>
#include <winsock.h>
#define MAX_LINE 1024
using namespace std;
void printService();
int opition(int);
int main(int argc,char** argv){
system("chcp 65001");
int port = 0;
int resvByte = 1;
// window socket set up
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
// Open a TCP socket
SOCKET sd;
sd=socket(AF_INET, SOCK_STREAM, 0);
// Server information
struct sockaddr_in serv;
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
// Service print
printService();
cin>>port;
port = opition(port);
serv.sin_port= htons(port);
// message
string mSend;
char mRecv[MAX_LINE];
connect(sd, (LPSOCKADDR) &serv, sizeof(serv));
switch (port)
{
case 7: //Echo Service
cout<<"Enter your message:\n";
cin.ignore();
getline(cin, mSend);
send(sd, mSend.c_str(), mSend.size()+1, 0);
resvByte = recv(sd, mRecv, MAX_LINE, 0);
break;
case 9: //Discard Service
cout<<"Enter your message:\n";
cin.ignore();
getline(cin, mSend);
send(sd, mSend.c_str(), mSend.size()+1, 0);
break;
case 13: //Daytime Service
resvByte = recv(sd, mRecv, MAX_LINE, 0);
break;
case 17: //Quote Service
resvByte = recv(sd, mRecv, MAX_LINE, 0);
break;
case 19: //Char Generator Service
resvByte = recv(sd, mRecv, MAX_LINE, 0);
break;
default:
cerr<<"Invalid Number!\n";
exit(1);
break;
}
//print result
cout<<"______________執行結果______________\n";
cout<<"[傳送內容]\n"<< mSend<<endl;
cout<<"[傳送內容長度]"<< mSend.size()+1<<" Bytes"<<endl;
cout<<"____________________________________\n";
cout<<"[回應內容]\n"<< string(mRecv) << endl;
cout<<"[回應內容長度]"<<resvByte<<" Bytes"<<endl;
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
void printService(){
cout << "____________________________________\n";
cout << "| 1. Echo 回應模式 |\n" ;
cout << "| 2. Discard 丟棄模式 |\n" ;
cout << "| 3. Daytime 日期與時間模式 |\n";
cout << "| 4. QUOTE 每日一句 |\n";
cout << "| 5. CHARGEN 字元產生器 |\n";
cout << "|___________________________________|\n";
}
int opition(int n){
switch (n)
{
case 1:
return 7;
break;
case 2:
return 9;
break;
case 3:
return 13;
break;
case 4:
return 17;
break;
case 5:
return 19;
break;
default:
cerr<<"Invalid Number!";
exit(1);
break;
}
}
```
- 執行結果
- Echo

- Discard

- QUOTE

- ps. 出現亂碼是BIG-5與UTF-8編碼問題(我這邊預設是UTF-8,所以導致亂碼)
- QUOTE

- CHARGEN

- 特例討論
- 本程式碼在選取選單時不能超過1~5,若超過程式會報錯,並傳送錯誤訊息

## 第三題:心得
這周玩telnet好好玩,之前計算機網路只知道他是文字互動功能,可以實現遠端控制,這次有機會玩他。BTW,我之前有聽過telnet未加密過,容易被竊聽,所以現今都用ssh加密連線。
作業的部分,我感覺我對抓封包越來越熟悉了,但程式作業中文字串的編碼問題真的好麻煩,我日期那邊有產生亂碼(我猜是Big-5編碼),後來查好久都沒有很實際的方法(我的consloe使用UTF-8顯示),希望這周有電神同學有實際方式實踐orz。
## 3/12後記
後來有用Python寫,發現剛好可以解決Big-5編碼問題(但我C++還是無解),Python Socket在傳輸時是用Byte這個資料型態傳送,因此只要調整編碼格式就可以順利解決
```python=
import socket
import os
def printMeun():
print("_____________________________________")
print("| 1. Echo 回應模式 |")
print("| 2. Discard 丟棄模式 |")
print("| 3. Daytime 日期與時間模式 |")
print("| 4. QUOTE 每日一句 |")
print("| 5. CHARGEN 字元產生器 |")
print("_____________________________________")
def servicePort(service:int) -> int:
match service:
case 1:
return 7
case 2:
return 9
case 3:
return 13
case 4:
return 17
case 5:
return 19
case _:#Default
print("Please enter 1~5")
exit
# Socket set up
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = "127.0.0.1"
PORT = -1
sendData = ""
recvData = ""
printMeun()
PORT = servicePort(int(input()))
s.connect((HOST, PORT))
if PORT == 7:
sendData = input("Please enter message u want to send:")
s.send(sendData.encode()) #Send data by byte
recvData = s.recv(1024).decode()
if PORT == 9:
sendData = input("Please enter message u want to send:")
s.send(sendData.encode()) #Send data by byte
if PORT == 13 or PORT == 17 or PORT == 19:
recvData = s.recv(1024).decode('big5')
print("______________執行結果______________")
print(f"[傳送內容]: {sendData}")
print(f"[傳送內容長度] {len(sendData) + 1} Bytes")
print("____________________________________")
print(f"[回應內容]: {recvData}")
print(f"[回應內容長度] {len(recvData) + 1} Bytes")
os.system("pause")
```
- 執行結果




