使用zlib库压缩多播数据包

时间:2015-03-10 12:32:22

标签: c zlib

我正在侦听来自多播ip端口的数据包并尝试使用zlib库压缩该数据包,(想知道实时数据包中zlib的压缩率,因为这是我们客户端的要求)。我已经实现了如下的zlib压缩代码,但outputDataBuffer的长度打印不正确,我不知道我错过了什么。

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <zlib.h>

using namespace std;
struct sockaddr_in localSock;
struct ip_mreq group;
int maxpacketsize = 1500;

void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP);
void listenSocket(int &sd,const short &structureSize,const short &compressionType);
void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)

int main(int argc, char *argv[])
{
    int sd = 0;
    char multicastIP[16]="230.0.0.50";
    char interfaceIP[16]="192.168.225.132";
    int multicastPort = 13551;
    short structureSize = 0;
    connectSocket(sd,multicastIP,multicastPort,interfaceIP);
    listenSocket(sd,structureSize);
    return 0;
}

void connectSocket(int &sd,char *multicastIP,int multicastPort,char *interfaceIP)
{
    int reuse = 1;
    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sd < 0)
    {
        perror("Opening datagram socket error");
        exit(1);
    }
    printf("Opening datagram socket....OK.\n");
    if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
    {
        perror("Setting SO_REUSEADDR error");
        close(sd);
        exit(1);
    }
    printf("Setting SO_REUSEADDR...OK.\n");

    memset((char *) &localSock, 0, sizeof(localSock));
    localSock.sin_family = AF_INET;
    localSock.sin_port = htons(multicastPort);
    localSock.sin_addr.s_addr = INADDR_ANY;
    if(bind(sd, (struct sockaddr*)&localSock, sizeof(localSock)))
    {
        perror("Binding datagram socket error");
        close(sd);
        exit(1);
    }
    printf("Binding datagram socket...OK.\n");
    group.imr_multiaddr.s_addr = inet_addr(multicastIP);
    group.imr_interface.s_addr = inet_addr(interfaceIP);
    if(setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
    {
        perror("Adding multicast group error");
        close(sd);
        exit(1);
    }
    printf("Adding multicast group...OK.\n");
}

void compressZlib(char *inputDataBuffer,int inputDataLength,z_stream &defstream)
{

    char *outputDataBuffer = new char[inputDataLength];
    memset(outputDataBuffer,0,inputDataLength);
    defstream.avail_in = (uInt)strlen(inputDataBuffer)+1;
    defstream.next_in = (Bytef *)inputDataBuffer;
    defstream.avail_out = (uInt)sizeof(outputDataBuffer);
    defstream.next_out = (Bytef *)outputDataBuffer;

   if(deflate(&defstream, Z_FINISH) != Z_OK )
   {
       cout<<"Error"<<endl;
   }   
   //printf("%lu  %lu\n", inputDataLength,defstream.total_in);
   printf("%lu  %lu\n", inputDataLength,strlen(outputDataBuffer));
}

void listenSocket(int &sd,const short &structureSize)
{
    char databuf[5000] = "";
    int receivedBytes = 0;
    z_stream defstream;
    defstream.zalloc = Z_NULL ;
    defstream.zfree = Z_NULL;
    defstream.opaque = Z_NULL;
    deflateInit(&defstream, Z_FULL_FLUSH);
    while(1)
    {
        int socklen = sizeof(struct sockaddr_in);
        struct sockaddr_in saddr;
        receivedBytes = recvfrom(sd, databuf, maxpacketsize, 0, (struct sockaddr *)&saddr, (socklen_t*)&socklen);
        if(receivedBytes < 0)
        {
            perror("Reading datagram message error");
            close(sd);
            exit(1);
        }
        compressZlib(databuf,receivedBytes,defstream);
        //compressZlib(databuf1,strlen(databuf1));
        //compressZlib();
        //cout<<receivedBytes<<endl;

    }
    deflateEnd(&defstream);
}

我还使用了compress2()函数,如下所示:

compress2((unsigned char*)outputBuffer,&outputDataLength,(const unsigned char*)inputBuffer,(unsigned long)inputBufferLength,Z_DEFAULT_COMPRESSION);

但这也无法正常工作,outputDataLength始终为0。

1 个答案:

答案 0 :(得分:1)

使用deflate()调用Z_FINISH表示您已经或者已经提供了deflate最后一个输入数据。然后deflate将终止该流。一旦提供了足够的输出空间来写入最后一个压缩数据,这可能是第一次这样的调用,deflate()将返回Z_STREAM_END,而不是Z_OK。然后,deflate()引擎已完成,除非您执行deflateEnd()后跟deflateInit(),或等效且更快,deflateReset(),否则无法再次使用。

看来,您所缺少的是阅读文档后获得的奖励。