---
# System prepended metadata

title: net w9
tags: [network]

---

# 網路程式設計 作業七
:::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我寶貝謝謝。