# [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
---