linux c 網路,獲取本地可用的埠號,判斷網路是否連通
阿新 • • 發佈:2018-12-24
// // Created by darren on 18-8-22. // #include <netdb.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> int getLocalPort() { unsigned short port = 0; int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) return port; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = 0; // 若port指定為0,則呼叫bind時,系統會為其指定一個可用的埠號 int ret = bind(sock, (struct sockaddr *) &addr, sizeof addr); // 3. 繫結 do { if (0 != ret) {// 4. 利用getsockname獲取 //LOGE("upn bind, %d, %s", errno, strerror(errno)) break; } struct sockaddr_in sockaddr; int len = sizeof(sockaddr); ret = getsockname(sock, (struct sockaddr *) &sockaddr, (socklen_t *) &len); // this function now not be hooked if (0 != ret) { // LOGE("upn, getsockname:%d, %s", errno, strerror(errno)) break; } port = ntohs(sockaddr.sin_port); // 獲取埠號 } while (false); //LOGD("UpnConfig::port::%d", port) close(sock); return port; } int getConnectState(int port, const char *ip, int tv_sec, int tv_usec) { int fd = -1; int ret = 0; do { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { //LOGE("Test::connect:socket: %d, %s", errno, strerror(errno)); break; } struct sockaddr_in addr; bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); int flags = fcntl(fd, F_GETFL, 0); if (flags < 0) { //LOGE("Test::connect:get flags: %d, %s", errno, strerror(errno)); break; } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, (void *) flags) < 0) { // LOGE("Test::connect:set flags: %d, %s", errno, strerror(errno)); break; } if (0 == connect(fd, (struct sockaddr *) &addr, sizeof(addr))) { break; } //LOGE("Test::connect:failed: %d, %s", errno, strerror(errno)); #ifdef __ENABLE_LOG_D__ if (EINPROGRESS != errno) { LOGE("Test::connect:failed: %d, %s", errno, strerror(errno)); break; } #endif fd_set fdr, fdw; FD_ZERO(&fdr); FD_ZERO(&fdw); FD_SET(fd, &fdr); FD_SET(fd, &fdw); struct timeval timeout; timeout.tv_sec = tv_sec;// seconds timeout.tv_usec = tv_usec; int rc = select(fd + 1, &fdr, &fdw, NULL, &timeout); if (0 < rc && (FD_ISSET(fd, &fdw) || FD_ISSET(fd, &fdr))) { break; } if (rc < 0) { //LOGE("Test::connect:select: %d, %d, %s", rc, errno, strerror(errno)); break; } if (0 == rc) { //LOGE("Test::connect:time out: %d, %s", errno, strerror(errno)); break; } } while (false); if (0 <= fd) { close(fd); } return ret; }