sysprog2020
目的: 引導學員複習 TCP/IP 程式設計
1
考慮到 client.c
和 server.c
可透過 socket 傳遞檔案,其中 client.c
程式列表如下:
/* 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
如下:
/* 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)
sendF2 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
sendF3 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
sendF4 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
sendF5 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
sendF6 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
sendF7 = ?
(a)
open(b)
read(c)
write(d)
socket(e)
listen(f)
accept(g)
bind(h)
recv(i)
send1970 年代推出的首款廣體民航客機波音 747 軟體由大約 40 萬行程式碼構成,而 2011 年引進的波音 787 的軟體規模則是波音 747 的 16 倍,約 650 萬行程式碼。換言之,你我的性命緊繫於一系列極為複雜的軟體系統之中,能不花點時間了解嗎? 軟體開發的安全性設計和測試驗證應獲得更高的重視。
Jul 6, 2025改寫自 CMU Introduction to Computer Systems 課程第一份作業,擴充 GNU/Linux 開發工具的使用並強化自動分析機制。
Jul 6, 2025自 Linux 核心原始程式碼編譯出 User-mode Linux 並運用工具來建構實驗所需的檔案系統
Jul 6, 2025本文回顧微處理器的 atomic 指令及軟硬體設計考量、memory ordering 及 memory barrier、C11 標準的 <stdatomic.h> 及 Linux 核心介面,和探討經典 lock-free 資料結構和演算法案例。
Jul 4, 2025or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up