# 網路程式設計 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抓取結果 ![image](https://hackmd.io/_uploads/BJAsN_Vb0.png) - 無CS架構下,UDP程式扔會傳送一個封包 - Wireshark抓取結果 ![image](https://hackmd.io/_uploads/rJD1rO4W0.png) - Wait... 理論上不會產生ICMP吧 - ICMP是網際網路控制訊息協定,幾乎每個人的網路封包都有,用以表示網路狀態,這邊產生原因是找不到目的地,代表我沒有Server - 在TCP程式無Server下,會因無法建立連線而傳送失敗 - Wireshark抓取結果 ![image](https://hackmd.io/_uploads/r10mUdVb0.png) - 程式執行解果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w8/GIF/Lab1.gif?raw=true) ## 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 - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w8/GIF/2.gif?raw=true) ## 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就好 - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w8/GIF/Lab3.gif?raw=true) ## 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分析 ![image](https://hackmd.io/_uploads/HkU1lYV-A.png) - 其實結果和LAB1一樣,只有一個封包,不會和TCP程式一樣要建立連線 - 執行結果 ![image](https://hackmd.io/_uploads/SJ689t4b0.png) ## 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的結果 ![image](https://hackmd.io/_uploads/rJkZQYNb0.png) - 可以發現我的port就是我設定的 - 執行結果 ![image](https://hackmd.io/_uploads/rJZ29YNZA.png) ## 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,更有彈性,~~感覺也更隨便~~ - 執行結果 ![image](https://hackmd.io/_uploads/rJDliFEZ0.png) ## 心得 這周學了UDP程式設計,感覺他比TCP更加自由,畢竟不用連線,所以socket可以亂亂用,但也有一些大缺點,例如像封包可能遺失等,感覺可以用確認碼等技巧補足。 作業的部分,我1~6嘗試用C與python寫,尤其是寫完C之後寫Python有一種快速通關的感覺,我最愛Python了0.0。 BTW, 上周的netcat好好玩,我之前在linux用也頂多只有連線到對方主機而已,沒想到window也有,而且功能比我想像的豐富,還可以聆聽封包,難怪稱為網路瑞士刀,因為功能多多。 ## 附錄 [全部程式碼在這](https://github.com/kevin0920911/NetworkGIF/tree/main/w8)