通常情况下,我们在路由器下根本取不到本机的外网出口IP。
那么就需要写一个服务部署在公网上,然后通过客户端访问,就知道自己的外网出口IP是啥了。
代码很简单,如下:

/*
 * 环境:Centos7
 * 作者:bugutian
 */
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <string>
#include <iostream>
#include <sstream>

using namespace std;
 
#define MAXLINE  1024
#define OPEN_MAX  16 

typedef struct Node{
    int fd;
    std::string ip;
    Node(int fd,const char* strip):fd(fd), ip(strip){}
}node_t;
 
int main( int argc , char *argv[] )
{
    int listen_port;
    if (argc < 2){
        cout << argv[0] << " [port]" << endl;
        return 0;
    }else{
        listen_port = atoi(argv[1]);
    }
    int i , maxi ,listenfd , connfd , sockfd ,epfd, nfds;
    int n;
    char buf[MAXLINE];
    struct epoll_event ev, events[20];  
    socklen_t clilen;
    struct pollfd client[OPEN_MAX];
    struct sockaddr_in cliaddr , servaddr;
    listenfd = socket(AF_INET , SOCK_STREAM , 0);
    memset(&servaddr,0,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(listen_port);
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    int flags = fcntl(listenfd, F_GETFL, 0);
    fcntl(listenfd, F_SETFL, flags|O_NONBLOCK);
 
    bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr));
    listen(listenfd,10);
    
    epfd = epoll_create(256);
    ev.data.fd=listenfd; 
    ev.events=EPOLLIN|EPOLLET;
    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
    
    for(;;)
    {
        nfds=epoll_wait(epfd,events,20,500); 
        for(i=0; i<nfds; i++)
        {
            if (listenfd == events[i].data.fd)
            {
                clilen = sizeof(cliaddr);
                connfd = accept(listenfd , (struct sockaddr *)&cliaddr, &clilen);
                if(connfd < 0)  
                {  
                    perror("connfd < 0");  
                    exit(1);  
                }
                node_t* ptr = new Node(connfd, inet_ntoa(cliaddr.sin_addr));
                ev.data.ptr = (void* )ptr;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
            }
            else if (events[i].events & EPOLLIN)
            {
                node_t* tmpPrt = (node_t*)events[i].data.ptr;
                sockfd = tmpPrt->fd;
                if ( sockfd < 0)  
                    continue;  
                n = recv(sockfd,buf,MAXLINE,0);
                if (n <= 0)   
                {    
                    close(sockfd);  
                    events[i].data.fd = -1;  
                }
                else
                {
                    buf[n]='\0';
                    printf("Socket %d said : %s\n",sockfd,buf);
                    ev.data.ptr = tmpPrt; 
                    ev.events=EPOLLOUT|EPOLLET;
                    epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
                }
            }
            else if( events[i].events&EPOLLOUT )
            {
                node_t* ptr = (node_t*)events[i].data.ptr;
                
                string rspData = "{\"ip\":\"" + ptr->ip + "\"}";
                ostringstream rspStr;
                rspStr << "HTTP/1.1 200 OK\r\n";
                rspStr << "Connection: keep-alive\r\n";
                rspStr << "Content-Type: text/json;charset=utf-8\r\n";
                rspStr << "Access-Control-Allow-Origin: *\r\n";
                rspStr << "Access-Control-Allow-Headers: X-Requested-With\r\n";
                rspStr << "Access-Control-Allow-Methods: GET,POST,OPTIONS\r\n";
                rspStr << "Content-Length: " << rspData.length() << "\r\n\r\n" << rspData;
                
                send(ptr->fd, rspStr.str().c_str(), rspStr.str().length(), 0);
                delete ptr;
                close(sockfd);
            }
            else 
            {
                printf("This is not avaible!");
            }
        }
    }
    close(epfd);  
    return 0;
}

编译

 g++ getwanip.cpp -o getwanip

运行

nohup ./getwanip 8080

然后通过浏览器访问服务器的8080端口,就可以看到自己的外网IP了。

posted on 2021-07-07 14:45  步孤天  阅读(541)  评论(0编辑  收藏  举报