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.
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:
#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);
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;
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;
bit_offset += 24;
apbuilder_set_bits(buf, bit_offset, 4, EXAMPLE_SUBMIT);
bit_offset = 0;
apbuilder_set_bits(buf, bit_offset, 24, cur_bits/8);
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){
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:
#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;
_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.