zoukankan      html  css  js  c++  java
  • UDP转发

    用法: prog.exe address1:port1 address2:port2
    程序将从本地端口的port1接收的数据发往 address1:port1, 同时address1:port1发出的数据将转发会原始的发送者。

    #ifndef __WIN32__
    #include <time.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #define S_CLOSE close
    #define S_READ read
    #define S_WRITE write
    #else
    #include <winsock2.h>
    #define socklen_t int
    #define S_CLOSE(s) closesocket(s)
    #define S_READ(fd, buf, len) recv(fd, buf, len, 0)
    #define S_WRITE(fd, buf, len) send(fd, buf, len, 0)
    #endif

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include <set>

    #define UDPF_KEEP 0x00000001

    struct udpiocb {
        int flags;
        int udpio_fd;
        time_t last_active;
        struct sockaddr_in udpio_addr;
    };

    bool operator < (const struct udpiocb & a, const struct udpiocb & b)
    {
        struct sockaddr_in addr_a, addr_b;
        addr_a = a.udpio_addr;
        addr_b = b.udpio_addr;
        if (addr_a.sin_port == addr_b.sin_port)
            return (addr_a.sin_addr.s_addr < addr_b.sin_addr.s_addr);
        return (addr_a.sin_port < addr_b.sin_port);
    }

    static std::set<udpiocb> udpio_list;

    int udpio_add(u_long addr, u_short port)
    {
        int error;
        struct udpiocb iocb;
        struct sockaddr_in addr_in1;
        int s_udp = socket(PF_INET, SOCK_DGRAM, 0);
        assert(s_udp != -1);
        addr_in1.sin_family = AF_INET;
        addr_in1.sin_port = htons(port);
        addr_in1.sin_addr.s_addr = htonl(INADDR_ANY);
        error = bind(s_udp, (struct sockaddr *)&addr_in1, sizeof(addr_in1));
        assert(error == 0);
        iocb.flags = UDPF_KEEP;
        iocb.udpio_fd = s_udp;
        iocb.udpio_addr = addr_in1;
        iocb.udpio_addr.sin_addr.s_addr = addr;
        udpio_list.insert(iocb);
        return 0;
    }

    int udpio_final(void)
    {
        std::set<udpiocb>::const_iterator iter;
        iter = udpio_list.begin();
        while (iter != udpio_list.end()) {
            S_CLOSE(iter->udpio_fd);
            ++iter;
        }
        return 0;
    }

    int udpio_realloc(const struct sockaddr_in & addr)
    {
        struct udpiocb iocb;
        iocb.flags = 0;
        iocb.udpio_addr = addr;
        std::set<udpiocb>::iterator iter;
        iter = udpio_list.find(iocb);
        if (iter != udpio_list.end()) {
            iocb = *iter;
            time(&iocb.last_active);
            udpio_list.erase(iter);
            udpio_list.insert(iocb);
            return iocb.udpio_fd;
        }
        iocb.udpio_fd = socket(AF_INET, SOCK_DGRAM, 0);
        time(&iocb.last_active);
        udpio_list.insert(iocb);
        return iocb.udpio_fd;
    }

    int udpio_event(fd_set * readfds, fd_set * writefds, fd_set * errorfds)
    {
        int fd, len;
           char buf[4096];
        int addr_len1;
        struct sockaddr_in addr_in1;
        std::set<udpiocb>::iterator iter;
        iter = udpio_list.begin();
        while (iter != udpio_list.end()) {
            if (FD_ISSET(iter->udpio_fd, readfds)) {
                addr_len1 = sizeof(addr_in1);
                len = recvfrom(iter->udpio_fd, buf, sizeof(buf), 0,
                         (struct sockaddr *)&addr_in1, &addr_len1);
                fd = udpio_realloc(addr_in1);
                sendto(fd, buf, len, 0, (struct sockaddr *)&(iter->udpio_addr),
                         sizeof(iter->udpio_addr));
            }
            ++iter;
        }
        return 0;
    }

    int udpio_collect(time_t current)
    {
        int count = udpio_list.size();
        std::set<udpiocb>::iterator iter;
        iter = udpio_list.begin();
        while (iter != udpio_list.end()) {
            if (iter->last_active + 60 < current &&
                    (iter->flags & UDPF_KEEP) == 0) {
                closesocket(iter->udpio_fd);
                udpio_list.erase(iter++);
                continue;
            }
             ++iter;
        }
        if (udpio_list.size() != count)
            printf("udpio collect: %d %d\n", udpio_list.size(), count);
        assert (udpio_list.size() <= count);
        return count - udpio_list.size();
    }

    int udpio_fd_set(fd_set * readfds, fd_set * writefds, fd_set * errorfds)
    {
        int fd_max = 0;
        std::set<udpiocb>::const_iterator iter;
        iter = udpio_list.begin();
        while (iter != udpio_list.end()) {
            FD_SET(iter->udpio_fd, readfds);
            fd_max = (fd_max < iter->udpio_fd? iter->udpio_fd: fd_max);
            ++iter;
        }
        return fd_max;
    }

    int udp_switch(void)
    {
        int count;
        struct fd_set readfds, writefds, errorfds;

        time_t t_last, t_current;
        size_t c_active = udpio_list.size();

        time(&t_last);
        for ( ; ; ) {
            FD_ZERO(&readfds);
            FD_ZERO(&writefds);
            FD_ZERO(&errorfds);

            int max_fd = udpio_fd_set(&readfds, &writefds, &errorfds);

            struct timeval timeout = {1, 1};
            count = select(max_fd + 1, &readfds, &writefds, &errorfds, &timeout);
            if (count == -1) {
                printf("select error: %d \n", count);
                continue;
            }

            if (count == 0) {
                continue;
            }

            if (c_active != udpio_list.size() &&
                    time(&t_current) != t_last) {
                udpio_collect(t_current);
                t_last = t_current;
                c_active = udpio_list.size();
            }

            printf("udpio event\n");
            udpio_event(&readfds, &writefds, &errorfds);
        }
        return 0;
    }

    /* udp_switch addr1:port1 */
    int main(int argc, char * argv[])
    {
        int error;
        char buf[512];

        WSADATA data;
           WSAStartup(0x201, &data);

        int count = 0;
        for (int i = 1; i < argc; i++) {
            char * pdot = NULL;
            strncpy(buf, argv[i], sizeof(buf));
            buf[sizeof(buf) - 1] = 0;
            pdot = strchr(buf, ':');
            if (pdot == NULL)
                continue;
            *pdot++ = 0;
            int port = atoi(pdot);
            if (port == 0 || port == -1)
                continue;
            udpio_add(inet_addr(buf), port);
            count++;
        }

        if (count > 0)
            udp_switch();
        udpio_final();
        return 0;
    }

    https://files.cnblogs.com/ahuo/UDPPass.rar 

  • 相关阅读:
    【转】浅谈Node.js单线程模型
    进程
    网络编程:tcp、udp、socket、struct、socketserver
    Python基础练习
    面向对象:其他双下方法
    isinstance、issubclass、反射
    面向对象:__getitem__、__setitem__、__delitem__
    面向对象:classmethod、staticmethod、property
    面向对象:继承、多态、封装
    异常处理
  • 原文地址:https://www.cnblogs.com/ahuo/p/1997276.html
Copyright © 2011-2022 走看看