About Union
The CMPP-defined data packets are most efficient to be processed using the Union in C language, because receiving and sending are a byte array, union can be used to conveniently Convert Between the byte array and the data packet structure. C # itself does not support union, but can use the P/invoke (platform encapsulation and call) mechanism to implement a structure similar to union.
When defining CMPP data packets, I defined the init function (used to convert a byte array into a data packet structure) and the getbuffer function (used to convert a data packet structure to a byte array) for each data packet structure ), it was mainly because I was not familiar with the P/invoke mechanism at the time.
Using the init and getbuffer functions is much less efficient than using the combination, but the system performance is quite stable during stress testing. If you are interested, you can try to use a combination to implement CMPP data packets.
Using system;
Using system. runtime. interopservices;
Namespace tiray. SMS
{
Public struct data_package
{
Public uint32 command;
Public uint32 sequenceid; // serial number
Public object data; // data
Public datetime sendtime; // data packet sending time
Public int sendcount; // Number of sendings
Public int status; // data packet status 0 -- null, 1 -- to be sent, 2 -- sent
}
# Region enums
Public Enum sms_state
{
Sp_connect, active_test, active_test_response, submit, submit_response, deliver, deliver_response, report, sp_disconnect,
Sp_connect_error, active_test_error, active_test_response_error, submit_error, submit_response_error, deliver_error, deliver_response_error, sp_disconnect_error, unknow_error
}
Public Enum Coding
{
ASCII = 0, binary = 4, ucs2 = 8, GBK = 15
}
# Endregion
# Region cmpp30 data packages
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_head
{
Public uint32 totallength;
Public uint32 commandid;
Public uint32 sequenceid;
Public byte [] getbuffer ()
{
Byte [] buffer = new byte [Marshal. sizeof (this)]; // 12;
Byte [] temp = NULL;
Temp = bitconverter. getbytes (totallength );
Buffer [3] = temp [0];
Buffer [2] = temp [1];
Buffer [1] = temp [2];
Buffer [0] = temp [3];
Temp = bitconverter. getbytes (commandid );
Buffer [7] = temp [0];
Buffer [6] = temp [1];
Buffer [5] = temp [2];
Buffer [4] = temp [3];
Temp = bitconverter. getbytes (sequenceid );
Buffer [11] = temp [0];
Buffer [10] = temp [1];
Buffer [9] = temp [2];
Buffer [8] = temp [3];
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_connect
{
Public cmpp_head head;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 6)]
Public String sourceaddress;
[Financialas (unmanagedtype. byvalarray, sizeconst = 16)]
Public byte [] authenticatorsource;
Public byte version;
Public uint32 timestamp;
Public byte [] getbuffer ()
{
Byte [] temp = NULL;
Int IPOs = 0;
Head. totallength = 39;
Byte [] buffer = new byte [39];
Byte [] headbuffer = This. Head. getbuffer ();
Array. Copy (headbuffer, 0, buffer, 0, headbuffer. Length );
IPOs = IPOs + headbuffer. length;
Temp = utility. encode (sourceaddress, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 6;
Array. Copy (authenticatorsource, 0, buffer, IPOs, authenticatorsource. Length );
IPOs = IPOs + authenticatorsource. length;
Buffer [IPOs] = version;
IPOs ++;
// Temp = bitconverter. getbytes (timestamp );
Temp = utility. inttonetbytes (timestamp );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_connect_resp
{
Public cmpp_head head;
Public uint32 status;
[Financialas (unmanagedtype. byvalarray, sizeconst = 16)]
Public byte [] authenticatorismg;
Public byte version;
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_submit
{
Public cmpp_head head;
Public uint64 msg_id;
Public byte pk_total;
Public byte pk_number;
Public byte registered_delivery;
Public byte msg_level;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 10)]
Public String service_id;
Public byte fee_usertype;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 32)]
Public String fee_terminal_id;
Public byte fee_terminal_type;
Public byte tp_pid;
Public byte tp_udhi;
Public byte msg_fmt;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 6)]
Public String msg_src;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 2)]
Public String feetype;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 6)]
Public String feecode;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 17)]
Public String valid_time;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 17)]
Public String at_time;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 21)]
Public String src_id;
Public byte destusr_tl;
Public String [] dest_terminal_id;
Public byte dest_terminal_type;
Public byte msg_length;
Public String msg_content;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 20)]
Public String linkid;
Public byte [] getbuffer ()
{
Int IPOs = 0;
Msg_length = (byte) Utility. countlength (msg_content.tostring (), (coding) msg_fmt );
Head. totallength = (uint32) (163 + 32 * destusr_tl + msg_length );
Byte [] buffer = new byte [head. totallength];
Byte [] temp = NULL;
Byte [] headbuffer = This. Head. getbuffer ();
Array. Copy (headbuffer, 0, buffer, 0, headbuffer. Length );
IPOs = headbuffer. length;
Temp = utility. inttonetbytes (msg_id );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Buffer [IPOs] = pk_total;
IPOs ++;
Buffer [IPOs] = pk_number;
IPOs ++;
Buffer [IPOs] = registered_delivery;
IPOs ++;
Buffer [IPOs] = msg_level;
IPOs ++;
Temp = utility. encode (service_id, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 10;
Buffer [IPOs] = fee_usertype;
IPOs ++;
Temp = utility. encode (fee_terminal_id, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 32;
Buffer [IPOs] = fee_terminal_type;
IPOs ++;
Buffer [IPOs] = tp_pid;
IPOs ++;
Buffer [IPOs] = tp_udhi;
IPOs ++;
Buffer [IPOs] = msg_fmt;
IPOs ++;
Temp = utility. encode (msg_src, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 6;
Temp = utility. encode (feetype, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 2;
Temp = utility. encode (feecode, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 6;
Temp = utility. encode (valid_time, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 17;
Temp = utility. encode (at_time, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 17;
Temp = utility. encode (src_id, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 21;
Buffer [IPOs] = destusr_tl;
IPOs ++;
For (INT I = 0; I <destusr_tl; I ++)
{
Temp = utility. encode (dest_terminal_id [I], coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + 32;
}
Buffer [IPOs] = dest_terminal_type;
IPOs ++;
Buffer [IPOs] = msg_length;
IPOs ++;
Temp = utility. encode (msg_content, (coding) msg_fmt );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Temp = utility. encode (linkid, coding. ASCII );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_submit_resp
{
Public cmpp_head head;
Public uint64 msg_id;
Public uint32 result;
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_deliver
{
Public cmpp_head head;
Public uint64 msg_id;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 21)]
Public String dest_id;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 10)]
Public String service_id;
Public byte tp_pid;
Public byte tp_udhi;
Public byte msg_fmt;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 10)]
Public String src_terminal_id;
Public byte src_terminal_type;
Public byte registered_delivery;
Public byte msg_length;
Public String msg_content;
[Financialas (unmanagedtype. byvaltstr, sizeconst = 20)]
Public String linkid;
Public bool Init (byte [] buffer)
{
Int IPOs = 0;
Bool Bok = true;
Try
{
Msg_id = (uint64) bitconverter. touint64 (buffer, 0 );
IPOs = IPOs + 8;
Dest_id = utility. Decode (buffer, IPOs, 21, coding. ASCII );
IPOs = IPOs + 21;
Service_id = utility. Decode (buffer, IPOs, 10, coding. ASCII );
IPOs = IPOs + 10;
Tp_pid = buffer [IPOs];
IPOs ++;
Tp_udhi = buffer [IPOs];
IPOs ++;
Msg_fmt = buffer [IPOs];
IPOs ++;
Src_terminal_id = utility. Decode (buffer, IPOs, 32, coding. ASCII );
IPOs = IPOs + 32;
Src_terminal_type = buffer [IPOs];
IPOs ++;
Registered_delivery = buffer [IPOs];
IPOs ++;
Msg_length = buffer [IPOs];
IPOs ++;
If (registered_delivery = 0) // is a short message.
{
Msg_content = utility. Decode (buffer, IPOs, msg_length, (coding) msg_fmt );
}
Else // status report, first converted to base64 string Storage
Msg_content = convert. tobase64string (buffer, IPOs, msg_length );
IPOs = IPOs + msg_length;
Linkid = utility. Decode (buffer, IPOs, 20, coding. ASCII );
}
Catch
{
Bok = false;
}
Return Bok;
}
Public cmpp_report getreport ()
{
Cmpp_report report = new cmpp_report ();
If (registered_delivery = 1) // status report
{
Byte [] bytes = convert. frombase64string (msg_content );
If (Bytes! = NULL) & (bytes. length> 0 ))
Report. INIT (bytes );
}
Return report;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_report
{
Public uint64 msg_id;
Public String Stat;
Public String submit_time;
Public String done_time;
Public String dest_terminal_id;
Public uint32 smsc_sequence;
Public bool Init (byte [] buffer)
{
Int IPOs = 0;
Bool Bok = true;
Try
{
Msg_id = (uint64) Utility. netbytestoint (buffer, 0, 8 );
IPOs + = 8;
Stat = utility. Decode (buffer, IPOs, 7, coding. ASCII );
IPOs + = 7;
Submit_time = utility. Decode (buffer, IPOs, 10, coding. ASCII );
IPOs + = 10;
Done_time = utility. Decode (buffer, IPOs, 10, coding. ASCII );
IPOs + = 10;
Dest_terminal_id = utility. Decode (buffer, IPOs, 32, coding. ASCII );
IPOs + = 32;
Smsc_sequence = (uint32) Utility. netbytestoint (buffer, IPOs, 4 );
}
Catch
{
Bok = false;
}
Return Bok;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_deliver_resp
{
Public cmpp_head head;
Public uint64 msg_id;
Public uint32 result;
Public byte [] getbuffer ()
{
Int IPOs = 0;
Head. totallength = (uint32) Marshal. sizeof (this );
Byte [] buffer = new byte [head. totallength];
Byte [] temp = NULL;
Byte [] headbuffer = This. Head. getbuffer ();
Array. Copy (headbuffer, 0, buffer, 0, headbuffer. Length );
IPOs = headbuffer. length;
Temp = bitconverter. getbytes (msg_id );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Temp = utility. inttonetbytes (result );
Array. Copy (temp, 0, buffer, IPOs, temp. Length );
IPOs = IPOs + temp. length;
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_active_test_resp
{
Public cmpp_head head;
Public byte reserved;
Public byte [] getbuffer ()
{
Int IPOs = 0;
Head. totallength = (uint32) Marshal. sizeof (this );
Byte [] buffer = new byte [head. totallength];
Byte [] headbuffer = This. Head. getbuffer ();
Array. Copy (headbuffer, 0, buffer, 0, headbuffer. Length );
IPOs = headbuffer. length;
Buffer [IPOs] = reserved;
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_cancel
{
Public cmpp_head head;
Public uint64 msgid;
Public byte [] getbuffer ()
{
Byte [] buffer = new byte [Marshal. sizeof (this)];
Byte [] headbuffer = This. Head. getbuffer ();
Int IPOs = headbuffer. length;
Array. Copy (headbuffer, 0, buffer, 0, IPOs );
Byte [] temp = bitconverter. getbytes (msgid );
Buffer [IPOs + 7] = temp [0];
Buffer [IPOs + 6] = temp [1];
Buffer [IPOs + 5] = temp [2];
Buffer [IPOs + 4] = temp [3];
Buffer [IPOs + 3] = temp [4];
Buffer [IPOs + 2] = temp [5];
Buffer [IPOs + 1] = temp [6];
Buffer [IPOs + 0] = temp [7];
Return buffer;
}
}
[Structlayout (layoutkind. Sequential, pack = 1, charset = charset. ANSI)]
Public struct cmpp_cancel_resp
{
Public cmpp_head head;
Public uint32 successid;
}
# Endregion
}
[To be continued]