# 網路程式設計 作業七 :::info 以下測試均使用C/C++展示,Python略有不同 ::: ## LAB1: TCP傳送測試 - 若兩方都先送後收,可以運作嗎? - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "I Hate C"; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); struct sockaddr_in clnt; int len_clnt = sizeof(clnt); /* Create a socket */ SOCKET clnt_sd = socket(AF_INET, SOCK_STREAM, 0); SOCKET serverSd = socket(AF_INET, SOCK_STREAM, 0); bind(serverSd,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); listen(serverSd, 5); clnt_sd = accept(serverSd,(struct sockaddr*) &clnt,&len_clnt); send(clnt_sd,DATA,strlen(DATA),0); printf("Sent: %s\n",DATA); recv(clnt_sd,buffer,sizeof(buffer),0); printf("Received: %s\n",buffer); closesocket(serverSd); return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "I Love Python!" serversd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversd.bind(('127.0.0.1', 1234)) serversd.listen(5) conn, addr = serversd.accept() conn.send(DATA.encode()) print(f'Sent: {DATA}') buffer = conn.recv(1024).decode() print(f'Received: {buffer}') ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "I Hate C"; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET clnt = socket(AF_INET, SOCK_STREAM, 0); connect(clnt,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); send(clnt,DATA,strlen(DATA),0); printf("Sent: %s\n",DATA); recv(clnt,buffer,sizeof(buffer),0); printf("Received: %s\n",buffer); closesocket(clnt); return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "I Love Python!" sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) sd.send(DATA.encode()) print(f'Sent: {DATA}') buffer = sd.recv(1024).decode() print(f'Received: {buffer}') ``` ::: - 執行結果 ![image](https://hackmd.io/_uploads/r1OU2Rdb0.png) - 當雙方是先送後收,是可運作的 - 若兩方都先收後送,可以運作嗎? - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "I Hate C"; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); struct sockaddr_in clnt; int len_clnt = sizeof(clnt); /* Create a socket */ SOCKET clnt_sd = socket(AF_INET, SOCK_STREAM, 0); SOCKET serverSd = socket(AF_INET, SOCK_STREAM, 0); bind(serverSd,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); listen(serverSd, 5); clnt_sd = accept(serverSd,(struct sockaddr*) &clnt,&len_clnt); recv(clnt_sd,buffer,sizeof(buffer),0); printf("Received: %s\n",buffer); send(clnt_sd,DATA,strlen(DATA),0); printf("Sent: %s\n",DATA); closesocket(serverSd); return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "I Love Python!" serversd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversd.bind(('127.0.0.1', 1234)) serversd.listen(5) conn, addr = serversd.accept() buffer = conn.recv(1024).decode() print(f'Received: {buffer}') conn.send(DATA.encode()) print(f'Sent: {DATA}') ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "I Hate C"; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET clnt = socket(AF_INET, SOCK_STREAM, 0); connect(clnt,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); recv(clnt,buffer,sizeof(buffer),0); printf("Received: %s\n",buffer); send(clnt,DATA,strlen(DATA),0); printf("Sent: %s\n",DATA); closesocket(clnt); return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "I Love Python!" sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) buffer = sd.recv(1024).decode() print(f'Received: {buffer}') sd.send(DATA.encode()) print(f'Sent: {DATA}') ``` ::: - 執行結果 ![image](https://hackmd.io/_uploads/HJZ2TCub0.png) - 若兩方都先收後送,是無法運作的,雙方都會等待接收 ## LAB2: 送多次,收一次 - 完成「送一次,收多次」的實驗 - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); struct sockaddr_in clnt; int len_clnt = sizeof(clnt); /* Create a socket */ SOCKET clnt_sd = socket(AF_INET, SOCK_STREAM, 0); SOCKET serverSd = socket(AF_INET, SOCK_STREAM, 0); bind(serverSd,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); listen(serverSd, 5); clnt_sd =accept(serverSd,(struct sockaddr*) &clnt,&len_clnt); for (int i = 0; i < 6; i++){ int n = recv(clnt_sd,buffer,6,0); buffer[n] = '\0'; printf("Client: %s(%d bytes)\n",buffer,n); } closesocket(serverSd); return 0; } ``` ::: :::spoiler Python ```python= import socket sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.bind(('127.0.0.1', 1234)) sd.listen(1) conn, andr = sd.accept() for i in range(5): buffer = conn.recv(6).decode() print(f'Received: {buffer}') sd.close() ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> #include <string.h> int main(){ char buffer[1024] = "[NCYU][NCYU][NCYU][NCYU][NCYU][NCYU]"; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET clnt = socket(AF_INET, SOCK_STREAM, 0); connect(clnt, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); send(clnt, buffer, strlen(buffer),0); printf("Sent: %s\n",buffer); return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "[NCYU][NCYU][NCYU][NCYU][NCYU]" sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) sd.send(DATA.encode()) print(f'Sent: {DATA}') sd.close() ``` ::: - 執行結果 ![image](https://hackmd.io/_uploads/S1VHYXtbA.png) - 完成「送多次,收一次」的實驗 - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); struct sockaddr_in clnt; int len_clnt = sizeof(clnt); /* Create a socket */ SOCKET clnt_sd = socket(AF_INET, SOCK_STREAM, 0); SOCKET serverSd = socket(AF_INET, SOCK_STREAM, 0); bind(serverSd,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); listen(serverSd, 5); clnt_sd =accept(serverSd,(struct sockaddr*) &clnt,&len_clnt); Sleep(1000); int n = recv(clnt_sd,buffer,36,0); buffer[n] = '\0'; printf("Client: %s(%d bytes)\n",buffer,n); closesocket(serverSd); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.bind(('127.0.0.1', 1234)) sd.listen(1) conn, andr = sd.accept() sleep(1) buffer = conn.recv(30).decode() print(f'Received: {buffer}') sd.close() ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> #include <string.h> int main(){ char buffer[1024] = "[NCYU]"; /* Initialize Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET clnt = socket(AF_INET, SOCK_STREAM, 0); connect(clnt, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); for (int i = 0; i < 6; i++){ send(clnt, buffer, strlen(buffer),0); printf("Sent: %s\n",buffer); } Sleep(1000); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * DATA = "[NCYU]" sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) for i in range(5): sd.send(DATA.encode()) print(f'Sent: {DATA}') sleep(1) sd.close() ``` ::: - 執行結果 ![image](https://hackmd.io/_uploads/ByP_KQYbC.png) - 結論 由以上兩個實驗,不難可以看出TCP socket傳送是類似stream的方式傳送 ## LAB3: 完成UDP成對收送的實驗 - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "[NCYU]"; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET serverSd = socket(AF_INET, SOCK_DGRAM, 0); bind(serverSd,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); /* Start recv data */ while (TRUE){ int n = recv(serverSd,buffer,6,0); printf("Received: %s (%d byte)\n",buffer,n); } return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "[NCYU]" sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.bind(('127.0.0.1', 1234)) while True: buffer = sd.recv(6).decode() print(f'Received: {buffer}') ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024] = ""; char DATA[1024] = "[NCYU]"; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0); for (int i=0;i<5;i++){ sendto(sd,DATA,strlen(DATA),0,(LPSOCKADDR)&serv_addr,sizeof(serv_addr)); printf("Sent: %s\n",DATA); } return 0; } ``` ::: :::spoiler Python ```python= import socket DATA = "[NCYU]" sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.connect(('127.0.0.1',1234)) for i in range(5): sd.send(DATA.encode()) print(f'Sent: {DATA}') sd.close() ``` ::: - 執行結果 - 當接收端收的大小較傳送大小大時 ![image](https://hackmd.io/_uploads/SJtEsQtW0.png) - 可以看到是正常傳送的 - 當接收端收的大小較傳送大小小時 ![image](https://hackmd.io/_uploads/SyZVcmKZR.png) - 可以看到recv()回傳的數值其實是-1,是失敗的 - BTW, 使用python時會直接跳出錯誤 - 結論 從上面可以看出UDP跟TCP差別,UDP recv 參數不能小於送出的大小 ## LAB4: 完成單次傳送文字檔的實驗 - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ char buffer[1024]=""; /* winsock startup */ WSADATA wsaData; WSAStartup(0x101,(LPWSADATA) &wsaData); /* Server information IP:127.0.0.1 PORT:1234 */ SOCKADDR_IN server,client; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(1234); /* Create socket */ SOCKET serversd = socket(AF_INET, SOCK_STREAM, 0); bind(serversd, (LPSOCKADDR) &server, sizeof(server)); listen(serversd, 5); SOCKET clientsd = accept(serversd, (LPSOCKADDR)&client, NULL); /* File */ FILE *file = fopen("bod.txt", "w"); recv(clientsd,buffer, 1024, 0); printf("Receive: %s", buffer); fprintf(file, "%s", buffer); fclose(file); closesocket(clientsd); } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('bod.txt','w') sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.bind(('127.0.0.1',1234)) sd.listen(1) conn, addr = sd.accept() data = conn.recv(1024).decode() print(f'Received: {data}') f.write(data) ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ /* winsock startup */ WSADATA wsaData; WSAStartup(0x101,(LPWSADATA) &wsaData); /* Server information IP: 127.0.0.1 PORT: 1234 */ SOCKADDR_IN server; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(1234); /* Create socket */ SOCKET sd = socket(AF_INET, SOCK_STREAM, 0); connect(sd, (LPSOCKADDR) &server, sizeof(server)); /* File */ FILE *file = fopen("alice.txt", "r"); char buffer[1024]; while(fgets(buffer, 1024, file)){ send(sd, buffer, strlen(buffer), 0); printf("Send: %s", buffer); } fclose(file); closesocket(sd); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) file = open('alice.txt', 'r') for line in file.readlines(): sd.send(line.encode()) print(f'Sent: {line}') sleep(1) ``` ::: - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w9/GIF/lab4.gif?raw=true) ## LAB5: 連續傳送大量文字檔的實驗 - 程式碼 - Server :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <string> #include <winsock.h> using namespace std; int main(){ char buffer[1024] = ""; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr, clnt_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET server_sd = socket(AF_INET, SOCK_STREAM, 0); bind(server_sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); listen(server_sd, 5); /* Start recv data */ ofstream fout("bod.txt", ios::out); SOCKET clnt_sd = accept(server_sd, (struct sockaddr*)&clnt_addr, NULL); int n; int byte=0; while ((n = recv(clnt_sd, buffer, 1024, 0)) && string(buffer) != "END" && n != SOCKET_ERROR){ byte += n; buffer[n] = '\0'; printf("Received: %s (%d byte)\n", buffer, n); fout << buffer << endl ; } cout<<"Total byte: "<<byte<<endl; fout.close(); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('bod.txt','w') sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.bind(('127.0.0.1', 1234)) sd.listen(1) conn, andr = sd.accept() buffer = "" while True: data = conn.recv(1024).decode() if data == 'END': break buffer += data print(f'Received: {data}') f.write(buffer) f.close() sd.close() ``` ::: - Client :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <winsock.h> #include <string> using namespace std; int main(){ /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET sd = socket(AF_INET, SOCK_STREAM, 0); connect(sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); /* Send data */ ifstream fin("alice.txt"); string s; while ( getline(fin,s) ){ send(sd,s.c_str(),s.size(),0); cout << "Sent: " << s << endl; Sleep(1000); } send(sd,"END",s.size(),0); fin.close(); closesocket(sd); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('alice.txt','r') sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) for i in f.readlines(): sd.send(i.encode()) print(f'Sent: {i}') sleep(1) sd.send('END'.encode()) sd.close() f.close() ``` ::: - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w9/GIF/lab5.gif?raw=true) - 為了避免TCP boundary問題,我在每次傳送都會sleep一秒 ## LAB6: 連續傳送大量二位元檔的實驗 - 程式碼 - Server :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ /* File DEST: bod.txt */ FILE *fout = fopen("bod.jpg", "w+b"); /* winsock startup */ WSADATA wsaData; WSAStartup(0x101,(LPWSADATA) &wsaData); /* Server information IP: 127.0.0.1 PORT: 1234 */ SOCKADDR_IN server; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(1234); /* Create socket */ SOCKET serversd = socket(AF_INET, SOCK_STREAM, 0); bind(serversd, (LPSOCKADDR) &server, sizeof(server)); listen(serversd, 5); SOCKET clientsd = accept(serversd, NULL, NULL); char buffer[1024]; int n; while ((n = recv(clientsd, buffer, 1024, 0)) && n>0){ buffer[n] = '\0'; if (strcmp(buffer, "END") == 0){ break; } fwrite(buffer, 1, 1024, fout); printf("Receive: %s", buffer); } fclose(fout); closesocket(clientsd); } ``` ::: :::spoiler Python ```python= import socket f = open('bod.jpg', 'wb') sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.bind(('127.0.0.1', 1234)) sd.listen(1) conn, addr = sd.accept() while True: data = conn.recv(1024) print(f'Received: {data}') if not data: break # 如果接收到空資料,表示資料傳輸完成,退出迴圈 if data == b'END': break # 如果接收到結束標記,表示圖片傳輸完成,退出迴圈 f.write(data) f.close() sd.close() ``` ::: - Client :::spoiler C ```C= #include <stdio.h> #include <winsock.h> int main(){ /* winsock startup */ WSADATA wsaData; WSAStartup(0x101,(LPWSADATA) &wsaData); /* Server information IP: 127.0.0.1 PORT: 1234 */ SOCKADDR_IN server; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_port = htons(1234); /* Create socket */ SOCKET sd = socket(AF_INET, SOCK_STREAM, 0); connect(sd, (LPSOCKADDR) &server, sizeof(server)); /* File DEST: alice.jpg */ FILE *file = fopen("alice.jpg", "rb"); char buffer[1024]; while(fread(buffer, 1, 1024, file)){ send(sd, buffer, 1024, 0); printf("Send: %s", buffer); } send(sd, "END", 1024, 0); fclose(file); closesocket(sd); } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('alice.jpg','rb') sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(('127.0.0.1', 1234)) for i in f.readlines(): sd.send(i) print(f'Sent: {i}') sleep(0.1) sd.send('END'.encode()) sd.close() ``` ::: - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w9/GIF/lab6.gif?raw=true) - 我使用圖片檔傳輸,左邊是欲傳送對象,右邊是複製完成成果 ## LAB7: UDP傳檔的實驗 - 程式碼 - Server :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <string> #include <winsock.h> using namespace std; int main(){ char buffer[1024] = ""; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr, clnt_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET server_sd = socket(AF_INET, SOCK_DGRAM, 0); bind(server_sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); /* Start recv data */ ofstream fout("bod.txt", ios::out); int n; int byte=0; while ((n = recv(server_sd, buffer, 1024, 0)) && string(buffer) != "END" && n != SOCKET_ERROR){ byte += n; buffer[n] = '\0'; printf("Received: %s (%d byte)\n", buffer, n); fout << buffer << endl ; } cout<<"Total byte: "<<byte<<endl; fout.close(); return 0; } ``` ::: :::spoiler Python ```python= import socket f = open('bod.jpg', 'wb') sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.bind(('127.0.0.1', 1234)) while True: data = sd.recv(1024) print(f'Received: {data}') if not data: break if data == b'END': break f.write(data) f.close() sd.close() ``` ::: - Client :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <winsock.h> #include <string> using namespace std; int main(){ /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0); connect(sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); /* Send data */ ifstream fin("alice.txt"); string s; while ( getline(fin,s) ){ send(sd,s.c_str(),s.size(),0); cout << "Sent: " << s << endl; Sleep(1000); } send(sd,"END",s.size(),0); fin.close(); closesocket(sd); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('alice.jpg','rb') sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.connect(('127.0.0.1', 1234)) while True: data = f.read(1024) if not data: break sd.send(data) print(f'Sent: {data}') sd.send('END'.encode()) sd.close() ``` ::: - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w9/GIF/lab7.gif?raw=true) ## LAB8: UDP傳檔改良的實驗 :::info ###### 改良方式 1. 用暗號:END告知結束 2. 最後送出的大小以確認正確與否 3. 傳送時要確定來源 ::: - 程式碼 - Server :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <string> #include <winsock.h> using namespace std; int main(){ char buffer[1024] = ""; /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr, clnt_addr; int clinet_addr_len = sizeof(clnt_addr); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); /* Create a socket */ SOCKET server_sd = socket(AF_INET, SOCK_DGRAM, 0); bind(server_sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); /* Start recv data */ ofstream fout("bod.txt", ios::out); int n; int byte=0; while ((n = recvfrom(server_sd, buffer, 1024, 0,(LPSOCKADDR)&clnt_addr,&clinet_addr_len)) && string(buffer) != "END" && n != SOCKET_ERROR){ if (clnt_addr.sin_addr.s_addr != inet_addr("127.0.0.1") && clnt_addr.sin_port != htons(3456) ){ continue; } byte += n; buffer[n] = '\0'; printf("Received: %s (%d byte)\n", buffer, n); fout << buffer << endl ; } cout<<"Total byte: "<<byte<<endl; n= recv(server_sd, buffer, 1024, 0); buffer[n] = '\0'; if (atoi(buffer) == byte) cout<<"File is sent successfully"<<endl; else cout<<"File is not sent successfully"<<endl; fout.close(); return 0; } ``` ::: :::spoiler Python ```python= import socket f = open('bod.jpg', 'wb') sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.bind(('127.0.0.1', 1234)) byte = 0 while True: data,addr = sd.recvfrom(1024) if addr != ('127.0.0.1', 3456): continue print(f'Received: {data}') if not data: break # 如果接收到空資料,表示資料傳輸完成,退出迴圈 if data == b'END': break # 如果接收到結束標記,表示圖片傳輸完成,退出迴圈 f.write(data) byte += len(data) f.close() if int(sd.recv(1024).decode()) == byte: print('File received successfully') sd.close() ``` ::: - Client :::spoiler C++ ```C++= #include <iostream> #include <fstream> #include <winsock.h> #include <string> using namespace std; int main(){ /* Initial Winsock */ WSADATA wsadata; WSAStartup(0x101, (LPWSADATA) &wsadata); /* Server information IP: 127.0.0.1 PORT: 1234 */ struct sockaddr_in serv_addr,clint_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr.sin_port = htons(1234); clint_addr.sin_family = AF_INET; clint_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); clint_addr.sin_port = htons(3456); /* Create a socket */ SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0); bind(sd, (LPSOCKADDR)&clint_addr, sizeof(clint_addr)); connect(sd, (LPSOCKADDR)&serv_addr, sizeof(serv_addr)); /* Send data */ ifstream fin("alice.txt"); string s; int byte = 0; while ( getline(fin,s) ){ send(sd,s.c_str(),s.size(),0); byte += s.size(); cout << "Sent: " << s << endl; Sleep(1000); } send(sd,"END",s.size(),0); send(sd,to_string(byte).c_str(),to_string(byte).size(),0); fin.close(); closesocket(sd); return 0; } ``` ::: :::spoiler Python ```python= import socket from time import * f = open('alice.jpg','rb') sd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sd.bind(('127.0.0.1',3456)) sd.connect(('127.0.0.1', 1234)) byte = 0 while True: data = f.read(1024) if not data: break byte += sd.send(data) print(f'Sent: {data}') sd.send('END'.encode()) sd.send(str(byte).encode()) sd.close() ``` ::: - 執行結果 ![image](https://github.com/kevin0920911/NetworkGIF/blob/main/w9/GIF/lab8.gif?raw=true) ## 附錄 [本周全部程式碼皆在這裡](https://github.com/kevin0920911/NetworkGIF/tree/main/w9) ## 心得 這周學了檔案上傳,以及更加深入的TCP STREAM與UDP DATAGRAM,之前在寫聊天室其實就有過這個問題,有去尋找相關的問題,後來才知道TCP傳送類似一個流,因此有時會會怪怪的。 然後檔案上傳的部分,期中考就有類似的,我用Python寫的。老實說真的實作出來感覺好好玩,但在寫的時候真的是崩潰連連,八成都是C的字串處理,後來直接改用C++,BTW, 其實Python檔案處理的函數跟C好像,我寫的時候很快就適應了好開心。 最後作業的部分,這周作業感覺寫超級久(重點我還生病討厭),可能是C跟Python一起寫吧,我還是好愛python,我愛python,python我寶貝謝謝。