# 網路程式設計 Week8
## LAB1: 以UDP來一送一收
- 程式碼
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on 12345");
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",1234
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
print("UDP Server up and listening...")
while True:
data, ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {data.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include <stdio.h>
#include <winsock.h>
char DATA[100] = "\\C is very hard!!!!!!/";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Client socket => ready to connect to server
note nate we use UDP, so the socket of client is sock datagram
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Start to send data to server
*/
int n = sendto(
sd,
DATA, strlen(DATA),0,
(LPSOCKADDR) &serv, sizeof(serv)
);
printf("Send: %s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
DATA = "I Love Python!!!!"
HOST,PORT = "127.0.0.1",1234
clientSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
clientSocket.sendto(DATA.encode(),(HOST,PORT))
print(f"Message send: {DATA}")
```
:::
- 實驗結果
- 有CS架構下,UDP程式只會有一個封包
- Wireshark抓取結果

- 無CS架構下,UDP程式扔會傳送一個封包
- Wireshark抓取結果

- Wait... 理論上不會產生ICMP吧
- ICMP是網際網路控制訊息協定,幾乎每個人的網路封包都有,用以表示網路狀態,這邊產生原因是找不到目的地,代表我沒有Server
- 在TCP程式無Server下,會因無法建立連線而傳送失敗
- Wireshark抓取結果

- 程式執行解果

## LAB2: 改為一(程式)送二(程式)收
- 程式碼
- 說明
- 為了達到1送10我做了以下改變
- Server在listen前,我先請使用者input port
- Client data創建了10筆
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
int port;
printf("Input the port number u want to recv: ");
scanf ("%d",&port);
serv.sin_port = htons(port);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on %d",port);
for (int i=0;i<10;i++){
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
}
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",int(input("Enter port: "))
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
while True:
message ,ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {message.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
int port;
printf("Input the port number u want to recv: ");
scanf ("%d",&port);
serv.sin_port = htons(port);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on %d",port);
for (int i=0;i<10;i++){
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
}
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",int(input("Enter port: "))
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
while True:
message ,ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {message.decode()}")
print("===============================")
```
:::
- 實驗結果
- 對於socket的數量
- TCP是connect oriented,所以需要10個socket
- UDP是connectless oriented,所以只要一個socket即可
- 改為1 to 10
- Server在listen前,我先請使用者input port
- 執行結果

## LAB3: 改為二(程式)送一(程式)收,並顯示來源端資訊
- 程式碼
- 說明
- 為了達到10送1我做了以下改變
- Client再傳送前要輸入port
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
int port;
printf("Input the port number u want to recv: ");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on %d",port);
for (int i=0;i<10;i++){
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
}
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",1234
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
print("UDP Server up and listening...")
while True:
data, ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {data.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include <stdio.h>
#include <winsock.h>
char DATA[100] = "\\C is very hard!!!!!!/";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Client socket => ready to connect to server
note nate we use UDP, so the socket of client is sock datagram
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Start to send data to server
*/
int n = sendto(
sd,
DATA, strlen(DATA),0,
(LPSOCKADDR) &serv, sizeof(serv)
);
printf("Send: %s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
DATA = [
"Hello, World!",
"How are you today?",
"I'm learning programming.",
"Python is my favorite language.",
"Today is a beautiful day.",
"Coding is fun and challenging.",
"I enjoy solving problems.",
"Reading books is a good habit.",
"Practice makes perfect.",
"Never stop learning."
]
HOST,PORT = "127.0.0.1",1234
channel = int(input("Enter channel(1-10): "))
clientSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
clientSocket.sendto(DATA[channel].encode(),(HOST,PORT))
print(f"Message send: {DATA[channel]}")
```
:::
- 實驗結果
- 以Socket數量來說
- TCP接收端通常需要10個
- UDP只需要1個就可以了
- 改為10 to 1
- 只要開10個終端機然後傳送到server就好
- 執行結果

## LAB4: UDP實作變化:當傳送對象是固定對象時
- 程式碼
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on 12345");
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",1234
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
print("UDP Server up and listening...")
while True:
data, ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {data.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include <stdio.h>
#include <winsock.h>
char DATA[100] = "\\C is very hard!!!!!!/";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Client socket => ready to connect to server
note nate we use UDP, so the socket of client is sock datagram
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Start to send data to server
*/
connect(sd,(LPSOCKADDR) &serv,sizeof(serv));
int n = send(
sd,
DATA, strlen(DATA),0
);
printf("Send: %s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
import time
HOST,PORT = "127.0.0.1",1234
DATA = "I don't know what to send"
sd = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sd.connect((HOST,PORT))
while True:
rate = int(input("Enter rate: "))
sendTime = 1/rate
for i in range(10):
sd.send(DATA.encode())
print(f"Message send: {DATA}")
time.sleep(sendTime)
```
:::
- 實驗結果
- connect的影響
- Wireshark分析

- 其實結果和LAB1一樣,只有一個封包,不會和TCP程式一樣要建立連線
- 執行結果

## LAB5: UDP實作變化:當傳送端想用固定port時
- 程式碼
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Client information tmp
*/
struct sockaddr_in client;
int len_client = sizeof(client);
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on 12345");
int n = recvfrom(
sd,
DATA,100,0,
(LPSOCKADDR) &client, &len_client
);
printf("recv:%s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",1234
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
print("UDP Server up and listening...")
while True:
data, ip = serverSocket.recvfrom(1024)
print(f"Client IP: {ip}")
print(f"Message: {data.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include <stdio.h>
#include <winsock.h>
char DATA[100] = "\\C is very hard!!!!!!/";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Client socket => ready to connect to server
note nate we use UDP, so the socket of client is sock datagram
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
client information
IP: 127.0.0.1
Port: 1234
sinfamily: IPV4
*/
struct sockaddr_in clint;
clint.sin_addr.s_addr = inet_addr("127.0.0.1");
clint.sin_port = htons(1234);
clint.sin_family = AF_INET;
/*
Start to send data to server
*/
bind(sd,(struct sockaddr*) &clint, sizeof(clint));
connect(sd,(LPSOCKADDR) &serv,sizeof(serv));
int n = send(
sd,
DATA, strlen(DATA),0
);
printf("Send: %s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
DATA = "I Love Python!!!!"
HOST,PORT = "127.0.0.1",1234
IP,CLIPORT = "127.0.0.1",3456
clientSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
clientSocket.bind((IP,CLIPORT))
clientSocket.connect((HOST,PORT))
clientSocket.send(DATA.encode())
print(f"Message send: {DATA}")
```
:::
- 實驗結果
- Client Bind之後,程式可執行成功,且server接收時確實能產生對應的port
- 使用python bind的結果

- 可以發現我的port就是我設定的
- 執行結果

## LAB6: UDP實作變化:當傳接送端不關心傳送來源時
- 程式碼
- Server
:::spoiler C
```C=
#include<stdio.h>
#include<winsock.h>
char DATA[100] = "";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
Server sock binding
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
bind(sd,(LPSOCKADDR)&serv,sizeof(serv));
printf("Ready to recv on 12345");
while (1){
int n = recv(
sd,
DATA,100,0
);
printf("recv:%s (%d)\n",DATA,n);
}
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
HOST,PORT = "127.0.0.1",1234
serverSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverSocket.bind((HOST,PORT))
print("UDP Server up and listening...")
while True:
data= serverSocket.recv(1024)
print(f"Message: {data.decode()}")
print("===============================")
```
:::
- Client
:::spoiler C
```C=
#include <stdio.h>
#include <winsock.h>
char DATA[100] = "\\C is very hard!!!!!!/";
int main(){
/*
Register winsock
*/
WSADATA wsadata;
WSAStartup(0x101,(LPWSADATA) &wsadata);
/*
Client socket => ready to connect to server
note nate we use UDP, so the socket of client is sock datagram
*/
SOCKET sd = socket(AF_INET,SOCK_DGRAM,0);
/*
Server information
IP: 127.0.0.1
Port: 12345
sinfamily: IPV4
*/
struct sockaddr_in serv;
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
serv.sin_port = htons(12345);
serv.sin_family = AF_INET;
/*
client information
IP: 127.0.0.1
Port: 1234
sinfamily: IPV4
*/
struct sockaddr_in clint;
clint.sin_addr.s_addr = inet_addr("127.0.0.1");
clint.sin_port = htons(1234);
clint.sin_family = AF_INET;
/*
Start to send data to server
*/
bind(sd,(struct sockaddr*) &clint, sizeof(clint));
connect(sd,(LPSOCKADDR) &serv,sizeof(serv));
int n = send(
sd,
DATA, strlen(DATA),0
);
printf("Send: %s (%d)\n",DATA,n);
closesocket(sd);
WSACleanup();
system("pause");
return 0;
}
```
:::
:::spoiler Python
```python=
import socket
DATA = "I Love Python!!!!"
HOST,PORT = "127.0.0.1",1234
IP,CLIPORT = "127.0.0.1",3456
clientSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
clientSocket.bind((IP,CLIPORT))
clientSocket.connect((HOST,PORT))
clientSocket.send(DATA.encode())
print(f"Message send: {DATA}")
```
:::
- 實驗結果
- 使用recv後我完全不用在宣告一個IP的structure,更有彈性,~~感覺也更隨便~~
- 執行結果

## 心得
這周學了UDP程式設計,感覺他比TCP更加自由,畢竟不用連線,所以socket可以亂亂用,但也有一些大缺點,例如像封包可能遺失等,感覺可以用確認碼等技巧補足。
作業的部分,我1~6嘗試用C與python寫,尤其是寫完C之後寫Python有一種快速通關的感覺,我最愛Python了0.0。
BTW, 上周的netcat好好玩,我之前在linux用也頂多只有連線到對方主機而已,沒想到window也有,而且功能比我想像的豐富,還可以聆聽封包,難怪稱為網路瑞士刀,因為功能多多。
## 附錄
[全部程式碼在這](https://github.com/kevin0920911/NetworkGIF/tree/main/w8)