Linux 网络开发必学课程(四)应用层协议设计与实现、应用层协议解析模块

本文详细介绍了Linux网络开发中应用层协议的设计与实现,包括TCP应用编程的问题、协议设计原则、协议解析模块的实现。通过编程实验展示了如何从内存和文件描述符中实时解析协议消息,解决数据粘连问题,确保数据的正确传输和解释。
摘要由CSDN通过智能技术生成

8应用层协议设计与实现

① 问题:下面的代码输出什么?为什么

        Receive: ABC

② 小知识

  • 发送缓冲区
    • 数据先进入发送缓冲区,之后由操作系统送往远端主机
  • 接收缓冲区
    • 远端数据被操作系统接收后放入接收缓冲区
    • 之后应用程序从接收缓冲区读取数据

         

 TCP应用编程中的问题”   数据接收端无法知道数据的发送方式!!!

        

④ 网络编程中的期待

  • 每次发送一条完整的消息,每次接收一条完整的消息
  • 即使接收缓冲区中有多条消息,也不会出现消息粘连(粘包)
  • 消息中涵盖了数据类型数据长度等信息

⑤ 应用层协议设计

  • 什么是协议?
    • 协议是通信双方为数据交换而建立的规则标准约定的集合
  • 协议对数据传输的作用
    • 通信双方根据协议能够正确收发数据
    • 通信双方根据协议能够解释数据的意义

⑥ 协议设计示例

  • 目标:设计可用于数据传输的协议
  • 完整消息包含
    • 数据头:数据类型(即:数据区用途,固定长度)
    • 数据长度:数据区长度(固定长度)
    • 数据区:字节数据(变长区域)

⑦ 协议设计示例

        

 因此:

  • 消息至少12个字节(消息头+数据长度)
  • 通过计算消息的总长度,能够避开数据粘连的问题

        

编程实验:应用层协议设计与实现

message.c

#include "message.h"
#include <malloc.h>
#include <string.h>

Message* Message_New(unsigned short type, unsigned short cmd, unsigned short index, unsigned short total, const char* payload, unsigned int length)
{
    Message* ret = malloc(sizeof(Message) + length);

    if( ret  )
    {
        ret->type = type;
        ret->cmd = cmd;
        ret->index = index;
        ret->total = total;
        ret->length = length;

        if( payload )
        {
            memcpy(ret + 1, payload, length);
        }
    }

    return ret;
}

message.h

#ifndef MESSAGE_H
#define MESSAGE_H

typedef struct message
{
    unsigned short type;
    unsigned short cmd;
    unsigned short index;
    unsigned short total;
    unsigned int length;
    unsigned char payload[];
} Message;

Message* Message_New(unsigned short type,
                     unsigned short cmd,
                     unsigned short index,
                     unsigned short total,
                     const char* payload,
                     unsigned int length);

#endif

client.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "message.h"

int main()
{
    int sock = 0;
    struct sockaddr_in addr = {0};
    int len = 0;
    char buf[128] = {0};
    char input[32] = {0};
    int r = 0;
    Message* pm = NULL;

    sock = socket(PF_INET, SOCK_STREAM, 0);

    if( sock == -1 )
    {
        printf("socket error\n");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_port = htons(8888);

    if( connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1 )
    {
        printf("connect error\n");
        return -1;
    }

    printf("connect success\n");

    pm = Message_New(0, 0, 1, 3, "A", 1);

    send(sock, pm, sizeof(Message) + 1, 0);

    pm = Message_New(0, 0, 2, 3, "B", 1);

    send(sock, pm, sizeof(Message) + 1, 0);

    pm = Message_New(0, 0, 3, 3, "C", 1);

    send(sock, pm, sizeof(Message) + 1, 0);

    close(sock);

    return 0;
}

server.c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值