我们公司是网络防火墙的,客户通过外网来访问我们的服务器资源。
我们实现的流程是:首先经过过滤包找到使用权限,可以访问我们的资源。用到的是SPI技术我现在做的是访问前台客户端,也就是Activex控件,需要在ipfliter.dll中加入QOS功能我是在
int WSPAPI WSPConnect(
    SOCKET s,
    const struct sockaddr FAR * name,
    int namelen,
    LPWSABUF lpCallerData,
    LPWSABUF lpCalleeData,
    LPQOS lpSQOS,
    LPQOS lpGQOS,
    LPINT lpErrno);
在WSPConnect中找到有QOS参数的,我现在想问怎么实现:通过客户端访问我们服务器时,达到限速和控制流量的功能呢?我目前的做法是:定义了一个QOS参数,在里面设置了限制的速度,和流量参数。并传递给WSPConnect中的lpSQOS参数。但是测试的时候从我们服务器上下东西,并没有起到相应的功能。请问各位高手们,我应该怎么做,才能起到限制客户端的流速和流量的功能呢? 请大侠们教我,非常着急! 谢谢!!!

解决方案 »

  1.   

    lpproctable->lpWSPSend = WSPSend;
    lpproctable->lpWSPRecv = WSPRecv;int WSPAPI WSPSend(
     SOCKET s,
     LPWSABUF lpBuffers,  DWORD dwBufferCount,
     LPDWORD lpNumberOfBytesSent,           DWORD dwFlags,
     LPWSAOVERLAPPED lpOverlap
                                             LPWSAOVERLAPPED_COMPLETION_ROUTINE            lpCompletionRoutine,   LPWSATHREADID lpThreadId, //执行调用的应用程序线程
     LPINT lpErrno)
    {}
    请问是否可以在重载的WSPSend和WSPRecv函数中lpBuffers里的缓冲区char *Buff,ULONG len,做拆包并延时发送处理呢?    具体要如何实现呢? 我写过一段但有问题:不知道怎么回事:lFlowVariable //为限制的速度值
    if(dwBufferCount = 1)
    {
    DWORD i = 0;
    WSABUF SendBuffers;
    DWORD m = lpBuffers->len/lFlowVariable;  //计算拆包数并得到每包长度
    DWORD unCount = m;

    //首次发送拆包后的第一包
    SendBuffers.len = m;
    SendBuffers.buf = lpBuffers->buf;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);

    //remanent中放的是:当前缓冲去中剩余包的长度
    DWORD remanent = 0;
    remanent = lpBuffers->len - m;
    DWORD len2 = 0;
    Sleep(m);//首次延迟的秒数

    DWORD j = 0;  //剩余长度的偏移量

    //下面循环体实现发送当前缓冲去剩余包数
    while(remanent>0)
    {
    j++;
    len2=remanent>m?m:remanent;

    SendBuffers.len = len2;
    SendBuffers.buf = lpBuffers->buf+len2*j;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId,lpErrno);

    if( j == m )
    {
    SendBuffers.len = len2;
    SendBuffers.buf = lpBuffers->buf+m*i;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId,lpErrno);
    break;
    }

    remanent  =  remanent - m;

    if(unCount--) //此处现实限速功能
    {
    Sleep(m);
    }
    }
    WriteLog("WSPSend:SOCKET=%ld:dwBufferCount=%ld:len=%ld",
    s,dwBufferCount,lpBuffers->len);
    return nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
    }
    }
    /*
    else
    {
    WSABUF SendBuffers;
    for(DWORD i = 0;i<dwBufferCount; i++) //循环体根据缓冲区的个数
    {
    if((lpBuffers+i)->len != 0) //判断缓冲区偏移量的长度是否为零
    {
    DWORD m = (lpBuffers+i)->len/lFlowVariable;  //计算拆包数并得到每包长度
    DWORD unCount = m;

    //首次发送拆包后的第一包
    SendBuffers.len = m;
    SendBuffers.buf = (lpBuffers+i)->buf;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);

    //remanent中放的是:当前缓冲去中剩余包的长度
    DWORD remanent = 0;
    remanent = (lpBuffers+i)->len - m;
    DWORD len2 = 0;
    Sleep(m);//首次延迟的秒数

    DWORD j = 0;  //剩余长度的偏移量

    //下面循环体实现发送当前缓冲去剩余包数
    while(remanent>0)
    {
    j++;
    len2=remanent>m?m:remanent;

    SendBuffers.len = len2;
    SendBuffers.buf = (lpBuffers+i)->buf+len2*j;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId,lpErrno);

    if( j == m )
    {
    SendBuffers.len = len2;
    SendBuffers.buf = (lpBuffers+i)->buf+m*i;
    nextproctable.lpWSPSend(s, &SendBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
    lpOverlapped, lpCompletionRoutine, lpThreadId,lpErrno);
    break;
    }

    remanent  =  remanent - m;

    if(unCount--) //此处现实限速功能
    {
    Sleep(m);
    }
    }
    }
    }
    }
      

  2.   

    我实在WSPRecv里面分包,可惜似乎不行。
      

  3.   

    int WSPAPI WSPRecv(
     SOCKET s,
     LPWSABUF lpBuffers,
     DWORD dwBufferCount,
     LPDWORD lpNumberOfBytesRecvd,
     LPDWORD lpFlags,
     LPWSAOVERLAPPED lpOverlapped,
     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
     LPWSATHREADID lpThreadId,
     LPINT lpErrno
        )
    {
    char szExePath[512]={0};
    GetModuleFileName(NULL,szExePath,512);
    DebugTrace("[NetLimitRecv]The recv Applaction is %s",szExePath);
    DebugTrace("[NetLimitRecv]The dwBufferCount is %d",dwBufferCount);
    DebugTrace("[NetLimitRecv]The *lpNumberOfBytesRecvd is %d before lpWSPRecv call",
    *lpNumberOfBytesRecvd); if(lpOverlapped&&lpCompletionRoutine)
    {
    DebugTrace("[NetLimitRecv]The recv is overlapped.");
    } int iret=0;
      if(*lpNumberOfBytesRecvd<4096)
      {
      DebugTrace("[NetLimitRecv]<4096 don't reduce packet.");
    iret=NextProcTable.lpWSPRecv(s,lpBuffers,dwBufferCount,lpNumberOfBytesRecvd,lpFlags,
    lpOverlapped,lpCompletionRoutine,lpThreadId,lpErrno); for(DWORD i=0;i<dwBufferCount;i++)
    DebugTrace("[NetLimitRecv]the buf klen:%d",lpBuffers[i].len);
    }else
    {
      DebugTrace("[NetLimitRecv]>4096 reduce the packet.");
      DWORD dwRecv=4096;
      char *pbuf=lpBuffers[0].buf;
      DWORD dwRecvCount=0;
      while(dwRecvCount<*lpNumberOfBytesRecvd)
    {
    WSABUF tmp={0};
    tmp.buf=pbuf+dwRecvCount;
    tmp.len=4096;
    DebugTrace("[NetLimitRecv]lpBuffers[0].len is %d",lpBuffers[0].len); if(*lpNumberOfBytesRecvd-dwRecvCount<4096)//如果差值小于4096了,那么就接受最后一个包。
    {
    tmp.len=*lpNumberOfBytesRecvd-dwRecvCount;
    dwRecv=*lpNumberOfBytesRecvd-dwRecvCount;
    } iret=NextProcTable.lpWSPRecv(s,&tmp,1,&dwRecv,lpFlags,
    lpOverlapped,lpCompletionRoutine,lpThreadId,lpErrno);
    if(iret==0&&dwRecv!=0)
    {
    DebugTrace("[NetLimitRecv]4096 limit recv suc!dwRecvCount %d,dwRecv %d",
    dwRecvCount,dwRecv);
    dwRecvCount+=dwRecv;
    }else
    {
    DebugTrace("[NetLimitRecv]recv err %d,dwRecv %d",iret,dwRecv);
    break;
    }
    }
    *lpNumberOfBytesRecvd=dwRecvCount;
    }
    DebugTrace("[NetLimitRecv]The *lpNumberOfBytesRecvd is %d end lpWSPRecv call",
    *lpNumberOfBytesRecvd); return iret;
    }