该文章仅供学习交流,严禁用于任何商业或非法用途,如有侵权,请联系本人删除!
实验名称
TCP单进程循环服务器与单进程客户端(简单回声)
实验内容
编写TCP单进程循环服务器程序与单进程客户端程序,实现以下主体功能:
- 客户端启动连接服务器之后,进入命令行交互模式。
- 操作人员在命令行窗口输入一行字符并回车后,客户端进程立刻从命令行(本质即stdin)读取数据,并将该行信息发送给服务器。
- 服务器收到该行信息后,会将该信息原封不动的返回给客户端,即所谓消息回声(Message Echo)
- 客户端收到服务器返回的消息回声后,将其打印输出至屏幕(本质即stdout)。
- 客户端在从命令行收到EXIT指令后退出。
实验代码
-
服务器程序代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> #include <signal.h> #define MAX_LEN 1024 int sigint_flag = 0; void handle_sigint(int sig) { printf("[srv] SIGINT is coming!\n"); sigint_flag = 1; } int install_sigint() { struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = handle_sigint; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa,NULL); return 0; } void srv_biz(int connfd, int veri_code) { char buffer[MAX_LEN]; int n; while ((n = read(connfd, buffer, MAX_LEN)) > 0) { printf("[ECH_RQT]%s", buffer); char receive[MAX_LEN + 15]; sprintf(receive, "(%d)%s", veri_code, buffer); write(connfd, receive, strlen(receive)); memset(buffer, 0, sizeof(buffer)); } close(connfd); } int main(int argc, char *argv[]) { if (argc < 4) { printf("Usage: %s <ip_address> <port> <veri_code>\n", argv[0]); return 1; } char ip_address[20]; strcpy(ip_address, argv[1]); int port = atoi(argv[2]); int veri_code = atoi(argv[3]); int connfd; //安装SIGINT 信号处理器 install_sigint(); //创建套接字 int listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { perror("[srv] socket creation failed"); return 1; } struct sockaddr_in server_addr, client_addr; bzero(&server_addr, sizeof(server_addr)); bzero(&client_addr, sizeof(client_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); socklen_t clilen; char client_ip[MAX_LEN]; if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("[srv] bind failed"); return 1; } if (listen(listenfd, 10) < 0) { perror("[srv] listen failed"); return 1; } printf("[srv] server[%s:%d][%d] is initializing!\n", ip_address, port, veri_code); while (!sigint_flag) { clilen = sizeof(client_addr); if ((connfd = accept(listenfd, (struct sockaddr*) &client_addr, &clilen)) < 0) { if(errno == EINTR) continue; else { perror("accept error"); exit(1); } } inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, MAX_LEN); int client_port = ntohs(client_addr.sin_port); printf("[srv] client[%s:%d] is accepted!\n", client_ip, client_port); srv_biz(connfd, veri_code); printf("[srv] client[%s:%d] is closed!\n", client_ip, client_port); } close(listenfd); return 0; }
-
客户端程序代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define MAX_LEN 1024 int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: %s <server_ip> <server_port>\n", argv[0]); return 1; } const char *server_ip = argv[1]; int server_port = atoi(argv[2]); int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Failed to create socket"); return 1; } struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(server_ip); server_addr.sin_port = htons(server_port); if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Failed to connect to server"); return 1; } printf("[cli] server[%s:%d] is connected!\n", server_ip, server_port); char message[MAX_LEN]; while (1) { if (fgets(message, sizeof(message), stdin) == NULL) { perror("Failed to read message from stdin"); break; } printf("[ECH_RQT]%s",message); int message_len = strlen(message); if (strcmp(message, "EXIT\n") == 0) { break; } if (write(sock, message, message_len) < 0) { perror("Failed to send message to server"); break; } char response[MAX_LEN]; int recv_len = read(sock, response, sizeof(response) - 1); if (recv_len < 0) { perror("Failed to receive response from server"); break; } else if (recv_len == 0) { printf("Server closed the connection\n"); break; } response[recv_len] = '\0'; printf("[ECH_REP]%s", response); } close(sock); printf("[cli] client is to return!\n"); return 0; }