Joke Collection Website - Public benefit messages - Mobile CMPP protocol development, why can't the following code receive CMPP?

Mobile CMPP protocol development, why can't the following code receive CMPP?

Where's your code?

Give you some information for your reference:

In fact, when it comes to the development of API, it just encapsulates a communication protocol. So that upper users can focus on their own business modules without knowing the detailed protocol explanation.

For CMPP2.0 protocol, only 8 instructions are needed, which is relatively not very complicated.

CMPP _ connection

= 0x 0000000 1; //Request a connection

CMPP connection RESP

= 0x 8000000 1; //Request connection reply

CMPP _ termination

= 0x 000000002; //Terminate the connection

CMPP _ termination _ resp = 0x80000002;

//Terminate the connection reply

CMPP _ submit

= 0x 000000004; //Submit SMS

CMPP submits RESP

= 0x80000004//

Submit SMS reply

CMPP delivery

= 0x 000000005; //SMS sending

CMPP delivery RESP

= 0x80000005//

Send SMS reply

CMPP _ query

= 0x 000000006; //SMS status query

CMPP query RESP

= 0x80000006//

SMS status query response

CMPP _ cancel

= 0x 000000007; //

Delete SMS

Repcmpp canceled

= 0x80000007// Delete SMS response

CMPP _ active _ test

= 0x 000000008; //

Activation test

CMPP _ active _ test _ resp = 0x80000008;

//Activate test response

It is enough to realize the CMPP protocol module, that is, to realize the above eight instructions. According to the design pattern mentioned above, let's talk about the implementation of the protocol in combination with API development.

For API external interfaces, the general definition format is as follows:

extern " C " _ _ declspec(dll export)int WINAPI active test()

The next step is to realize the function of the interface:

1, establish socket connection

struct sockaddr _ in _ socaddr

_socaddr.sin_family =

AF _ INET

_socaddr.sin_port = htons( _port

);

_ so caddr . sin _ addr . s _ addr = inet _ addr(_ ismg);

Return connection (_soc, (struct

sockaddr *)& amp; _socaddr,sizeof(_ SOC addr));

As for setting the sending timeout, receiving timeout and blocking or non-blocking receiving mode, you can set different target values according to your own needs.

Secondly, log in to the SMS gateway server.

According to CMPP protocol, the main part is authenticator source = MD5 (source _ addr+9 bytes of 0 +shared.

Secret+timestamp), MD5 algorithm can directly find the source program on the Internet, so there is no need to rewrite this content. This part is relatively simple, so I won't write it here.

//Calculate the value of one-way hash function

strcpy( authsrc,_ spid);

char * pos = auth src+strlen(_ spid)+

9 ; 9 bytes of //0

strcpy( pos,_ passwd);

pos+= strlen(_ passwd);

strcpy( pos,_timestamp( timestr

)); //timestamp

pos+= strlen(timestr);

CTX . update((unsigned char *)auth src,(int)( pos -

auth src));

CTX . finalize();

CTX . raw _ digest(msg-& gt; abstract

);

//Copy the string converted into MD5 into the sent data.

Third, submit text messages.

Compared with logging in, submitting SMS is not very complicated. Just copy the data submitted by the client program to the sending window, send it and wait for the gateway to respond. Of course, before receiving the user's data, we can make some appropriate judgments, such as whether the mobile phone number is all numbers, whether it is sent regularly or whether the survival time is correct.

//Note the contents of variable user data and reserved fields:

memcpy(_ pkg-& gt; Data and. Msg, sizeof(CMPP _ submit));

//Copy the last 8 bytes of the reserved data to the appropriate location.

memcpy(

(_ pkg-& gt; Data+nsize-sizeof (

msg.reserve ) - sizeof( CMPP_HEAD)),

msg.reserve

sizeof( msg.reserve))。

Fourth, receive SMS and status.

There are two ways to deal with the short message after receiving it.

1, using the callback function:

Compared with API, this method is relatively simple. Just define the interface function. When the client program is initialized, it will pass in the function pointer of the callback function. When the API receives the short message sent by the short message gateway, it calls the function pointer to pass the relevant parameter data to the client. There is no need to consider queuing or other details.

The callback function I defined in the API is as follows:

typedef int(WINAPI * TProcGetDeliver)(

Character *

msgid,

Unsigned

char * destnumber,

Unsigned

char * serviceid,

Unsigned

char tppid,

Unsigned

char tpudhi,

Unsigned

char msgfmt,

Unsigned

char * srcnumber,

Unsigned

Char delivery,

Unsigned

Chalmsgren,

Unsigned

char * msgcontent,

Unsigned

Char * reserve,

Unsigned

char * stat,

Unsigned

char * submittime,

Unsigned char * donetime);

In the API external interface, just define one parameter as the transfer function pointer, as follows:

extern " C " _ _ declspec(dll export)int WINAPI IFInitInterface(char * ismg,

Unsigned short port, tprocgetdeliver fcltgetdeliver);

FCltGetDeliver is a pointer to the callback function passed by the user. When calling, just use the parameter to open the call directly. As follows:

err = _ fCltGetDeliver((char *)& amp; _msgid,

_ msg-& gt; destnumber,

_ msg-& gt; serviceid,

_ msg-& gt; tppid,

_ msg-& gt; tpudhi,

_ msg-& gt; msgfmt,

_ msg-& gt; Src number,

_ msg-& gt; Delivery,

_ msg-& gt; Msgren,

_ msg-& gt; msgcontent,

_ msg-& gt; Reserve,

_stat,

_submittime,

_donetime

) ;

In this way, all received parameters are successfully passed to the client.

2. The client program calling the API periodically detects and extracts it from the buffer queue:

