20221320—冯泰瑞—课上测试:网络编程
完成下面任务(29分)
1.在 Ubuntu 或 openEuler 中完成任务(推荐openEuler)
2.参考《head first C》实现knock knock服务器,提交代码knock.c,编译运行过程(13分)
服务器
fengtairui@fengtairui-virtual-machine:~$ touch knock.c
fengtairui@fengtairui-virtual-machine:~$ vim knock.c
fengtairui@fengtairui-virtual-machine:~$ gcc -o knock knock.c
fengtairui@fengtairui-virtual-machine:~$ ./knock
Knock Knock server is running on port 8080...
客户端
fengtairui@fengtairui-virtual-machine:~$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Knock! Knock!
Who's there?
Lettuce.
Lettuce who?
Lettuce in, it's cold out here!
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>#define PORT 8080
#define BUFFER_SIZE 1024void handle_client(int client_socket) {char buffer[BUFFER_SIZE];int read_size;// 发送初始消息send(client_socket, "Knock! Knock!\n", strlen("Knock! Knock!\n"), 0);// 等待客户端的响应read_size = recv(client_socket, buffer, BUFFER_SIZE, 0);buffer[read_size] = '\0'; // 确保字符串以 null 结尾if (strcmp(buffer, "Who's there?\n") == 0) {send(client_socket, "Lettuce.\n", strlen("Lettuce.\n"), 0);read_size = recv(client_socket, buffer, BUFFER_SIZE, 0);buffer[read_size] = '\0';if (strcmp(buffer, "Lettuce who?\n") == 0) {send(client_socket, "Lettuce in, it's cold out here!\n", strlen("Lettuce in, it's cold out here!\n"), 0);} else {send(client_socket, "I didn't get that.\n", strlen("I didn't get that.\n"), 0);}} else {send(client_socket, "I didn't get that.\n", strlen("I didn't get that.\n"), 0);}close(client_socket);
}int main() {int server_socket, client_socket;struct sockaddr_in server_addr, client_addr;socklen_t addr_size;// 创建 socketserver_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket < 0) {perror("Socket creation failed");exit(EXIT_FAILURE);}// 配置服务器地址server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = INADDR_ANY;server_addr.sin_port = htons(PORT);// 绑定 socketif (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {perror("Bind failed");close(server_socket);exit(EXIT_FAILURE);}// 监听连接if (listen(server_socket, 5) < 0) {perror("Listen failed");close(server_socket);exit(EXIT_FAILURE);}printf("Knock Knock server is running on port %d...\n", PORT);// 接受客户端连接while (1) {addr_size = sizeof(client_addr);client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &addr_size);if (client_socket < 0) {perror("Accept failed");continue;}// 处理客户端handle_client(client_socket);}// 关闭服务器 socketclose(server_socket);return 0;
}
3.使用多线程实现knock knock服务器,提交代码knockmt.c,编译运行过程,至少两个客户端测试,服务器运行结果中要打印线程id(13分)
服务器
fengtairui@fengairui-virtual-machine:~$ touch knockmt.c
fengtairui@fengtairui-virtual-machine:~$ vim knockmt.c
fengtairui@fengtairui-virtual-machine:~$ gcc knockmt.c -o knockmt -lpthread
fengtairui@fengtairui-virtual-machine:~$ ./knockmt
Knock knock server is listening on port 8088...
Accepted connection from 127.0.0.1:55206
Thread ID: 123637524858432 is handling client connection
Accepted connection from 127.0.0.1:57026
Thread ID: 123637514372672 is handling client connection
客户端1
fengtairui@fengtairui-virtual-machine:~$ telnet localhost 8088
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Knock knock
Who's there?
Omar
Omar who?
Omar my goodness, you scared me!
Haha, that's a good one! Come on in.
客户端2
fengtairui@fengtairui-virtual-machine:~$ telnet localhost 8088
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Knock
You didn't say 'Knock knock'. Goodbye.
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>#define PORT 8088
#define MAX_BUFFER_SIZE 1024// 结构体用于传递参数给线程函数
typedef struct {int clientSocket;struct sockaddr_in clientAddr;
} ThreadArgs;// 处理客户端连接的线程函数
void *handleClientThread(void *arg) {ThreadArgs *args = (ThreadArgs *)arg;int clientSocket = args->clientSocket;struct sockaddr_in clientAddr = args->clientAddr;char buffer[MAX_BUFFER_SIZE];int n;// 获取线程IDpthread_t tid = pthread_self();printf("Thread ID: %lu is handling client connection\n", tid);// 接收客户端消息n = read(clientSocket, buffer, MAX_BUFFER_SIZE);if (n < 0) {perror("Error reading from socket");close(clientSocket);free(arg);pthread_exit(NULL);}buffer[n] = '\0';// 检查消息是否为"Knock knock"if (strcmp(buffer, "Knock knock") == 0) {const char *response1 = "Who's there?";write(clientSocket, response1, strlen(response1));// 接收客户端下一条消息n = read(clientSocket, buffer, MAX_BUFFER_SIZE);if (n < 0) {perror("Error reading from socket");close(clientSocket);free(arg);pthread_exit(NULL);}buffer[n] = '\0';// 检查消息是否为"Omar"if (strcmp(buffer, "Omar") == 0) {const char *response2 = "Omar who?";write(clientSocket, response2, strlen(response2));// 接收客户端最后一条消息n = read(clientSocket, buffer, MAX_BUFFER_SIZE);if (n < 0) {perror("Error reading from socket");close(clientSocket);free(arg);pthread_exit(NULL);}buffer[n] = '\0';// 检查消息是否为"Omar my goodness, you scared me!"if (strcmp(buffer, "Omar my goodness, you scared me!") == 0) {const char *response3 = "Haha, that's a good one! Come on in.";write(clientSocket, response3, strlen(response3));} else {const char *response3 = "I don't understand. Goodbye.";write(clientSocket, response3, strlen(response3));}} else {const char *response2 = "I don't know who that is. Goodbye.";write(clientSocket, response2, strlen(response2));}} else {const char *response = "You didn't say 'Knock knock'. Goodbye.";write(clientSocket, response, strlen(response));}close(clientSocket);free(arg);pthread_exit(NULL);
}int main() {int serverSocket, clientSocket;struct sockaddr_in serverAddr, clientAddr;socklen_t clientAddrLen = sizeof(clientAddr);pthread_t thread;// 创建套接字serverSocket = socket(AF_INET, SOCK_STREAM, 0);if (serverSocket < 0) {perror("Error creating socket");exit(1);}// 初始化服务器地址结构memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY;serverAddr.sin_port = htons(PORT);// 绑定套接字到指定地址和端口if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {perror("Error binding socket");exit(1);}// 监听连接请求if (listen(serverSocket, 5) < 0) {perror("Error listening for connections");exit(1);}printf("Knock knock server is listening on port %d...\n", PORT);while (1) {// 接受客户端连接clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientAddrLen);if (clientSocket < 0) {perror("Error accepting connection");continue;}// 获取客户端IP地址char clientIP[INET_ADDRSTRLEN];inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);printf("Accepted connection from %s:%d\n", clientIP, ntohs(clientAddr.sin_port));// 为每个客户端连接创建一个新线程ThreadArgs *args = (ThreadArgs *)malloc(sizeof(ThreadArgs));args->clientSocket = clientSocket;args->clientAddr = clientAddr;if (pthread_create(&thread, NULL, handleClientThread, (void *)args)!= 0) {perror("Error creating thread");close(clientSocket);free(args);continue;}// 分离线程,使其在结束后自动释放资源pthread_detach(thread);}close(serverSocket);return 0;
}
4.提交git log结果(3分)
fengtairui@fengtairui-virtual-machine:~$ git add knock.c knockmt.c knock knockmt
fengtairui@fengtairui-virtual-machine:~$ git commit -m "konck"
[master 0027bef] konck4 files changed, 220 insertions(+)create mode 100755 knockcreate mode 100644 knock.ccreate mode 100755 knockmtcreate mode 100644 knockmt.c
fengtairui@fengtairui-virtual-machine:~$ git log
commit 0027bef181c7570899f2918eb52ed4f8cbc6041c (HEAD -> master)
Author: fengtairui <1978274655@qq.com>
Date: Tue Dec 17 10:58:53 2024 +0800konck