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

罗索

libnatpmp:实现客户端自动绑定路由器外部端口

落鹤生 发布于 2012-01-13 10:04 点击:次 
libnatpmp项目,其提供了十分简单的借口形式对路由器端口映射进行的封装,只要路由器支持upnp可以实现客户端自动绑定路由器外部端口,十分的有用。
TAG:

原文地址:http://miniupnp.free.fr/libnatpmp.html

通过对libupnp,及mimiupnp两个项目的了解,感觉libupnp太繁杂,太沉重了,miniupnp包括对upnp客户端及服务器的实现。 最为重要的是libnatpmp项目,其提供了十分简单的借口形式对路由器端口映射进行的封装,只要路由器支持upnp可以实现客户端自动绑定路由器外部 端口,十分的有用。

而且今天在学习upnp的过程无意发现了俩个异步事件机制的软件库,可以用来取代网络服务器所使用的循环检查架构,可以省去对网络的处理。

I hadn't noticed when I started to code libnatpmp, but another library was allready existing using the same name : Allen Porter made his C++ library in october/november 2007. If you want to have a look at it, it is available here. So what's next ? maybe I should change the name of my library ? what do you think of libnatpmpc ? (c like client or like the C language ?)

The NAT Port Mapping Protocol (NAT-PMP)

NAT-PMP

is the direct concurrent to the UPnP IGD specification. It is providing a way to do

NAT traversal

. It is part of the

Bonjour protocol specifications

. You can get the description of this simple protocol

here

or by reading the

draft

. At the moment it is mainly supported by

Apple

software and hardware. If you are looking for a way to add NAT-PMP capabilities to your *BSD, Linux or (Open)Solaris Router, you should have a look at

MiniUPnPd

which is supporting NAT-PMP in addition to UPnP since December 2007 !

libnatpmp description

libnatpmp is an attempt to make a portable and fully compliant implementation of the protocol for the client side. It is based on non blocking sockets and all calls of the API are asynchronous. It is therefore very easy to integrate the NAT-PMP code to any event driven code.

Download and build libnatpmp

To download the source code, go to the

MiniUPnP Download page

.

 

Use

gmake

or

make

to build the library and samples.

Use libnatpmp in your programs

It should be very easy to use libnatpmp in any C/C++ program. All the API is described in the natpmp.h file.

 

  • First of all, a variable of type natpmp_t must be allocated and initnatpmp() must be called.
  • sendpublicaddressrequest() or sendnewportmappingrequest() can be called.
  • For each request sent, readnatpmpresponseorretry() should be called as long as it returns NATPMP_TRYAGAIN.
  • If you are waiting for the socket (field s in the natpmp_t object) to be ready for reading using system calls such as select() or poll(), you can use getnatpmprequesttimeout() in order to know how long to wait before calling readnatpmpresponseorretry() anyway.
  • To free all used resources, closenatpmp() can be called.

Sample code

Error checking has been deliberately omitted. Please check all return codes in natpmp.h file.

simple sample

This very simple sample just ask for a redirection and return when the job is done.


void redirect(uint16_t privateport, uint16_t publicport)
{
  int r;
  natpmp_t natpmp;
  natpmpresp_t response;
  initnatpmp(&natpmp);
  sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, privateport, publicport, 3600);
  do {
    fd_set fds;
    struct timeval timeout;
    FD_ZERO(&fds);
    FD_SET(natpmp.s, &fds);
    getnatpmprequesttimeout(&natpmp, &timeout);
    select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
    r = readnatpmpresponseorretry(&natpmp, &response);
  } while(r==NATPMP_TRYAGAIN);
  printf("mapped public port %hu to localport %hu liftime %u\n",
         response.newportmapping.mappedpublicport,
         response.newportmapping.privateport,
         response.newportmapping.lifetime);
  closenatpmp(&natpmp);
}

more complex sample

We could imagine the init phase of a P2P software. During this phase, the software tries to get the public IP address and add a port mapping. At the end of the process, natpmpstate will be either

Sdone

or

Serror

.


{
  natpmp_t natpmp;
  natpmpresp_t response;
  enum { Sinit=0, Ssendpub, Srecvpub, Ssendmap, Srecvmap, Sdone, Serror=1000 } natpmpstate = Sinit;
  int r;
  [...]
  if(initnatpmp(&natpmp)<0)
    natpmpstate = Serror;
  else
    natpmpstate = Ssendpub;
  [...]
  while(!finished_all_init_stuff) {
    [...]
    other init stuff :)
    [...]
    switch(natpmpstate) {
    case Ssendpub:
      if(sendpublicaddressrequest(&natpmp)<0);
        natpmpstate = Serror;
      else
        natpmpstate = Srecvpub;
      break;
    case Srecvpub:
      r = readnatpmpresponseorretry(&natpmp, &response);
      if(r<0 && r!=NATPMP_TRYAGAIN)
        natpmpstate = Serror;
      else if(r!=NATPMP_TRYAGAIN) {
        copy(publicaddress, response.publicaddress.addr);
        natpmpstate = Ssendmap;
      }
      break;
    case Ssendmap:
      if(sendnewportmappingrequest(&natpmp, protocol, privateport, publicport, lifetime)<0);
        natpmpstate = Serror;
      else
        natpmpstate = Srecvmap;
      break;
    case Srecvmap:
      r = readnatpmpresponseorretry(&natpmp, &response);
      if(r<0 && r!=NATPMP_TRYAGAIN)
        natpmpstate = Serror;
      else if(r!=NATPMP_TRYAGAIN) {
        copy(publicport, response.newportmapping.mappedpublicport);
        copy(privateport, response.newportmapping.privateport);
        copy(mappinglifetime, response.newportmapping.lifetime);
        natpmpclose(&natpmp);
        natpmpstate = Sdone;
      }
      break;
    }
    [...]
  }
  [...]
}

Thomas Bernard

To contact me, use the MiniUPnP forum or use email : miniupnp _AT_ free _DOT_ fr

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