1. 程式人生 > >linux c 網路,獲取本地可用的埠號,判斷網路是否連通

linux c 網路,獲取本地可用的埠號,判斷網路是否連通

//
// 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;
}