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?
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.
………….
}
- Related articles
- Happy birthday to my classmates.
- A selection of wedding invitations for the Spring Festival.
- After the netizen lost his mobile phone, a photo of Iran appeared. What does this mean?
- Can the Taobao payment success page not prompt?
- Minsheng Trust overdue announcement SMS
- What is it like to have a crush on someone for seven years?
- What scams and risks do strangers usually have when they make phone calls?
- How to chase the communication skills of Leo girls
- Activity summary template for participating in speech contest
- What does it mean to transfer online loans to accounts?