For the queue method, the API must establish its own buffer queue. For security reasons, this queue must be thread-safe (it can be protected by a critical section). When receiving a distributed message, the data is temporarily stored in the queue:

Int nl = sizeof(CMPP _ hyde)+sizeof (

CMPP _ delivery);

_pushrecqueue( _recpkg,nl);

The following is the _pushrecqueue function;

void WINAPI _ pushrecqueue(void * inval,int nl)

{

char * _ queval = new char[nl+ 1];

memset( _queval,0,sizeof(nl+ 1));

memcpy( _queval,inval,nl);

_queue。 _ push(_ que val);

}

In order to ensure the security of data to the greatest extent, don't receive too much data into the queue. The data put in the queue just waits for the user to use the API interface to take it away. The related interface is similar to the parameters of the callback function, which will not be explained here. Just explain that you can provide an interface for the client to detect whether there is data in the queue that can be received:

extern " C " _ _ declspec(dll export)int

WINAPI has deliver();

It is up to the client to decide whether to get the data.

Verb (abbreviation of verb) sending interface

For API, the most important part is to send data. After connecting with the gateway through the SOCKET socket, send your own data.

Before sending data, assemble the data packet to be sent and copy the data to the sending window. For packets that do not respond, as long as they are sent successfully, they can quit the sending process. For packets waiting for a response, start the clock to detect whether a response is received and return the result to the sending window. Set the sending times. If the first transmission times out, it will be sent again according to the set number of transmissions. If the transmission is unsuccessful, you can set a flag bit to send a link detection flag. If the link detection fails, you should reconnect when the user sends it or directly return the result of broken link.

CMPP _ package * _ pkg =(CMPP _ package *) buf;

int err = API _ E _ UNKNOW _ ERR

If( _soc == INVALID_SOCKET) returns API _ E _ INVALT _ SOC.

while(_ pkg-& gt; n & gt0 )

{

_ pkg-& gt; n = _ pkg-& gt; n - 1

; //transmission times

_ lastactime = time(NULL);

EnterCriticalSection(

& amp_ csec _ SOC);

attempt

{

Error =

send( _soc,buf,len,0);

}

Catch (...)

{

}

LeaveCriticalSection(

& amp_ csec _ SOC);

If (err & ltLen) // transmission fails.

{

Error =

API _ E _ SO _ SENDERR

continue

}

//Don't jump out and respond to the results.

if(_ pkg-& gt; resp == false)

{

err = 0

break

}

//Wait for a response event

…………

}

//If the transmission times out, set the transmission link detection flag to on.

if( err == API_E_SO_OVETIME)

{

_ needacttest = _ needacttest+ 1

}

Return err

Sixth, the receiving interface

As for the received data, it can be received because the amount of interface data for sending short messages is not very large.

Part, explain some functions, so as to reduce the design difficulty. Of course, it is not difficult to receive the data in the buffer at one time and analyze it piece by piece.

For receiving, start a new thread, which can also ensure the timeliness and schedulability of receiving. First, the header information is received to determine the length of the whole packet, and the next packet is not received until the contents of the whole packet are received. Some packets may also have no packet structure, so they can be analyzed after receiving the correct packet header. Its structure is as follows:

//First receive the header part and determine the size and type of the data packet.

err = _ pscoket-& gt; _recv(

_ pscoket-& gt; _rec_window,sizeof(CMPP _ HEAD));

if( err == SOCKET_ERROR || err ==

Api _ e _ invalid _ SOC) to continue;

CMPP _ package * _recpkg = (

CMPP _ PACKAGE *)_ pscoket-& gt; _ rec _ window

if(ntohl(_ rec pkg-& gt; Head. Size)

& gt0 )

{

//Receive the data packet body

_reclen =

0 ; //Receiving length

_ recdatalen = nto HL(_ rec pkg-& gt; head . size)-sizeof(_ rec pkg-& gt; Head);

do

{

Sleep (1);

_ recdatalen = _ recdatalen-_ rec len;

err = _ pscoket-& gt; _recv(

_ rec pkg-& gt; data + _reclen,_ recdatalen);

If (err = = socket _ error || err = = API _ e _ invalt _ SOC) continues;

_ reclen = err

} and (

_ recdatalen-_ rec len & gt; 0 ) ;

If (

_ recdatalen & gt_reclen) to continue;

}

attempt

{

_ pscoket-& gt; _ analysisrecpack(_ rec pkg); //Analyze the contents of the package

}

Catch (...)

{

}

Seven, analysis protocol package

After receiving a complete CMPP protocol packet, it is relatively easy to parse it according to the command word, but we need to pay attention to the problem of transforming network data stream into host data stream.

Unsigned char _ result = 0;;

CMPP _ DELIVER * _ msg =(CMPP _ DELIVER *)_ recp kg-& gt; data

DELIVER _ CONTENT * _ pcont =(DELIVER _ CONTENT

*)_ msg-& gt; msgcontent

if(_ msg-& gt; msglen & lt= 0 )

{

_result = 4

; //The received length error requires the gateway server to resend this packet.

}

else if(_ msg-& gt; msglen & gt200 )

{

_result = 6

; //The received length error requires the gateway server to resend this packet.

}

else if(_ msg-& gt; Delivery! = 0 | | _ msg->; Delivery! =

1 )

{

_result = 1

; //The received protocol format is wrong, and the gateway server is required to resend this packet.

}

//Return the error message directly.

if(_ result & gt; 0 )

{

_deliverresp(

_ rec pkg-& gt; head.seqid,_ msg-& gt; msgid,_ result);

Return;

}

if( _fCltGetDeliver)

{

//If the client program uses the callback function to get the received short message or status, call back.

//Transfer function for transferring data

……………

}

other

{

//If the client uses the method of extracting from the queue by itself, it will directly push the data to the queue// column for the user to extract.

………….

}