织梦CMS - 轻松建站从此开始!

罗索

UDP转发小工具

jackyhwei 发布于 2011-09-02 12:13 点击:次 
用法: prog.exe address1:port1 address2:port2。程序将从本地端口的port1接收的数据发往 address1:port1, 同时address1:port1发出的数据将转发会原始的发送者。
TAG:

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

  1. #ifndef __WIN32__ 
  2. #include <time.h> 
  3. #include <errno.h> 
  4. #include <fcntl.h> 
  5. #include <unistd.h> 
  6. #include <signal.h> 
  7. #include <sys/types.h> 
  8. #include <netinet/in.h> 
  9. #include <arpa/inet.h> 
  10. #include <sys/socket.h> 
  11. #define S_CLOSE close 
  12. #define S_READ read 
  13. #define S_WRITE write 
  14. #else 
  15. #include <winsock2.h> 
  16. #define socklen_t int 
  17. #define S_CLOSE(s) closesocket(s) 
  18. #define S_READ(fd, buf, len) recv(fd, buf, len, 0) 
  19. #define S_WRITE(fd, buf, len) send(fd, buf, len, 0) 
  20. #endif 
  21.  
  22. #include <stdlib.h> 
  23. #include <stdio.h> 
  24. #include <string.h> 
  25. #include <assert.h> 
  26. #include <set> 
  27.  
  28. #define UDPF_KEEP 0x00000001 
  29.  
  30. struct udpiocb { 
  31.     int flags; 
  32.     int udpio_fd; 
  33.     time_t last_active; 
  34.     struct sockaddr_in udpio_addr; 
  35. }; 
  36.  
  37. bool operator < (const struct udpiocb & a, const struct udpiocb & b) 
  38.     struct sockaddr_in addr_a, addr_b; 
  39.     addr_a = a.udpio_addr; 
  40.     addr_b = b.udpio_addr; 
  41.     if (addr_a.sin_port == addr_b.sin_port) 
  42.         return (addr_a.sin_addr.s_addr < addr_b.sin_addr.s_addr); 
  43.     return (addr_a.sin_port < addr_b.sin_port); 
  44.  
  45. static std::set<udpiocb> udpio_list; 
  46.  
  47. int udpio_add(u_long addr, u_short port) 
  48.     int error; 
  49.     struct udpiocb iocb; 
  50.     struct sockaddr_in addr_in1; 
  51.     int s_udp = socket(PF_INET, SOCK_DGRAM, 0); 
  52.     assert(s_udp != -1); 
  53.     addr_in1.sin_family = AF_INET; 
  54.     addr_in1.sin_port = htons(port); 
  55.     addr_in1.sin_addr.s_addr = htonl(INADDR_ANY); 
  56.     error = bind(s_udp, (struct sockaddr *)&addr_in1, sizeof(addr_in1)); 
  57.     assert(error == 0); 
  58.     iocb.flags = UDPF_KEEP; 
  59.     iocb.udpio_fd = s_udp; 
  60.     iocb.udpio_addr = addr_in1; 
  61.     iocb.udpio_addr.sin_addr.s_addr = addr; 
  62.     udpio_list.insert(iocb); 
  63.     return 0; 
  64.  
  65. int udpio_final(void
  66.     std::set<udpiocb>::const_iterator iter; 
  67.     iter = udpio_list.begin(); 
  68.     while (iter != udpio_list.end()) { 
  69.         S_CLOSE(iter->udpio_fd); 
  70.         ++iter; 
  71.     } 
  72.     return 0; 
  73.  
  74. int udpio_realloc(const struct sockaddr_in & addr) 
  75.     struct udpiocb iocb; 
  76.     iocb.flags = 0; 
  77.     iocb.udpio_addr = addr; 
  78.     std::set<udpiocb>::iterator iter; 
  79.     iter = udpio_list.find(iocb); 
  80.     if (iter != udpio_list.end()) { 
  81.         iocb = *iter; 
  82.         time(&iocb.last_active); 
  83.         udpio_list.erase(iter); 
  84.         udpio_list.insert(iocb); 
  85.         return iocb.udpio_fd; 
  86.     } 
  87.     iocb.udpio_fd = socket(AF_INET, SOCK_DGRAM, 0); 
  88.     time(&iocb.last_active); 
  89.     udpio_list.insert(iocb); 
  90.     return iocb.udpio_fd; 
  91.  
  92. int udpio_event(fd_set * readfds, fd_set * writefds, fd_set * errorfds) 
  93.     int fd, len; 
  94.        char buf[4096]; 
  95.     int addr_len1; 
  96.     struct sockaddr_in addr_in1; 
  97.     std::set<udpiocb>::iterator iter; 
  98.     iter = udpio_list.begin(); 
  99.     while (iter != udpio_list.end()) { 
  100.         if (FD_ISSET(iter->udpio_fd, readfds)) { 
  101.             addr_len1 = sizeof(addr_in1); 
  102.             len = recvfrom(iter->udpio_fd, buf, sizeof(buf), 0, 
  103.                      (struct sockaddr *)&addr_in1, &addr_len1); 
  104.             fd = udpio_realloc(addr_in1); 
  105.             sendto(fd, buf, len, 0, (struct sockaddr *)&(iter->udpio_addr), 
  106.                      sizeof(iter->udpio_addr)); 
  107.         } 
  108.         ++iter; 
  109.     } 
  110.     return 0; 
  111.  
  112. int udpio_collect(time_t current) 
  113.     int count = udpio_list.size(); 
  114.     std::set<udpiocb>::iterator iter; 
  115.     iter = udpio_list.begin(); 
  116.     while (iter != udpio_list.end()) { 
  117.         if (iter->last_active + 60 < current && 
  118.                 (iter->flags & UDPF_KEEP) == 0) { 
  119.             closesocket(iter->udpio_fd); 
  120.             udpio_list.erase(iter++); 
  121.             continue
  122.         } 
  123.          ++iter; 
  124.     } 
  125.     if (udpio_list.size() != count) 
  126.         printf("udpio collect: %d %d\n", udpio_list.size(), count); 
  127.     assert (udpio_list.size() <= count); 
  128.     return count - udpio_list.size(); 
  129.  
  130. int udpio_fd_set(fd_set * readfds, fd_set * writefds, fd_set * errorfds) 
  131.     int fd_max = 0; 
  132.     std::set<udpiocb>::const_iterator iter; 
  133.     iter = udpio_list.begin(); 
  134.     while (iter != udpio_list.end()) { 
  135.         FD_SET(iter->udpio_fd, readfds); 
  136.         fd_max = (fd_max < iter->udpio_fd? iter->udpio_fd: fd_max); 
  137.         ++iter; 
  138.     } 
  139.     return fd_max; 
  140.  
  141. int udp_switch(void
  142.     int count; 
  143.     struct fd_set readfds, writefds, errorfds; 
  144.  
  145.     time_t t_last, t_current; 
  146.     size_t c_active = udpio_list.size(); 
  147.  
  148.     time(&t_last); 
  149.     for ( ; ; ) { 
  150.         FD_ZERO(&readfds); 
  151.         FD_ZERO(&writefds); 
  152.         FD_ZERO(&errorfds); 
  153.  
  154.         int max_fd = udpio_fd_set(&readfds, &writefds, &errorfds); 
  155.  
  156.         struct timeval timeout = {1, 1}; 
  157.         count = select(max_fd + 1, &readfds, &writefds, &errorfds, &timeout); 
  158.         if (count == -1) { 
  159.             printf("select error: %d \n", count); 
  160.             continue
  161.         } 
  162.  
  163.         if (count == 0) { 
  164.             continue
  165.         } 
  166.  
  167.         if (c_active != udpio_list.size() && 
  168.                 time(&t_current) != t_last) { 
  169.             udpio_collect(t_current); 
  170.             t_last = t_current; 
  171.             c_active = udpio_list.size(); 
  172.         } 
  173.  
  174.         printf("udpio event\n"); 
  175.         udpio_event(&readfds, &writefds, &errorfds); 
  176.     } 
  177.     return 0; 
  178.  
  179. /* udp_switch addr1:port1 */ 
  180. int main(int argc, char * argv[]) 
  181.     int error; 
  182.     char buf[512]; 
  183.  
  184.     WSADATA data; 
  185.        WSAStartup(0x201, &data); 
  186.  
  187.     int count = 0; 
  188.     for (int i = 1; i < argc; i++) { 
  189.         char * pdot = NULL; 
  190.         strncpy(buf, argv[i], sizeof(buf)); 
  191.         buf[sizeof(buf) - 1] = 0; 
  192.         pdot = strchr(buf, ':'); 
  193.         if (pdot == NULL) 
  194.             continue
  195.         *pdot++ = 0; 
  196.         int port = atoi(pdot); 
  197.         if (port == 0 || port == -1) 
  198.             continue
  199.         udpio_add(inet_addr(buf), port); 
  200.         count++; 
  201.     } 
  202.  
  203.     if (count > 0) 
  204.         udp_switch(); 
  205.     udpio_final(); 
  206.     return 0; 

 

(pagx)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201109/14937.html]
本文出处:blog.chinaunix.net 作者:pagx
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容