代码笔记 | TCP 组包和拆包算法

来源:互联网 发布:阿里云邮箱密码找回 编辑:程序博客网 时间:2024/05/17 07:40
 /*************************************文件名: server.cTCP 组包和拆包实现算法  */#include <stdlib.h>#include <sys/types.h>#include <stdio.h>#include <sys/socket.h>#include <linux/in.h>#include <string.h>    #include <stdio.h>#include <stdlib.h>#include <string.h>      #define BUF_SIZE 1024*5    //#define TCP_PACK_DEBUG 1    int main(){      int nBufuseLen=0;       //缓冲区里用到的长度    int nRevOnceLen=0;      //read 一次读到的长度    int nPackLen=0;         //每一包的长度,包括头和两个长度和尾字节    int bufSize=BUF_SIZE;        unsigned char buf[BUF_SIZE];     //read 的缓存        int i=0;        int sfp,nfp; /* 定义两个描述符 */    struct sockaddr_in s_add,c_add;    int sin_size;    unsigned short portnum=6000; /* 服务端使用端口 */    printf("Hello,welcome to my server !\\r\\n");    sfp = socket(AF_INET, SOCK_STREAM, 0);    if(-1 == sfp)    {        printf("socket fail ! \\r\\n");        return -1;    }    printf("socket ok !\\r\\n");    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */    bzero(&s_add,sizeof(struct sockaddr_in));    s_add.sin_family=AF_INET;    s_add.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */    s_add.sin_port=htons(portnum);    /* 使用bind进行绑定端口 */    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))    {        printf("bind fail !\\r\\n");        return -1;    }    printf("bind ok !\\r\\n");    /* 开始监听相应的端口 */    if(-1 == listen(sfp,5))    {        printf("listen fail !\\r\\n");        return -1;    }    printf("listen ok\\r\\n");    //  while(1)    {            //    char buf[1027];        //    int readlen;            sin_size = sizeof(struct sockaddr_in);        /* accept服务端使用函数,调用时即进入阻塞状态,等待用户进行连接,在没有客户端进行连接时,程序停止在此处,           不会看到后面的打印,当有客户端进行连接时,程序马上执行一次,然后再次循环到此处继续等待。           此处accept的第二个参数用于获取客户端的端口和地址信息。            */        nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);        if(-1 == nfp)        {            printf("accept fail !\\r\\n");            return -1;        }        printf("accept ok!\\r\\nServer start get connect from %#x : %#x\\r\\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));        /* 这里使用write向客户端发送信息,也可以尝试使用其他函数实现 */        if(-1 == write(nfp,"hello,welcome to my server \\r\\n",32))        {            printf("write fail!\\r\\n");            return -1;        }    //头0xF9   两个长度字节   数据   尾0xF8        while(1)        {#ifdef TCP_PACK_DEBUG            {                printf("bufSize = %d ,nBufuseLen = %d\\n",bufSize,nBufuseLen);            }#endif            if(bufSize>nBufuseLen)            {                nRevOnceLen=read(nfp,buf+nBufuseLen,bufSize-nBufuseLen);                nBufuseLen=nBufuseLen+nRevOnceLen;    #ifdef TCP_PACK_DEBUG                {                    printf("nBufuseLen = %d>3\\n",nBufuseLen);                }#endif                /*                                printf(" nRevOnceLen data:\\n");                                for(i=0; i<nRevOnceLen; i++)                                {                                    printf(" 0x%x ",buf[i]&0xFF);                                }                                printf(" \\n");                */                }            else            {                printf("buf if full\\n");            }                    while(nBufuseLen>3)            //用到的大于3个字节            {                    /*            printf(" nBufuseLen data:\\n");                            for(i=0; i<nBufuseLen; i++)                            {                                printf(" 0x%x ",buf[i]&0xFF);                            }                            printf(" \\n");                */  #ifdef TCP_PACK_DEBUG                {                    printf("buf[0] = 0x%x \\n",buf[0]&0xFF);                }#endif                if((buf[0]&0xFF)==0xF9)         //头                {                    nPackLen=(buf[1]*256)+buf[2];    #ifdef TCP_PACK_DEBUG                    {                        printf("nBufuseLen=%d ,nPackLen=%d\\n",nBufuseLen,nPackLen);                    }#endif                        if(nBufuseLen>=nPackLen)                //大于和=                    {#ifdef TCP_PACK_DEBUG                        {                            printf("buf[nPackLen-1] = 0x%x \\n",buf[nPackLen-1]&0xFF);                        }#endif                            if((buf[nPackLen-1]&0xFF)==0xF8)                  //尾                        {                            //找到一包数据,所有的数据都往前移动nPackLen个字节#ifdef TCP_PACK_DEBUG                            {                                printf("head 0x%x length %d tail 0x%x \\n", buf[0]&0xFF,nPackLen,buf[nPackLen-1]&0xFF);                            }#endif                                for(i=0; i<nBufuseLen-nPackLen; i++)                            {                                buf[i]=buf[nPackLen+i];                            }                                nBufuseLen=nBufuseLen-nPackLen;      //用到的字节变小了                            //   continue;           //不要read了                        }                        else                        {    #ifdef TCP_PACK_DEBUG                            printf("buf[%d-1]=0x%x,(buf[0]!=0xF8)\\n",nPackLen,(buf[nPackLen-1]!=0xF8));        //这里应该不会执行                            for(i=0; i<5; i++)                            {                                printf(" 0x%x ",buf[i]&0xFF);                            }                            printf(" \\n");#endif                            printf(" (buf[nPackLen-1]&0xFF)!=0xF8 \\n");                            nBufuseLen=0;           //清除错误的包   //这里应该不会执行                                    break;                            }                    }                    else                    {    #ifdef TCP_PACK_DEBUG                        printf(" nBufuseLen<=nPackLen\\n");#endif                        break;                    }                }                else                {                    printf(" (buf[0]!=0xF9)\\n");        //这里应该不会执行                    nBufuseLen=0;           //清除错误的包   //这里应该不会执行                    break;                }            }                /*                        if((0xFF&buf[0])!=0xF2)                        {                            printf("readlen = %d buf  0x%x  0x%x  0x%x \\n",readlen,0xFF&buf[0],0xFF&buf[1],0xFF&buf[2]);                        }                                if(readlen!=1027)                            printf("readlen = %d buf  0x%x  0x%x  0x%x \\n",readlen,0xFF&buf[0],0xFF&buf[1],0xFF&buf[2]);                */        }        //  close(nfp);    }    // close(sfp);    return 0;}

0 0
原创粉丝点击