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)
send改寫自 Linux /dev/mem的新玩法 一文,採用 CC BY-SA 授權
Jun 17, 2025Copyright (慣C) 2019 宅色夫
Jun 16, 2025現代處理器設計:原理和關鍵特徵 ==直播錄影(上)== ==直播錄影(下)== 導讀短片 How A CPU Works | A Basic Guide On Processor Stages & Functionality 多核處理器有前途嗎? [ ] 〈The Evolution Of CPU Processing Power〉系列 ==^必看^==
Jun 15, 2025系統的 throughput 是評斷排程器優劣的重要效能
Jun 14, 2025or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up