代碼分爲2部分;
1.隨機生成一個未被 udp 佔用的端口號
2.啓動一個 udp程序,使用我們剛纔找到的端口號
#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <cstring> #include <cstdlib> #include <ctime> #include <unistd.h> #include <errno.h> const int MAXLINE = 1024; int find_available_udp_port() { const int MIN_PORT = 1024; // 通常1024以下的端口是保留的 const int MAX_PORT = 65535; // UDP端口的最大範圍 int sockfd, port = -1; struct sockaddr_in serv_addr; srand(time(nullptr)); // 初始化隨機數生成器 int iMaxTryCount = 100; int iStartTryCount = 0; // 不斷嘗試直到找到可用的端口 do { port = MIN_PORT + rand() % (MAX_PORT - MIN_PORT + 1); // 生成隨機端口號 // 創建UDP socket if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { std::cerr << "ERROR opening socket" << std::endl; return -1; // 錯誤處理 } // 設置服務器的地址和端口 memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; // 監聽所有網絡接口 serv_addr.sin_port = htons(port); // 端口號 // 嘗試綁定到端口 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { // 如果綁定失敗,關閉socket並繼續嘗試 close(sockfd); if (errno != EADDRINUSE) { std::cerr << "ERROR on binding: " << strerror(errno) << std::endl; return -1; // 非EADDRINUSE錯誤,返回錯誤 }else{ printf("Address already in use, port:%d\r\n", port); //端口被佔用,繼續嘗試其他方法... continue } } else { // 綁定成功,端口可用,關閉socket並返回端口號 close(sockfd); return port; } ++iStartTryCount; } while (iStartTryCount<iMaxTryCount); // 理論上,只要端口範圍足夠大,總會找到一個可用的端口 return port; } int main() { int port = find_available_udp_port(); if (port >= 0) { std::cout << "Found available UDP port: " << port << std::endl; } else { std::cerr << "Failed to find an available UDP port." << std::endl; } int sockfd; struct sockaddr_in servaddr, cliaddr; char buffer[MAXLINE]; socklen_t len; // 創建UDP socket if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { std::cerr << "ERROR opening socket" << std::endl; return 1; } // 清除servaddr結構並設置地址家族 memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 監聽所有網絡接口 servaddr.sin_port = htons(port); // 端口號 // 綁定到指定的端口 if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { std::cerr << "ERROR on binding" << std::endl; return 1; } // 打印啓動成功信息 std::cout << "Server started and listening on port " << port << std::endl; // 無限循環,等待接收數據 while (true) { len = sizeof(cliaddr); ssize_t n = recvfrom(sockfd, (char *)buffer, MAXLINE, MSG_WAITALL, (struct sockaddr *) &cliaddr, &len); buffer[n] = '\0'; if (n < 0) { std::cerr << "ERROR in recvfrom" << std::endl; break; } // 打印接收到的數據 std::cout << "Received from client: " << buffer << std::endl; // (可選)發送數據回客戶端 //sendto(sockfd, (const char *)buffer, strlen(buffer), MSG_CONFIRM, // (const struct sockaddr *) &cliaddr, sizeof(cliaddr)); } // 關閉socket close(sockfd); return 0; }