根据字符信息建立哈夫曼编码并发送给客户端

服务器端线程负责接收来自多个客户的连接请求,接收来自每个客户端的字符信息,并根据这些字符信息,建立霍夫曼编码,最后将该编码发送给客户端;客户端发送连接请求,建立连接,接受霍夫曼编码并且显示。


server:

#include<winsock2.h>
#include<stdio.h>
#include<string.h>
#pragma comment(lib,"ws2_32.lib")

#include<conio.h>
#include<iostream.h>
#include<stdlib.h>
//using namespace std;
#define MAXVALUE 10000  /*权值最大值*/
#define MAXLEAF 30 /*叶子最多个数*/
#define MAXNODE MAXLEAF*2-1    /* 结点数的个数*/
#define MAXBIT 50        /*编码的最大位数*/


typedef struct node   /*结点类型定义*/
{
    char letter;
    int weight;
    int parent;
    int lchild;
    int rchild;
}HNodeType
typedef struct    /*编码类型定义*/
{
    char letter;
    int bit[MAXBIT];
    int start;
}HCodeType;


typedef struct  /*输入符号的类型*/
{
    char s;
    int num;
}lable;


char szHuffman[30]={0};/* 定义二维全局变量数组储存字符 */
char bmHuffman[30][20] = {0}; /* 定义二维全局变量数组用于储存哈夫曼编码字符串 */
int nHuffman = 0; /* 定义一个记录数组中元素个数的全局变量用于回传 */

void HuffmanTree(HNodeType HuffNode[],int n,lable a[])
{
    int i,j,m1,m2,x1,x2,temp1;
    char temp2;
    for (i=0;i<2*n-1;i++)      /*结点初始化*/
    {
        HuffNode[i].letter=0;
        HuffNode[i].weight=0;
        HuffNode[i].parent=-1;
        HuffNode[i].lchild=-1;
        HuffNode[i].rchild=-1;
    }
    for (i=0;i<n-1;i++)
        for (j=i+1;j<n-1;j++) /*对输入字符按权值大小进行排序*/
            if (a[j].num>a[i].num)
            {
                temp1=a[i].num;
                a[i].num=a[j].num;
                a[j].num=temp1;
                temp2=a[i].s;
                a[i].s=a[j].s;
                a[j].s=temp2;
            }

    for (i=0;i<n;i++)
    {
        HuffNode[i].weight=a[i].num;
        HuffNode[i].letter=a[i].s;
    }
    for (i=0;i<n-1;i++)        /*构造huffman树*/
    {
        m1=m2=MAXVALUE;
        x1=x2=0;
        for (j=0;j<n+i;j++)/*寻找权值最小与次小的结点*/
        {
            if (HuffNode[j].parent==-1&&HuffNode[j].weight<m1)
            {
                m2=m1;
                x2=x1;
                m1=HuffNode[j].weight;
                x1=j;
            }
            else if (HuffNode[j].parent==-1&&HuffNode[j].weight<m2)
            {
                m2=HuffNode[j].weight;
                x2=j;
            }
        }
        HuffNode[x1].parent=n+i;
        HuffNode[x2].parent=n+i;         /*权值最小与次小的结点进行组合*/
        HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
        HuffNode[n+i].lchild=x1;
        HuffNode[n+i].rchild=x2;
    }
}

