找回密码
 注册
关于网站域名变更的通知
查看: 454|回复: 2
打印 上一主题 下一主题

SMS中用Unicode编码发送中文

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-7-5 07:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
SMS中用Unicode编码发送中文

" g2 L. [9 G- p. ^
4 i" a. L; \# e8 s4 L% ~1 t作者: 陈轶飞 : t$ o8 H( n! W- G# B

, n8 `  Z6 D* \( {关键词: SMS、PDU、Unicode、GB2312、linux、编码转换
; j) N. K% z! i8 J
8 r  i8 R' @$ v8 O6 {, ?; T6 GSMS是由Esti 所制定的一个规范(GSM 03.40 和 GSM 03.38)。有两种方式来发送和接收SMS消息:文本模式或者PDU(protocol description unit)模式。文本模式只能发送普通的ASCII字符,而要发送图片、铃声、其它编码的字符(如中文)就必须采用PDU模式。
5 O' |! L) |! Z+ q5 ^: B& ~PDU模式中,可以采用三种编码方式来编码要发送的内容,分别是 7-bit编码、8-bit编码、16-bit编码。7-bit编码用于发送普通的ASCII字符;8-bit编码通常用于发送数据消息,比如图片和铃声等;而16-bit编码用于发送Unicode字符。在这三种编码方式下,可以发送的较大字符数分别是 160、 140、 70。
4 t/ r4 d0 Q7 {; o% ^3 A" D- [+ ?若要发送中文(或日文等),必须采用PDU模式的Unicode编码方式。
* B* W5 f7 a* p我最近参与了一个在linux下收发短信的项目。其中,需要实现中文的发送和接收。由于原来没有中文编码、Unicode编码的经验,所以查了一些资料,也在一些论坛上提了一些问题。现在把它整理出来,希望对以后再做类似项目的朋友有个帮助。我写的比较简单,关于PDU的规范,可以看这里:http://www.ascend-tech.com.cn/sustain/SMS_PDU-mode.pdf ,或者去wavecom的网站上找找看。 # n. p0 G' w8 ^. ^( P* s
) W% F7 Q7 \9 ~
1、 GB2312 编码到Unicode 编码的转换
9 f$ C5 ]$ P; n# O  n- p. `" u0 C- R- g
在 Redhat 7.3系统上,默认是用GB2312编码保存中文字符的(对于中英文混合的文本也是如此)。所以首先需要把 GB2312 编码的字符串转换到 Unicode编码的字符串。GB2312编码是一种多字节编码方式,对于中文,用2个字节表示,对于英文,用1个字节表示,就是英文的ascii码。(注:我没有仔细看过GB2312编码的规范,以上理解是实际开发中得出来的,不能保证正确性)。Unicode编码是双字节编码方式,对所有字符,都采用2个字节编码。在linux平台上,GB2312编码到Unicode编码的转换,可以有三种实现方式(或者更多): , p- [( y9 [% [& ]$ e: |
1)、用 mbstowcs () 函数。就是多字节编码到宽字符的转换。我试过它,可以正确的转换,但是这个函数可能不是很可靠。 - T+ ?1 |8 A* l; ~
0 @/ H. o$ r: t% ?
2)、用 GB2312 à Unicode 的转换表,手动查表转换。网上有这样的转换表,你需要对每一个GB2312字符,根据它是中文字符还是英文字符,分别转换。
* Y: D: F1 K$ p  ~3 {/ a( z1 o9 Y
- \! R' o6 q) w. v3)、用 iconv () 函数。这可能是linux上的标准的方法,不仅可以转换GB2312到Unicode,还可以在任意的两种编码之间转换(前提是linux系统要支持这些编码)。 , O/ T+ x" d$ k7 b$ D
首先要用 iconv_open(), 打开一个转换句柄,指定两种转换前的编码和转换后的编码。 " {9 Q+ o; O" ^
然后用 icnov() 作转换。较后用 iconv_close()关闭句柄,释放资源。 5 s' s; ?7 L1 v
* {2 o/ r; J* B4 E. T

1 c- C# F  s: m9 {: f+ }# m9 i5 p/ _& {3 e: A; W
#include <iconv.h> ; t: y: g& t, B% s2 C

3 s1 ~; }. `* z0 i0 y+ G#define BUFLEN 200
9 `8 K" F/ s2 M' t3 fchar inbuf[BUFLEN];
; J! d3 P- _7 z* |6 e6 B- @& h) xchar outbuf[BUFLEN]; - |" N0 E( W( J; @
char* pin = inbuf;
3 ^# X  L7 J; {. q7 q3 C( Schar* pout = outbuf; 8 H9 h( y5 M  d5 Y/ A7 D

* K8 y( G. N6 M+ ]6 @, ^9 L…打开文件,读入GB2312数据到inbuf,数据长度为 len ) v& f$ c! g4 a

9 y6 d% O5 |; g. ^& oint inleft = len; 3 L( ?' {8 q0 M  l$ [! }
int outleft = BUFLEN;
4 t% p1 k' ~. U, P0 R, S
. K2 T9 F3 f( z& niconv_t cd;
  J- Q' ?) W7 e& C  ?2 F( W5 Vif((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1)
" I2 z6 w; w8 r, ]; Wreturn –1; : I) |; R/ @! U0 q5 I: O, r* I
if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1) # F, w$ X7 t, m5 r& l$ L
return –1; ! U3 Y& |/ S/ L3 K  K; w
iconv_close(cd); 1 V* r+ T+ S6 Q, g0 n- q

( x; ]1 l2 ~) w& O使用 iconv () 时,需要注意参数的使用,inleft 是输入缓冲区数据数据长度,outleft是输出缓冲区大小。(需要保证输出缓冲区足够大)。 4 p5 h- Z. I# k$ R0 K0 s
转换以后,outleft 是outbuf中空闲空间的大小,所以 BUFLEN-outleft 才是真正的Unicode数据长度。
( K4 j" ]5 X& V+ c注意:不论是GB2312编码,还是Unicode编码,在内存中都是一些字节序列,所以我们可以统一用 类型为 char(或者unsigned char)的字符数组来保存。所以,BUFLEN-outleft 是 字符(char)个数,而不是Unicode字符个数。 + \7 }! P' F7 q& C9 n$ D* X
$ O! `! F: b2 ?% f. L$ i* y2 o

% ^* v  ?$ I1 f" @2、 Unicode 编码到 16-bit 编码的转换 2 f$ d9 X3 E- z2 O; [, P1 b; ?' X

; Q6 n* u2 k: C2 s, C8 \在得到 Unicode编码以后,还需要转换到 PDU 的16-bit 编码,才可以正确的发送。在这个转换过程中,需要注意两点: ; y* `, I+ H( ]6 i4 h( A! Z! \' I
1)、Unicode 编码最开始的 0xFEFF标志要被去除,在0xFEFF之后的内容,才是真正的Unicode字符。(至于为什么有这个0xfeff标志,知道的朋友告诉我一声,呵呵)。 , ~8 g3 `, W' e8 P$ V6 o6 Z

* D0 s2 q4 ?- S  s, X2)、Unicode 是双字节字符,由于我的系统是小端字节序(little-endian),也就是说,在存储的时候,是先低位,后高位,例如“中”的Unicode编码是 0x4E2D,存储的时候是 2D4E,在转换到 16-bit编码的时候,要注意这个顺序的不同。当然,如果你的系统是大端字节序(big-endian),那么就不用这样做了。
2 U: R' d: q6 v5 ^' ^3 f
3 v8 w' s# J# U1 v4 AOK,关于如何将 0x4E2D 的Unicode编码转换到 “4E2D” 的16-bit编码,我就不多写了。
* J/ b! u) s4 c0 i" s$ q/ f" W: I) J
! m# r* m6 K8 i2 \5 x& I
, }& V% Z# q5 u- ~# \4 _5 }2 H3、正确计算16-bit 编码的消息体长度
' D; u7 ^' _$ }/ @6 A( g! m$ r$ }
4、正确设置 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP , t* X3 n  W7 r% G! `# g

2 Y5 y/ d" E% U" Q9 [) Q( ^2 u在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的设置正确与否,对能否发送 Unicode 至关重要。根据协议规范以及我的调试结果,以上几个标志的正确设置分别为(都是16进制):
" }7 k/ L. Q0 a5 @/ d6 gFirst-Octet : 11 3 B1 {. d' y; W* w/ E7 W( U
TP-MR : 00
8 [  W3 {+ q# {4 H. XTP-PID : 00 4 X5 Y5 s; U' i- [; W2 J/ o0 [# ^
TP-DCS : 08 (编码方式,16-bit) ) W1 r1 h, C$ Z3 o% X0 Y- [, s& Q
TP-VP : A7 ; p! Q5 B2 e2 M3 r8 A" v
/ i: O/ m; a7 C8 G# o& b
经过以上步骤,已经可以做到发送中文字符了。
1 W% X5 T. H+ h2 u% L) h5 H$ h4 y希望这篇文档,能为准备在linux下做短信开发的朋友提供一些帮助。
, @' B" M) p/ A, N$ x5 Y, O1 W( A2 w2 J
" o9 f4 `: U0 T$ j7 k5 p  _
参考文献: , ~' C4 S0 }1 c4 K# V  C$ S. e
★ An introduction to the SMS in PDU mode GSM Recommendation phase 2
( L; D; n8 p6 e0 x6 R' G3 ^' q

该用户从未签到

3#
发表于 2019-7-5 17:08 | 只看该作者
研究一下SMS中用Unicode编码发送中文 ,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-9-28 10:19 , Processed in 0.140625 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表