Click here to Skip to main content
15,891,529 members
Articles / Desktop Programming / MFC

How to auto-generate communication protocol source code

Rate me:
Please Sign up or sign in to vote.
2.00/5 (4 votes)
1 Nov 2007CPOL1 min read 27.9K   865   13   3
This article explains how to auto-generate communication protocol source code.

Introduction

This article explains how to auto generate communication protocol source code to avoid complicated network programming.

Background

As we all know, network programming and debugging a network communication protocol is very complicated, and is a very hard job to do. Specially if the protocol you want to implement can run on Windows, Linux, and Unix platforms. Tuning a network communication protocol performance is another very hard job to do.

Using Auto Protocol Builder, you can easily and automatically build TCP-based or UDP-based network protocol source code for client/server sides. It generates pure platform independent C source code to ensure high performance on Windows, Linux, and Unix platforms. The auto protocol struct diagram helps protocol design. There is platform independent C source code and a platform independent network programming library to support all fixed or variant length binary protocols.

How to Use

What you need to do is just create a project and add fields or packets in your protocol. After this, you just click the Generate button. You will see the generated communication protocol source code.

C++
int main(int argc, char ** argv)
{
    int        result = 0;
    int        i = 0;
    int        len = 0;
    unsigned int tid;
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    example_trans conn;

    example_submit submit;

    wVersionRequested = MAKEWORD (2, 2);
    err = WSAStartup (wVersionRequested, &wsaData);

    memset(&conn,0,sizeof(conn));

    _beginthreadex(NULL, 0, server_thread_func, NULL, 0, &tid);

    result = apbuilder_create_tcp_socket(&(conn.socket));
        if(result != 0){
        printf("apbuilder_create_tcp_socket error is %d\n", result);
        return 0;
    }

    apbuilder_sleep(1000);

    result = apbuilder_connect(conn.socket, "127.0.0.1",4321);
    if(result != 0){
        printf("apbuilder_connect result is %d\n", result);
        return 0;
    }

    while(1){
        memset(&submit, 0, sizeof(example_submit));
        submit.head.command_length = 1;
        submit.head.command_type = 1;
        submit.head.command_sequence = 1;
        submit.bit1 = 1;
        submit.bit2 = 1;

        result = example_submit_send(&conn,&submit, 30);
        if(result != 0){
            printf("smpp_submit_send result is %d\n", result);
            return result;
        }
        apbuilder_sleep(1000);
    }
}

Here is the communication API code:

C++
#include <stdio.h>
#include <stdlib.h>
#include "apbuilder_socket.h"
#include "apbuilder_util.h"
#include "example_api.h"

static int read_packet(example_trans *trans, example_packet *pk, 
                       int timeout, int *body_len);
static int parse_submit(example_trans *trans, example_packet *hpk, 
                        example_submit *pk, int body_len);

int WINAPI example_submit_send(example_trans *trans, example_submit *pk, int timeout)
{
    unsigned char dw1 = 0;
    unsigned short int dw2 = 0;
    unsigned int dw4 = 0;
    apbuilder_int64_t dw8 = 0;
    int len = 0;
    int i = 0;
    int bit_offset = 0;
    int cur_bits = 0;
    int buf_size = 0;
    int result = 0;
    int header_len = 0;
    int body_len = 0;

    char *buf = NULL;
    assert(trans != NULL);
    buf_size += sizeof(example_submit);
    buf_size += 1;

    buf = (char *)malloc(buf_size);
    if(buf == NULL)
        return ENOMEM;

    memset(buf, 0, buf_size);

    //handle protocol head
    apbuilder_set_bits(buf, cur_bits, 24, pk->head.command_length);
    cur_bits += 24;

    apbuilder_set_bits(buf, cur_bits, 4, pk->head.command_type);
    cur_bits += 4;

    apbuilder_set_bits(buf, cur_bits, 4, pk->head.command_sequence);
    cur_bits += 4;

    header_len = cur_bits/8;

    //handle protocol packet
    apbuilder_set_bits(buf, cur_bits, 4, pk->bit1);
    cur_bits += 4;

    apbuilder_set_bits(buf, cur_bits, 4, pk->bit2);
    cur_bits += 4;

    body_len = cur_bits/8-header_len;

    //assign packet type
    bit_offset += 24;
    apbuilder_set_bits(buf, bit_offset, 4, EXAMPLE_SUBMIT);

    //assign packet total length
    bit_offset = 0;
    apbuilder_set_bits(buf, bit_offset, 24, cur_bits/8);

    //send data
    timeout = timeout*APBUILDER_USEC_PER_SEC;
    result = apbuilder_socket_send_all(trans->socket, 
                       buf, cur_bits/8, &len, timeout);

    if(buf)
        free(buf);

    if(result != 0)
        return result;

    return 0;
}

