# [2020q3](http://wiki.csie.ncku.edu.tw/sysprog/schedule) 第 16 週測驗題 ###### tags: `sysprog2020` :::info 目的: 引導學員複習 TCP/IP 程式設計 ::: ==[作答表單]()== --- ### 測驗 `1` 考慮到 `client.c` 和 `server.c` 可透過 socket 傳遞檔案,其中 `client.c` 程式列表如下: ```cpp /* Client code */ #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #define PORT_NUMBER 55555 #define SERVER_ADDRESS "localhost" #define NEW_FILENAME "new-file.txt" #define CHUNK_SIZE 1024 int main(int argc, char **argv) { int client_socket; struct sockaddr_in remote_addr; char buffer[CHUNK_SIZE] = {0}; long int file_size; int total_recv = 0; /* Zeroing remote_addr struct */ memset(&remote_addr, 0, sizeof(remote_addr)); /* Construct remote_addr struct */ remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(PORT_NUMBER); inet_pton(AF_INET, SERVER_ADDRESS, &(remote_addr.sin_addr)); /* Create client socket */ client_socket = socket(AF_INET, SOCK_STREAM, 0); if (client_socket < 0) { perror("Error creating socket"); exit(EXIT_FAILURE); } /* Connect to the server */ if (connect(client_socket, (struct sockaddr *) &remote_addr, sizeof(struct sockaddr)) < 0) { perror("Error connecting to server"); exit(EXIT_FAILURE); } printf("Client connected to server at port %d\n", PORT_NUMBER); /* Receiving file size */ printf("Receiving message from server.\n"); int recv_size = recv(client_socket, buffer, sizeof(long) + 1, 0); file_size = atol(buffer); printf("\nFile size : %ld\n", file_size); /* Open a new file */ FILE *fp = fopen(NEW_FILENAME, "w+"); if (fp == NULL) { perror("Failed to open file"); exit(EXIT_FAILURE); } while (total_recv < file_size) { recv_size = recv(client_socket, buffer, CHUNK_SIZE, 0); total_recv += recv_size; printf("Received %d Bytes. Total is %d\n", recv_size, total_recv); fwrite(buffer, recv_size, 1, fp); } fseek(fp, 0, SEEK_END); file_size = ftell(fp); printf("New file size: %ld\n", file_size); fclose(fp); close(client_socket); return 0; } ``` 對應的 `server.c` 如下: ```cpp /* Server code */ #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> #define PORT_NUMBER 55555 #define SERVER_ADDRESS "localhost" #define FILE_TO_SEND "file.txt" #define CHUNK_SIZE 1024 int main(int argc, char **argv) { int server_socket, peer_socket; socklen_t sock_len; struct sockaddr_in server_addr, peer_addr; int total_read = 0; char buf[4096]; memset(&server_addr, 0, sizeof(server_addr)); server_socket = F1(AF_INET, SOCK_STREAM, 0); peer_socket = F2(AF_INET, SOCK_STREAM, 0); if (server_socket < 0 || peer_socket < 0) { exit(EXIT_FAILURE); } server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT_NUMBER); inet_pton(AF_INET, SERVER_ADDRESS, &(server_addr.sin_addr)); if ((F3(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr))) < 0) { exit(EXIT_FAILURE); } F4(server_socket, 1); printf("Waiting for incoming connections...\n"); sock_len = sizeof(struct sockaddr_in); /* Accepting incoming peers */ peer_socket = F5(server_socket, (struct sockaddr *) &peer_addr, (socklen_t *) &sock_len); if (peer_socket < 0) { exit(EXIT_FAILURE); } /* Open file in read-only */ FILE *fp = fopen("file.txt", "r"); if (fp == NULL) { exit(EXIT_FAILURE); } fseek(fp, 0, SEEK_END); long int file_size = ftell(fp); sprintf(buf, "%ld\n", file_size); F6(peer_socket, buf, sizeof(long) + 1, 0); fseek(fp, 0, SEEK_SET); while (!feof(fp)) { int actually_read = fread(buf, 1, CHUNK_SIZE, fp); total_read += actually_read; F7(peer_socket, buf, actually_read, 0); int num_left = (int) file_size - total_read; if (num_left == 0) break; } fclose(fp); close(peer_socket); close(server_socket); return 0; } ``` 其中 F1 到 F7 都是 Linux 系統呼叫,請補完以符合預期。 ==作答區== F1 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F2 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F3 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F4 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F5 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F6 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send F7 = ? * `(a)` open * `(b)` read * `(c)` write * `(d)` socket * `(e)` listen * `(f)` accept * `(g)` bind * `(h)` recv * `(i)` send ---