# Socket Programming Report
---
## 學生:B1105142 李旼學
## 授課老師: 蔡仁勝教授
___
## 報告內容
## 一.實驗目的:
使用socket programming 模擬 client server間的 TCP connection , 並利用wireshark分析封包
## 二.實驗材料:
vscode,wireshark
## 三.程式碼:
▾以下是server的socket
```
import socket
import random
server_name = "Server of Nuk"
server_ip = "127.0.0.1"
server_port = 2000
'''
建立server的名字 以及所對應的IP以及Port
'''
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((server_ip, server_port))
server_socket.listen(0)
print(f"listening on {server_ip}:{server_port}")
'''
建立server的socket 採用IPV4以及TCP的服務 並將一開始建立的IP以及Port植入socket
接下來便開始監聽是否有人呼叫server
'''
while True:
connection, client_address = server_socket.accept()
print("Connection from", client_address)
'''
若有client來建立連線 則接受連線後 印出client address
'''
data = connection.recv(1024)
if not data:
break
client_name, client_number = data.decode().split(',')
'''
此時根據題目要求 client會在此時傳送資料 內含它的名字以及所輸入的number
server此時接收到這個封包 並將資料extract出來
'''
if 1 <= int(client_number) <= 100:
print(f"Client_name: {client_name}")
print(f"Server_name: {server_name}")
server_number = random.randint(1, 100)
sum = int(client_number) + server_number
print(f"Client_number: {client_number}")
print(f"Server_number: {server_number}")
print(f"Sum: {sum}")
server_reply = f"{server_name},{server_number}"
connection.send(server_reply.encode())
else:
print("Client number is not in the range 1 to 100. Closing connection.")
'''
接下來根據題目要求 如果client_number在1到100之間 就印出client_name跟server_name
然後server在1到100間隨機選一數 與client_number相加 接著印出 client_number
Server_number跟兩者的sum 接著server回傳一個reply給client 裡面包含了server_name
以及Server_number 但如果client_number不在範圍內 就直接close connection
'''
connection.close()
```
▾以下是client的socket
```
import socket
client_name = "Client of Louis"
server_ip = "127.0.0.1"
server_port = 2000
'''
建立client的名字 以及要連結的server Ip 跟 Port
'''
client_number=input("Enter the number between 1 and 100:")
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((server_ip,server_port))
'''
建立client的socket 採用IPV4以及TCP的服務 接著輸入1到100之間的數字後
與server建立連線
'''
client_send = f"{client_name},{client_number}"
client_socket.send(client_send.encode())
'''
接著建立封包內含client_name跟client_number encode後傳送給server
'''
data= client_socket.recv(1024)
server_name, server_number = data.decode().split(',')
'''
收到server回傳的封包 內含server_name跟server_number
然後將其extract出來
'''
sum = int(client_number) + int(server_number)
print(f"Client Name: {client_name}")
print(f"Server Name: {server_name}")
print(f"Client Number: {client_number}")
print(f"Server Number: {server_number}")
print(f"Sum: {sum}")
'''
印出上述5個設定的值
'''
client_socket.close()
```
程式碼的撰寫想法附在程式中,其實只要了解TCP連線的步驟,以及熟悉python寫socket時的語法,就能輕鬆實現這次的實驗.
## 四.實驗結果:
case1: 當client number介於1到100之間時
▾以下是server在vscode上的結果

▾以下是client在vscode上的結果

由結果可得知,此client server的行為跟報告要求相同,而且可看出此時cilent的port為59765.
case2:當client number不在1到100之間時
▾以下是server在vscode上的結果

▾以下是client在vscode上的結果

可看出當client number不在1到100之間時,server會直接結束連線,而client
因為收不到server的封包而error, 接著觀察此時client的port變成64071,
與前一次不同,是因為執行了兩次不同的連線,而cilent使用了dynamic port,也
會相應的改變.
## 五.實驗討論:
有了以上的結果後,接下來就是使用wireshark,分析擷取到的封包,來進行進一步的解讀.先觀察server(port 2000)擷取到的封包,以下為wireshark的結果.

以下為在client(port 59765)擷取到的封包

首先先分析封包的流程,一開始由client發送SYN要求連線,server則回覆一個SYN ACK,client此時在送一個ACK表示收到回覆,建立起一個 3-way hand-shaking.接下來cilent傳送一個含有其名字跟number的封包給server,也就是PSH ACK這個封包,server收到後回覆一個ACK.接著server回傳其名字跟number給client,就是server端的PSH ACK封包,client收到後回復一個ACK.接著server發送FIN ACK請求終止連線,client收到後回覆一個ACK,接著也發送一個FIN ACK請求終止連線,server回覆一個ACK後,這次的流程就結束了.
接下來分析上課所說過的seq以及ack,我將其流程畫成以下的圖形.

當client傳送pkt時,其len為19,所以server回傳ack20,表示20前的byte都收到了.當server傳送pkt時,其len為16,所以cilent回傳seq20 ack17,因為前面傳送了20bytes,ack17則表示17以前的都收到了.

探究封包中的內容,也可以發現上課所說的window以及checksum.