1 在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
2 参考《head first C》实现knock knock服务器,提交代码knock.c,编译运行过程(13分)
3 使用多线程实现knock knock服务器,提交代码knockmt.c,编译运行过程,至少两个客户端测试,服务器运行结果中要打印线程id(13分)
4 提交git log结果(3分)
c
// knock.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
char buffer[256];
int should_continue = 1;
while (should_continue) {
printf("Knock knock\n");
fflush(stdout); // 确保输出被立即发送
if (fgets(buffer, 256, stdin) == NULL) {
perror("Error reading from stdin");
exit(EXIT_FAILURE);
}
if (strcmp(buffer, "Who's there?\n") == 0) {
printf("Computer\n");
fflush(stdout);
if (fgets(buffer, 256, stdin) == NULL) {
perror("Error reading from stdin");
exit(EXIT_FAILURE);
}
if (strcmp(buffer, "Computer who?\n") == 0) {
printf("Computer says boot and listen.\n");
fflush(stdout);
if (fgets(buffer, 256, stdin) == NULL) {
perror("Error reading from stdin");
exit(EXIT_FAILURE);
}
if (strcmp(buffer, "I don't get it.\n") == 0) {
printf("I know you don't get it. That's why I'm explaining it.\n");
fflush(stdout);
should_continue = 0;
}
}
} else {
printf("Who's there?\n");
fflush(stdout);
}
}
return 0;
}
编译运行过程:
bash
gcc -o knock knock.c
./knock
3. 使用多线程实现 Knock Knock 服务器
以下是使用多线程实现的 Knock Knock 服务器的代码示例:
c
// knockmt.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#define BUFFER_SIZE 256
void *handle_client(void *socket_desc) {
char buffer[BUFFER_SIZE];
long socket = (long)socket_desc;
pthread_t thread_id = pthread_self();
printf("Thread %ld handling client %ld\n", thread_id, socket);
if (read(socket, buffer, BUFFER_SIZE) > 0) {
if (strcmp(buffer, "Knock knock\n") == 0) {
write(socket, "Who's there?\n", 14);
} else if (strcmp(buffer, "Who's there?\n") == 0) {
write(socket, "Computer\n", 8);
} else if (strcmp(buffer, "Computer who?\n") == 0) {
write(socket, "Computer says boot and listen.\n", 28);
} else if (strcmp(buffer, "I don't get it.\n") == 0) {
write(socket, "I know you don't get it. That's why I'm explaining it.\n", 45);
} else {
write(socket, "Sorry, I don't understand.\n", 24);
}
}
close(socket);
free(socket_desc);
pthread_exit(NULL);
}
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
pthread_t tid;
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Listening on port 8080...\n");
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
int *new_sock = malloc(1);
*new_sock = new_socket;
if (pthread_create(&tid, NULL, handle_client, (void *)new_sock) != 0) {
perror("could not create thread");
}
}
return 0;
}
编译运行过程:
gcc -o knockmt knockmt.c -lpthread
./knockmt
客户端测试:
telnet localhost 8080
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.
Knock knock
Who’s there?
Who’s there?
Computer
Computer who?
Computer says boot and listen.
I don’t get it.
I know you don’t get it. That’s why I’m explaining it.
Connection closed by foreign host.