Try   HackMD

socket programming c in linux

目標

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

完成 socket,在 client 端輸入,server 端回傳計算後的數學公式。

// client端 // server端回傳 add 1 26 27 abs -100 100 mul 33 55 1815 unsupoort!! Hello kill

實作程式碼

server.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int process_command(char *buffer, char *response) { int a, b; char command[256]; sscanf(buffer, "%s %d %d", command, &a, &b); // 解析從緩衝區讀取的命令 // 根據命令生成回應 if (strcmp(command, "add") == 0) { sprintf(response, "%d", a + b); } else if (strcmp(command, "abs") == 0) { sprintf(response, "%d", abs(a)); } else if (strcmp(command, "mul") == 0) { sprintf(response, "%d", a * b); } else if (strcmp(command, "kill") == 0) { // 檢查是否是 "kill" 命令 return 1; // 如果是 "kill" 命令,返回1,讓主迴圈停止 } else { strcpy(response, "Hello"); } return 0; // 正常情況下返回 0 } int main() { int sockfd, newsockfd, portno = 5001; char buffer[256], response[256]; struct sockaddr_in serv_addr, cli_addr; socklen_t clilen; sockfd = socket(AF_INET, SOCK_STREAM, 0); // 創建一個新的 socket bzero((char *) &serv_addr, sizeof(serv_addr)); // 初始化伺服器地址結構 serv_addr.sin_family = AF_INET; // 設定地址家族為 Internet serv_addr.sin_addr.s_addr = INADDR_ANY; // 允許任何來源的連接 serv_addr.sin_port = htons(portno); // 設定端口號 bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); // 綁定 socket 到給定的 IP 和端口號 listen(sockfd, 5); // 開始監聽連接,並設定最大連接數為5 clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); // 接受連接,並獲得新的 socket 檔案描述符 // 主迴圈 while (1) { bzero(buffer, 256); // 清空緩衝區 read(newsockfd, buffer, 255); // 從 socket 中讀取數據 if (strlen(buffer) == 0) { break; // 如果讀取到的數據為空,退出迴圈 } // 處理命令,如果處理結果為1,退出迴圈 if(process_command(buffer, response)) { break; } write(newsockfd, response, strlen(response)); // 將處理結果寫入 socket } close(newsockfd); // 關閉新的 socket 檔案描述符 close(sockfd); // 關閉原始 socket 檔案描述符 return 0; }

client.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <unistd.h> int main() { int sockfd, portno = 5001, n; // 定義 socket 檔案描述符、端口號和返回值 struct sockaddr_in serv_addr; // 定義伺服器地址結構 struct hostent *server; // 定義主機信息 char buffer[256], response[256]; // 定義請求和回應緩衝區 sockfd = socket(AF_INET, SOCK_STREAM, 0); // 創建一個新的 socket server = gethostbyname("localhost"); // 獲取本地主機名 bzero((char *) &serv_addr, sizeof(serv_addr)); // 初始化伺服器地址結構 serv_addr.sin_family = AF_INET; // 設定地址家族為 Internet bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length); // 拷貝主機地址到伺服器地址結構 serv_addr.sin_port = htons(portno); // 設定端口號 connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)); // 連接到伺服器 while (fgets(buffer,255,stdin) != NULL) { // 循環讀取標準輸入 buffer[strcspn(buffer, "\n")] = '\0'; // 去掉字串末尾的換行符 if(strcmp(buffer, "") == 0) { // 如果輸入為空,退出循環 break; } write(sockfd, buffer, strlen(buffer)); // 寫請求到 socket if(strcmp(buffer, "kill") == 0) { // 如果命令為 "kill",退出循環 break; } bzero(response, 256); // 清空回應緩衝區 read(sockfd, response, 255); // 從 socket 中讀取回應 printf("%s\n", response); // 打印回應 } close(sockfd); // 關閉 socket return 0; }

Makefile

all: server client server: server.c gcc -o server server.c client: client.c gcc -o client client.c clean: rm -f server client

in.txt

add 1 26 abs -100 mul 33 55 unsupoort!! kill

ans.txt

27 100 1815 Hello

啟動服務

以下命令用於編譯服務器代碼並將編譯後的文件保存為 server_node

gcc server.c -o server_node

以下命令用於編譯客戶端代碼並將編譯後的文件保存為 client_node

gcc client.c -o client_node

然後可以在不同的終端運行 server_nodeclient_node 文件來查看輸出 下面的命令用於運行編譯後的文件

./server_node

在單獨的終端中運行 client_node,並可在 client 端測試

./client_node

測試

make ./server & ./client < in > out diff -s out ans

跑完測試後,如果一切正確,應該會看到以下消息:Files out and ans are identical