void HuffmanCode(int n,lable a[])
{
nHuffman = 0; /* 初始化元素个数 */

    HNodeType HuffNode[MAXNODE];
    HCodeType HuffCode[MAXLEAF],cd;
    int i,j,c,p;
    HuffmanTree(HuffNode,n,a);

    for (i=0;i<n;i++)     /*按结点位置进行编码*/
    {
        cd.start=n-1;
        c=i;
        p=HuffNode[c].parent;
        while (p!=-1)
        {
            if (HuffNode[p].lchild==c)
                cd.bit[cd.start]=0;
            else cd.bit[cd.start]=1;
            cd.start--;
            c=p;
            p=HuffNode[c].parent;
        }
        for (j=cd.start+1;j<n;j++)    /*储存编码*/
            HuffCode[i].bit[j]=cd.bit[j];
        HuffCode[i].start=cd.start;
    }
    for (i=0;i<n;i++)
    {
        HuffCode[i].letter=HuffNode[i].letter;
        printf("         %c ",HuffCode[i].letter);
szHuffman[nHuffman] = HuffCode[i].letter;
char temp[20] = "";
char c[2] = "";
        for (j=HuffCode[i].start+1;j<n;j++)
{
            printf("%d",HuffCode[i].bit[j]);
c[0] = HuffCode[i].bit[j]+48; /* 给临时字符串赋值,构成哈夫曼编码    */
strcat(temp, c);
}
strcpy(bmHuffman[nHuffman], temp);/* 哈夫曼编码数组赋值 */
nHuffman++; /* 元素个数+1 */
        printf("\n");
    }
}
void main()
{
int len=sizeof(SOCKADDR);
char sendBuf[100];//发送至客户端的字符串
char recvBuf[100];//接受客户端返回的字符串
    lable data[30];
    char *p;
    int i,count=0;
    
WSADATA wsaData;
SOCKET sockServer;
SOCKADDR_IN addrServer;
SOCKET sockClient;
SOCKADDR_IN addrClient;
WSAStartup(MAKEWORD(2,2),&wsaData);
sockServer=socket(AF_INET,SOCK_STREAM,0);
addrServer.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//INADDR_ANY表示任何IP
addrServer.sin_family=AF_INET;
addrServer.sin_port=htons(6000);//绑定端口6000
bind(sockServer,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
 
//Listen监听端
listen(sockServer,5);//5为等待连接数目
printf("服务器已启动:\n监听中...\n");

 for (;;)
    {
//会阻塞进程,直到有客户端连接上来为止
sockClient=accept(sockServer,(SOCKADDR*)&addrClient,&len);
//接收并打印客户端数据
recv(sockClient,recvBuf,100,0);
printf("接收的字符:%s\n",recvBuf);

for (i=0;i<30;i++)
        {
            data[i].s=0;
            data[i].num=0;
        }
        p=recvBuf;
        while (*p)     /*计算字符个数与出现次数(即权值)*/
        {
            for (i=0;i<=count+1;i++)
            {
                if (data[i].s==0)
                {
                    data[i].s=*p;
                    data[i].num++;
                    count++;
                    break;
                }
                else if (data[i].s==*p)
                {
                    data[i].num++;
                    break;
                }
            }
            p++;
        }
        printf("\n");


 HuffmanCode(count,data);
        count=0;
for (i=0; i<nHuffman; i++)
{
// printf("%c  %s\n",szHuffman[i],bmHuffman[i]); /* 测试数组中元素是否正常 */


sendBuf[0] = szHuffman[i]; /* 先回传字符 */
sendBuf[1] = '\0';
send(sockClient,sendBuf,100,0);

  strcpy(sendBuf, bmHuffman[i]); /* 再回传对应的哈夫曼编码 */
send(sockClient,sendBuf,100,0);

}
send(sockClient, "#\0", 100, 0); /* 以#为标志通知客户端接收完毕 */

//关闭socket
closesocket(sockClient);}
WSACleanup();}


client:

#include<winsock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")


void main()
{
char message[100];
printf("  输入需要编码的字符:");
scanf("%s",message);

WSADATA wsaData;
SOCKET sockClient;//客户端Socket
SOCKADDR_IN addrServer;//服务端地址
WSAStartup(MAKEWORD(2,2),&wsaData);
//新建客户端socket
sockClient=socket(AF_INET,SOCK_STREAM,0);
//定义要连接的服务端地址
addrServer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//目标IP(127.0.0.1是回送地址)
addrServer.sin_family=AF_INET;
addrServer.sin_port=htons(6000);//连接端口6000
//连接到服务端
connect(sockClient,(SOCKADDR*)&addrServer,sizeof(SOCKADDR));
//发送数据

send(sockClient,message,strlen(message)+1,0);
printf("\n");
char recvmsg[100];
do
{
recv(sockClient, recvmsg, 100, 0);
if (strcmp(recvmsg,"#\0") == 0)
break;
printf("%s  ", recvmsg);


recv(sockClient, recvmsg, 100, 0);
printf("%s\n", recvmsg);


}while(1);

//关闭socket
closesocket(sockClient);
WSACleanup();}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值