# 網路程式設計 作業七
:::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}')
```
:::
- 執行結果

- 當雙方是先送後收,是可運作的
- 若兩方都先收後送,可以運作嗎?
- 程式碼
- 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}')
```
:::
- 執行結果

- 若兩方都先收後送,是無法運作的,雙方都會等待接收
## 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()
```
:::
- 執行結果

- 完成「送多次,收一次」的實驗
- 程式碼
- 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()
```
:::
- 執行結果

- 結論
由以上兩個實驗,不難可以看出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()
```
:::
- 執行結果
- 當接收端收的大小較傳送大小大時

- 可以看到是正常傳送的
- 當接收端收的大小較傳送大小小時

- 可以看到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)
```
:::
- 執行結果

## 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()
```
:::
- 執行結果

- 為了避免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()
```
:::
- 執行結果

- 我使用圖片檔傳輸,左邊是欲傳送對象,右邊是複製完成成果
## 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()
```
:::
- 執行結果

## 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()
```
:::
- 執行結果

## 附錄
[本周全部程式碼皆在這裡](https://github.com/kevin0920911/NetworkGIF/tree/main/w9)
## 心得
這周學了檔案上傳,以及更加深入的TCP STREAM與UDP DATAGRAM,之前在寫聊天室其實就有過這個問題,有去尋找相關的問題,後來才知道TCP傳送類似一個流,因此有時會會怪怪的。
然後檔案上傳的部分,期中考就有類似的,我用Python寫的。老實說真的實作出來感覺好好玩,但在寫的時候真的是崩潰連連,八成都是C的字串處理,後來直接改用C++,BTW, 其實Python檔案處理的函數跟C好像,我寫的時候很快就適應了好開心。
最後作業的部分,這周作業感覺寫超級久(重點我還生病討厭),可能是C跟Python一起寫吧,我還是好愛python,我愛python,python我寶貝謝謝。