Linux開發中GSM 中文簡訊 SMS PDU編碼原理及實現

來源:互聯網
上載者:User

SMS是由Esti 所制定的一個規範(GSM 03.40 和 GSM 03.38)。有兩種方式來發送和接收SMS訊息:文字模式或者PDU(protocol description unit)模式。文字模式只能發送普通的ASCII字元,而要發送圖片、鈴聲、其它編碼的字元(如中文)就必須採用PDU模式。

PDU模式中,可以採用三種編碼方式來編碼要發送的內容,分別是 7-bit編碼、8-bit編碼、16-bit編碼。7-bit編碼用於發送普通的ASCII字元;8-bit編碼通常用於發送資料訊息,比片和鈴聲等;而16-bit編碼用於發送Unicode字元。在這三種編碼方式下,可以發送的最大字元數分別是 160、 140、70。
 

若要發送中文(或日文等),必須採用PDU模式的Unicode編碼方式。

最近參與了一個在linux下收發簡訊的項目。其中,需要實現中文的發送和接收。由於原來沒有中文編碼、Unicode編碼的經驗,所以查了一些資料,也在一些論壇上提了一些問題。現在把它整理出來,希望對以後再做類似項目的朋友有個協助。我寫的比較簡單,關於PDU的規範,可以點擊這裡下載SMS_PDU-mode.pdf查看,或者去wavecom的網站上找找看。

1、GB2312 編碼到Unicode 編碼的轉換

在 RedHat 7.3系統上,預設是用GB2312編碼儲存中文字元的(對於中英文混合的文本也是如此)。所以首先需要把 GB2312 編碼的字串轉換到 Unicode編碼的字串。

GB2312編碼是一種多位元組編碼方式,對於中文,用2個位元組表示,對於英文,用1個位元組表示,就是英文的ascii碼。(註:我沒有仔細看過 GB2312編碼的規範,以上理解是實際開發中得出來的,不能保證正確性)。Unicode編碼是雙位元組編碼方式,對所有字元,都採用2個位元組編碼。在 linux平台上,GB2312編碼到Unicode編碼的轉換,可以有三種實現方式(或者更多):

1)、用 mbstowcs () 函數。就是多位元組編碼到寬字元的轉換。我試過它,可以正確的轉換,但是這個函數可能不是很可靠。

2)、用 GB2312 à Unicode 的轉換表,手動查錶轉換。網上有這樣的轉換表,你需要對每一個GB2312字元,根據它是中文字元還是英文字元,分別轉換。

3)、用 iconv () 函數。這可能是linux上的標準的方法,不僅可以轉換GB2312到Unicode,還可以在任意的兩種編碼之間轉換(前提是linux系統要支援這些編碼)。

首先要用 iconv_open(), 開啟一個轉換控制代碼,指定兩種轉換前的編碼和轉換後的編碼。然後用 icnov() 作轉換。最後用 iconv_close()關閉控制代碼,釋放資源。

#include <iconv.h>
#define BUFLEN 200

char inbuf[BUFLEN];
char outbuf[BUFLEN];
char* pin = inbuf;
char* pout = outbuf;

//開啟檔案,讀入GB2312資料到inbuf,資料長度為 len
int inleft = len;
int outleft = BUFLEN;
iconv_t cd;

if((cd = iconv_open(“gb2312”, “unicode”)) == (iconv_t)-1)
          return 1;

if(iconv(cd, &pin, &inleft, &pout, &outleft) == (size_t)-1)
          return 1;

iconv_close(cd);

使用 iconv () 時,需要注意參數的使用,inleft 是輸入緩衝區資料資料長度,outleft是輸出緩衝區大小。(需要保證輸出緩衝區足夠大)。轉換以後,outleft 是outbuf中空閑空間的大小,所以 BUFLEN-outleft 才是真正的Unicode資料長度。

注意:不論是GB2312編碼,還是Unicode編碼,在記憶體中都是一些位元組序列,所以我們可以統一用 類型為 char(或者unsigned char)的字元數組來儲存。所以,BUFLEN-outleft是 字元(char)個數,而不是Unicode字元個數。

2、 Unicode 編碼到 16-bit 編碼的轉換

在得到 Unicode編碼以後,還需要轉換到 PDU 的16-bit 編碼,才可以正確的發送。在這個轉換過程中,需要注意兩點:

1)、Unicode 編碼最開始的 0xFEFF標誌要被去除,在0xFEFF之後的內容,才是真正的Unicode字元。(至於為什麼有這個0xfeff標誌,知道的朋友告訴我一聲,呵呵)。

2)、Unicode 是雙位元組字元,由於我的系統是小端位元組序(little-endian),也就是說,在儲存的時候,是先低位,後高位,例如“中”的Unicode編碼是 0x4E2D,儲存的時候是 2D4E,在轉換到 16-bit編碼的時候,要注意這個順序的不同。當然,如果你的系統是大端位元組序(big-endian),那麼就不用這樣做了。

3)、為了將0x4E2D 的Unicode編碼轉換到 “4E2D” 的16-bit編碼,可以用 sprintf(buf,    “%02X”,    outbuf[i]) 對每一個位元組作轉換。

3、正確計算16-bit 編碼的訊息體長度

PDU規範中,需要包括訊息體的長度,這裡你要小心計算。

4、正確設定 First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP

在PDU格式中,First-Octet 、TP-MR、TP-PID、TP-DCS、TP-VP的設定正確與否,對能否發送 Unicode 至關重要。根據協議規範以及我的調試結果,以上幾個標誌的正確設定分別為(都是16進位):

First-Octet : 11   
TP-MR:          00
TP-PID:          00
TP-DCS:        08      (編碼方式,16-bit)
TP-VP:           A7

經過以上步驟,已經可以做到發送中文字元了。

 

本篇文章來源於 Linux公社網站(www.linuxidc.com)  原文連結:http://www.linuxidc.com/Linux/2011-05/35682.htm

 

 

 

 原文連結http://www.linuxidc.com/Linux/2011-05/35682.htm

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.