實驗樓樓賽第4期C語言專案挑戰題 -遠端 Shell
阿新 • • 發佈:2018-12-21
這道題實際上考察的是 Linux 上的 C 語言網路程式設計。並且只給出了客戶端的原始碼和服務端的二進位制檔案。需要根據客戶端程式碼編譯和執行的狀態來找 bug,必要的時候需要進行除錯跟蹤。
在客戶端程式碼檔案中包含了多個 socket 程式設計中容易犯的錯誤:
錯誤1:TCP 連線
伺服器端使用 TCP 連線,程式碼中建立 socket 的時候用的是 UDP 連線方式,需要使用:
int sock = socket(AF_INET, SOCK_STREAM, 0);
錯誤2:埠號使用網路位元組序
位元組序使用錯誤也是常見的 socket 錯誤,需要使用 htons 函式將主機位元組序的埠號改為網路位元組序:
connection.sin_port = htons(PORT);
錯誤3:強制型別轉化
connect 函式中第二個引數需要使用 struct sockaddr 型別指標,但 connection 的型別不匹配,這個錯誤在編譯的提示中可以很容易看出來。修改的程式碼為:
if (connect(sock, (struct sockaddr*)&connection, sizeof(connection)) != 0)
錯誤4:if 中的 == 誤用
pid 變數沒有初始化直接在 if 中用作 == 比較,此處應該是 =,pid 為 fork 建立後返回的程序 ID:
if(pid = fork())
最終修改後的程式碼:
#include "share.h" void send_cmd(int sock, int pid) { char str[MAX_MSG_LENGTH] = {0}; printf("> "); while (fgets(str, MAX_MSG_LENGTH, stdin) == str) { if(strncmp(str, END_STRING, strlen(END_STRING)) == 0) break; if(send(sock, str, strlen(str)+1, 0) < 0) perro("send"); } kill(pid, SIGKILL); printf("Goodbye.\n"); } void receive(int sock) { char buf[MAX_MSG_LENGTH] = {0}; int filled = 0; while(filled = recv(sock, buf, MAX_MSG_LENGTH-1, 0)){ buf[filled] = '\0'; printf("%s", buf); fflush(stdout); } printf("Server disconnected.\n"); } int main(int argc, char **argv) { if(argc != 2) perro("args"); int sock = socket(AF_INET, SOCK_STREAM, 0); if(sock == -1) perro("socket"); struct in_addr server_addr; if(!inet_aton(argv[1], &server_addr)) perro("inet_aton"); struct sockaddr_in connection; connection.sin_family = AF_INET; memcpy(&connection.sin_addr, &server_addr, sizeof(server_addr)); connection.sin_port = htons(PORT); if (connect(sock, (struct sockaddr*)&connection, sizeof(connection)) != 0) perro("connect"); int pid; if(pid = fork()) send_cmd(sock, pid); else receive(sock); return 0; }