static int read_packet(example_trans *trans, example_packet *pk, 
                       int timeout, int *body_len)
{
    int result = 0;
    char buf[sizeof(example_packet)];
    int len = 0;
    int cur_bits = 0;
    int i = 0;

    assert(trans != NULL);
    assert(pk != NULL);

    memset(buf, 0, sizeof(buf));
    timeout = timeout*APBUILDER_USEC_PER_SEC;


    result = apbuilder_socket_recv_all(trans->socket, 
                       buf+cur_bits/8, 4, &len, timeout);
    if(result != 0)
        return result;

    pk->pk_head.command_length = apbuilder_get_bits(buf, cur_bits, 24);
    cur_bits += 24;
    pk->pk_head.command_type = apbuilder_get_bits(buf, cur_bits, 4);
    cur_bits += 4;
    pk->pk_head.command_sequence = apbuilder_get_bits(buf, cur_bits, 4);
    cur_bits += 4;

    if((pk->pk_head.command_length-cur_bits/8) != 0){
        result = apbuilder_socket_recv_all(trans->socket, buf+cur_bits/8, 
                       pk->pk_head.command_length-cur_bits/8, &len, timeout);
        if(result != 0)
            return result;
    }

    *body_len = pk->pk_head.command_length - cur_bits/8;
    memcpy(pk->pk_body, buf+cur_bits/8, *body_len);
    return 0;
}

static int parse_submit(example_trans *trans, example_packet *hpk, 
                        example_submit *pk, int body_len)
{
    int result = 0;
    int len = 0;
    int cur_bits = 0;
    int i = 0;

    assert(trans != NULL);
    assert(pk != NULL);

    pk->bit1 = apbuilder_get_bits(hpk->pk_body, cur_bits, 4);
    cur_bits += 4;
    if(cur_bits/8 > body_len)
        return -1;

    pk->bit2 = apbuilder_get_bits(hpk->pk_body, cur_bits, 4);
    cur_bits += 4;
    if(cur_bits/8 > body_len)
        return -1;

    if(cur_bits/8 != body_len){
        //invalid packet
        return -1;
    }

    return 0;
}

int WINAPI example_read_packet(example_trans *trans, example_upacket *upk, int timeout)
{
    int result = 0;
    int body_len = 0;
    example_packet pk;

    memset(&pk, 0, sizeof(pk));

    result = read_packet(trans, &pk, timeout, &body_len);
    if(result != 0)
        return result;

    switch(pk.pk_head.command_type){
    case EXAMPLE_SUBMIT:
        upk->submit.head = pk.pk_head;
        upk->command_type = pk.pk_head.command_type;
        return parse_submit(trans, &pk, &(upk->submit), body_len);
        break;
    default:
        break;
    }

    return 0;
}

void WINAPI example_print_head(example_head *head)
{
    int i = 0;
    int len = 0;
    char temp[1024];

    printf("DDD:head.command_length is %d\n", head->command_length);
    printf("DDD:head.command_type is %d\n", head->command_type);
    printf("DDD:head.command_sequence is %d\n", head->command_sequence);
}

void WINAPI example_print_submit(example_submit *pk)
{
    int i = 0;
    int len = 0;
    char temp[1024];

    printf("DDD:pk.bit1 is %d\n", pk->bit1);
    printf("DDD:pk.bit2 is %d\n", pk->bit2);
}

The header file:

C++
#ifndef EXAMPLE_API_H
#define EXAMPLE_API_H

#ifdef _WIN32
#include <winsock2.h />
#endif

#include <assert.h>
#include <errno.h />

#include "apbuilder_type.h"

#ifdef __cplusplus
extern "C"{
#endif

#define EXAMPLE_MAX_PK_SIZE 18

enum{
    EXAMPLE_SUBMIT = 0x00000001,
};

typedef struct example_head{
    unsigned int command_length;
    unsigned char command_type;
    unsigned char command_sequence;
}example_head;

typedef struct example_packet{
    example_head pk_head;
    char pk_body[EXAMPLE_MAX_PK_SIZE+1];
}example_packet;

typedef struct example_submit{
    example_head head;
    unsigned char bit1;
    unsigned char bit2;
}example_submit;

typedef struct example_trans{
    apbuilder_socket_t socket;
}example_trans;

typedef struct example_upacket{
    unsigned char command_type;
    union{
        example_submit submit;
    };
}example_upacket;

//timeout:waitting seconds when sending or reading message
//message type field and message length field will be set auto 
//by the interface,others fields should be set by api user
_declspec(dllexport) int WINAPI example_submit_send(example_trans *trans, 
                                example_submit *pk, int timeout);

_declspec(dllexport) int WINAPI example_read_packet(example_trans *trans, 
                                example_upacket *pk, int timeout);

_declspec(dllexport) void WINAPI example_print_head(example_head *head);

_declspec(dllexport) void WINAPI example_print_submit(example_submit *pk);


#ifdef __cplusplus
}
#endif

#endif

As you can see, this tool is very easy to use to auto generate communication protocol source code. Actually, you don't need to program ever :) If you want to get more information, you can visit www.upredsun.com.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionThis is a bit akward code Pin
djhenrya18-Apr-12 19:34
djhenrya18-Apr-12 19:34 
Questioncan i make a UDP protocol with it? Pin
MrZhangjianliang16-Nov-07 23:53
MrZhangjianliang16-Nov-07 23:53 
AnswerRe: can i make a UDP protocol with it? Pin
upredsun17-Nov-07 2:40
upredsun17-Nov-07 2:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.