日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

短消息编解码算法

發布時間:2025/3/17 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 短消息编解码算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.消息編碼與解碼
用C實現7-bit編碼和解碼的算法如下:

// 7-bit編碼
// pSrc: 源字符串指針
// pDst: 目標編碼串指針
// nSrcLength: 源字符串長度
// 返回: 目標編碼串長度
int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
??? int nSrc;??????? // 源字符串的計數值
??? int nDst;??????? // 目標編碼串的計數值
??? int nChar;?????? // 當前正在處理的組內字符字節的序號,范圍是0-7
??? unsigned char nLeft;??? // 上一字節殘余的數據
???
??? // 計數值初始化
??? nSrc = 0;
??? nDst = 0;
???
??? // 將源串每8個字節分為一組,壓縮成7個字節
??? // 循環該處理過程,直至源串被處理完
??? // 如果分組不到8字節,也能正確處理
??? while(nSrc
??? {
??????? // 取源字符串的計數值的最低3位
??????? nChar = nSrc & 7;
???
??????? // 處理源串的每個字節
??????? if(nChar == 0)
??????? {
??????????? // 組內第一個字節,只是保存起來,待處理下一個字節時使用
??????????? nLeft = *pSrc;
??????? }
??????? else
??????? {
??????????? // 組內其它字節,將其右邊部分與殘余數據相加,得到一個目標編碼字節
??????????? *pDst = (*pSrc << (8-nChar)) | nLeft;
???
??????????? // 將該字節剩下的左邊部分,作為殘余數據保存起來
??????????? nLeft = *pSrc >> nChar;
??????????? // 修改目標串的指針和計數值 pDst++;
??????????? nDst++;
??????? }
???????
??????? // 修改源串的指針和計數值
??????? pSrc++; nSrc++;
??? }
???
??? // 返回目標串長度
??? return nDst;
}
???
// 7-bit解碼
// pSrc: 源編碼串指針
// pDst: 目標字符串指針
// nSrcLength: 源編碼串長度
// 返回: 目標字符串長度
int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
??? int nSrc;??????? // 源字符串的計數值
??? int nDst;??????? // 目標解碼串的計數值
??? int nByte;?????? // 當前正在處理的組內字節的序號,范圍是0-6
??? unsigned char nLeft;??? // 上一字節殘余的數據
???
??? // 計數值初始化
??? nSrc = 0;
??? nDst = 0;
???
??? // 組內字節序號和殘余數據初始化
??? nByte = 0;
??? nLeft = 0;
???
??? // 將源數據每7個字節分為一組,解壓縮成8個字節
??? // 循環該處理過程,直至源數據被處理完
??? // 如果分組不到7字節,也能正確處理
??? while(nSrc
??? {
??????? // 將源字節右邊部分與殘余數據相加,去掉最高位,得到一個目標解碼字節
??????? *pDst = ((*pSrc << nByte) | nLeft) & 0x7f;
??????? // 將該字節剩下的左邊部分,作為殘余數據保存起來
??????? nLeft = *pSrc >> (7-nByte);
???
??????? // 修改目標串的指針和計數值
??????? pDst++;
??????? nDst++;
???
??????? // 修改字節計數值
??????? nByte++;
???
??????? // 到了一組的最后一個字節
??????? if(nByte == 7)
??????? {
??????????? // 額外得到一個目標解碼字節
??????????? *pDst = nLeft;
???
??????????? // 修改目標串的指針和計數值
??????????? pDst++;
??????????? nDst++;
???
??????????? // 組內字節序號和殘余數據初始化
??????????? nByte = 0;
??????????? nLeft = 0;
??????? }
???
??????? // 修改源串的指針和計數值
??????? pSrc++;
??????? nSrc++;
??? }
???
??? *pDst = 0;
???
??? // 返回目標串長度
??? return nDst;
} 需要指出的是,7-bit的字符集與ANSI標準字符集不完全一致,在0x20以下也排布了一些可打印字符,但英文字母、阿拉伯數字和常用符號的位 置兩者是一樣的。用上面介紹的算法收發純英文短消息,一般情況應該是夠用了。如果是法語、德語、西班牙語等,含有 “?”、 “é”這一類字符,則要按上面編碼的輸出去查表,請參閱GSM 03.38的規定。 8-bit編碼其實沒有規定什么具體的算法,不需要介紹。 UCS2編碼是將每個字符(1-2個字節)按照ISO/IEC10646的規定,轉變為16位的Unicode寬字符。在Windows系統中,特 別是在2000/XP中,可以簡單地調用API 函數實現編碼和解碼。如果沒有系統的支持,比如用單片機控制手機模塊收發短消息,只好用查表法解決了。 Windows環境下,用C實現UCS2編碼和解碼的算法如下: // UCS2編碼
// pSrc: 源字符串指針
// pDst: 目標編碼串指針
// nSrcLength: 源字符串長度
// 返回: 目標編碼串長度
int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
??? int nDstLength;??????? // UNICODE寬字符數目
??? WCHAR wchar[128];????? // UNICODE串緩沖區
???
??? // 字符串-->UNICODE串
??? nDstLength = ::MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);
???
??? // 高低字節對調,輸出
??? for(int i=0; i
??? {
??????? // 先輸出高位字節
??????? *pDst++ = wchar[i] >> 8;
?????? // 后輸出低位字節
??????? *pDst++ = wchar[i] & 0xff;
??? }
???
??? // 返回目標編碼串長度
??? return nDstLength * 2;
}
???
// UCS2解碼
// pSrc: 源編碼串指針
// pDst: 目標字符串指針
// nSrcLength: 源編碼串長度
// 返回: 目標字符串長度
int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
??? int nDstLength;??????? // UNICODE寬字符數目
??? WCHAR wchar[128];????? // UNICODE串緩沖區
???
??? // 高低字節對調,拼成UNICODE
??? for(int i=0; i
??? {
??????? // 先高位字節
??????? wchar[i] = *pSrc++ << 8;
???
??????? // 后低位字節
??????? wchar[i] |= *pSrc++;
??? }
???
??? // UNICODE串-->字符串
??? nDstLength = ::WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);
???
??? // 輸出字符串加個結束符???
??? pDst[nDstLength] = '\0';???
???
??? // 返回目標字符串長度
??? return nDstLength;
} 用以上編碼和解碼模塊,還不能將短消息字符串編碼為PDU串需要的格式,也不能直接將PDU串中的用戶信息解碼為短消息字符串,因為還差一個在可打 印字符串和字節數據之間相互轉換的環節。可以循環調用sscanf和sprintf函數實現這種變換。下面提供不用這些函數的算法,它們也適用于單片機、 DSP編程環境。 // 可打印字符串轉換為字節數據
// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// pSrc: 源字符串指針
// pDst: 目標數據指針
// nSrcLength: 源字符串長度
// 返回: 目標數據長度
int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
??? for(int i=0; i
??? {
??????? // 輸出高4位
??????? if(*pSrc>='0' && *pSrc<='9')
??????? {
??????????? *pDst = (*pSrc - '0') << 4;
??????? }
??????? else
??????? {
??????????? *pDst = (*pSrc - 'A' + 10) << 4;
??????? }
???
??????? pSrc++;
???
??????? // 輸出低4位
??????? if(*pSrc>='0' && *pSrc<='9')
??????? {
??????????? *pDst |= *pSrc - '0';
??????? }
??????? else
??????? {
??????????? *pDst |= *pSrc - 'A' + 10;
??????? }
??????? pSrc++;
??????? pDst++;
??? }
???
??? // 返回目標數據長度
??? returnnSrcLength / 2;
}
???
// 字節數據轉換為可打印字符串
// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
// pSrc: 源數據指針
// pDst: 目標字符串指針
// nSrcLength: 源數據長度
// 返回: 目標字符串長度
int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
??? const char tab[]="0123456789ABCDEF";??? // 0x0-0xf的字符查找表
???
??? for(int i=0; i
??? {
??????? // 輸出低4位
??????? *pDst++ = tab[*pSrc >> 4];
???
??????? // 輸出高4位
??????? *pDst++ = tab[*pSrc & 0x0f];
???
??????? pSrc++;
??? }
???
??? // 輸出字符串加個結束符
??? *pDst = '\0';
???
??? // 返回目標字符串長度
??? return nSrcLength * 2;
}
2消息發送
// 用戶信息編碼方式
#define GSM_7BIT??????? 0
#define GSM_8BIT??????? 4
#define GSM_UCS2??????? 8
???
// 短消息參數結構,編碼/解碼共用
// 其中,字符串以0結尾
typedef struct {
??? char SCA[16];?????? // 短消息服務中心號碼(SMSC地址)
??? char TPA[16];?????? // 目標號碼或回復號碼(TP-DA或TP-RA)
??? char TP_PID;??????? // 用戶信息協議標識(TP-PID)
??? char TP_DCS;??????? // 用戶信息編碼方式(TP-DCS)
??? char TP_SCTS[16];?? // 服務時間戳字符串(TP_SCTS), 接收時用到
??? char TP_UD[161];??? // 原始用戶信息(編碼前或解碼后的TP-UD)
??? char index;???????? // 短消息序號,在讀取時用到
} SM_PARAM; 大家已經注意到PDU串中的號碼和時間,都是兩兩顛倒的字符串。利用下面兩個函數可進行正反變換: // 正常順序的字符串轉換為兩兩顛倒的字符串,若長度為奇數,補'F'湊成偶數
// 如:"8613851872468" --> "683158812764F8"
// pSrc: 源字符串指針
// pDst: 目標字符串指針
// nSrcLength: 源字符串長度
// 返回: 目標字符串長度
int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength)
{
??? int nDstLength;?? // 目標字符串長度
??? char ch;????????? // 用于保存一個字符
???
??? // 復制串長度
??? nDstLength = nSrcLength;
???
??? // 兩兩顛倒
??? for(int i=0; i
??? {
??????? ch = *pSrc++;??????? // 保存先出現的字符
??????? *pDst++ = *pSrc++;?? // 復制后出現的字符
??????? *pDst++ = ch;??????? // 復制先出現的字符
??? }
???
??? // 源串長度是奇數嗎?
??? if(nSrcLength & 1)
??? {
??????? *(pDst-2) = 'F';???? // 補'F'
??????? nDstLength++;??????? // 目標串長度加1
??? }
???
??? // 輸出字符串加個結束符
??? *pDst = '\0';
???
??? // 返回目標字符串長度
??? return nDstLength;
}
???
// 兩兩顛倒的字符串轉換為正常順序的字符串
// 如:"683158812764F8" --> "8613851872468"
// pSrc: 源字符串指針
// pDst: 目標字符串指針
// nSrcLength: 源字符串長度
// 返回: 目標字符串長度
int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength)
{
??? int nDstLength;?? // 目標字符串長度
??? char ch;????????? // 用于保存一個字符
???
??? // 復制串長度
??? nDstLength = nSrcLength;
???
??? // 兩兩顛倒
??? for(int i=0; i
??? {
??????? ch = *pSrc++;??????? // 保存先出現的字符
??????? *pDst++ = *pSrc++;?? // 復制后出現的字符
??????? *pDst++ = ch;??????? // 復制先出現的字符
??? }
???
??? // 最后的字符是'F'嗎?
??? if(*(pDst-1) == 'F')
??? {
??????? pDst--;
??????? nDstLength--;??????? // 目標字符串長度減1
??? }
???
??? // 輸出字符串加個結束符
??? *pDst = '\0';
???
??? // 返回目標字符串長度
??? return nDstLength;
} 以下是PDU全串的編解碼模塊。為簡化編程,有些字段用了固定值。 // PDU編碼,用于編制、發送短消息
// pSrc: 源PDU參數指針
// pDst: 目標PDU串指針
// 返回: 目標PDU串長度
int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst)
{
??? int nLength;???????????? // 內部用的串長度
??? int nDstLength;????????? // 目標PDU串長度
??? unsigned char buf[256]; // 內部用的緩沖區
???
??? // SMSC地址信息段
??? nLength = strlen(pSrc->SCA);??? // SMSC地址字符串的長度???
??? buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1;??? // SMSC地址信息長度
??? buf[1] = 0x91;??????? // 固定: 用國際格式號碼
??? nDstLength = gsmBytes2String(buf, pDst, 2);??????? // 轉換2個字節到目標PDU串
??? nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength);??? // 轉換SMSC到目標PDU串
???
??? // TPDU段基本參數、目標地址等
??? nLength = strlen(pSrc->TPA);??? // TP-DA地址字符串的長度
??? buf[0] = 0x11;??????????? // 是發送短信(TP-MTI=01),TP-VP用相對格式(TP-VPF=10)
??? buf[1] = 0;?????????????? // TP-MR=0
??? buf[2] = (char)nLength;?? // 目標地址數字個數(TP-DA地址字符串真實長度)
??? buf[3] = 0x91;??????????? // 固定: 用國際格式號碼
??? nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 轉換4個字節到目標PDU串
??? nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 轉換TP-DA到目標PDU串
???
??? // TPDU段協議標識、編碼方式、用戶信息等
??? nLength = strlen(pSrc->TP_UD);??? // 用戶信息字符串的長度
??? buf[0] = pSrc->TP_PID;??????? // 協議標識(TP-PID)
??? buf[1] = pSrc->TP_DCS;??????? // 用戶信息編碼方式(TP-DCS)
??? buf[2] = 0;??????????? // 有效期(TP-VP)為5分鐘
??? if(pSrc->TP_DCS == GSM_7BIT)???
??? {
??????? // 7-bit編碼方式
??????? buf[3] = nLength;??????????? // 編碼前長度
??????? nLength = gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4;??? // 轉換TP-DA到目標PDU串
??? }
??? else if(pSrc->TP_DCS == GSM_UCS2)
??? {
??????? // UCS2編碼方式
??????? buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength);??? // 轉換TP-DA到目標PDU串
??????? nLength = buf[3] + 4;??????? // nLength等于該段數據長度
??? }
??? else
??? {
??????? // 8-bit編碼方式
??????? buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength);??? // 轉換TP-DA到目標PDU串
??????? nLength = buf[3] + 4;??????? // nLength等于該段數據長度
??? }
??? nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength);??????? // 轉換該段數據到目標PDU串
???
??? // 返回目標字符串長度
??? return nDstLength;
}
??? // PDU解碼,用于接收、閱讀短消息
// pSrc: 源PDU串指針
// pDst: 目標PDU參數指針
// 返回: 用戶信息串長度
int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst)
{
??? int nDstLength;????????? // 目標PDU串長度
??? unsigned char tmp;?????? // 內部用的臨時字節變量
??? unsigned char buf[256]; // 內部用的緩沖區
???
??? // SMSC地址信息段
??? gsmString2Bytes(pSrc, &tmp, 2);??? // 取長度
??? tmp = (tmp - 1) * 2;??? // SMSC號碼串長度
??? pSrc += 4;????????????? // 指針后移
??? gsmSerializeNumbers(pSrc, pDst->SCA, tmp);??? // 轉換SMSC號碼到目標PDU串
??? pSrc += tmp;??????? // 指針后移
???
??? // TPDU段基本參數、回復地址等
??? gsmString2Bytes(pSrc, &tmp, 2);??? // 取基本參數
??? pSrc += 2;??????? // 指針后移
??? if(tmp & 0x80)
??? {
??????? // 包含回復地址,取回復地址信息
??????? gsmString2Bytes(pSrc, &tmp, 2);??? // 取長度
??????? if(tmp & 1) tmp += 1;??? // 調整奇偶性
??????? pSrc += 4;????????? // 指針后移
??????? gsmSerializeNumbers(pSrc, pDst->TPA, tmp);??? // 取TP-RA號碼
??????? pSrc += tmp;??????? // 指針后移
??? }
???
??? // TPDU段協議標識、編碼方式、用戶信息等
??? gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2);??? // 取協議標識(TP-PID)
??? pSrc += 2;??????? // 指針后移
??? gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2);??? // 取編碼方式(TP-DCS)
??? pSrc += 2;??????? // 指針后移
??? gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);??????? // 服務時間戳字符串(TP_SCTS)
??? pSrc += 14;?????? // 指針后移
??? gsmString2Bytes(pSrc, &tmp, 2);??? // 用戶信息長度(TP-UDL)
??? pSrc += 2;??????? // 指針后移
??? if(pDst->TP_DCS == GSM_7BIT)???
??? {
??????? // 7-bit解碼
??????? nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式轉換
??????? gsmDecode7bit(buf, pDst->TP_UD, nDstLength);??? // 轉換到TP-DU
??????? nDstLength = tmp;
??? }
??? else if(pDst->TP_DCS == GSM_UCS2)
??? {
??????? // UCS2解碼
??????? nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);??????? // 格式轉換
??????? nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength);??? // 轉換到TP-DU
??? }
??? else
??? {
??????? // 8-bit解碼
??????? nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);??????? // 格式轉換
??????? nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength);??? // 轉換到TP-DU
??? }
???
??? // 返回目標字符串長度
??? return nDstLength;
}

轉載于:https://blog.51cto.com/mosey/843306

總結

以上是生活随笔為你收集整理的短消息编解码算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 香蕉视频色版 | 日韩av在线播放不卡 | 日韩视频一| 国产成人福利视频 | 国产区精品 | 艳情五月| 久久国色 | 欧美精品日韩精品 | 精品成人av一区二区三区 | 亚洲片国产一区一级在线观看 | 欧美不卡在线观看 | 日韩av成人 | 给我看免费高清在线观看 | 国产在线不卡 | 少妇搡bbbb搡bbbb | 我们的生活第五季在线观看免费 | 亚洲精品国产精品国自产网站 | 久久一区精品 | 九热在线视频 | 亚洲天堂网在线观看 | 欧美一区二区三区激情 | 中文字幕35页 | 在线观看麻豆视频 | 华人av在线 | cekc老妇女cea0 | 操干视频| 亚洲AV无码阿娇国产精品 | 一区二区三区欧美精品 | 亚洲综合色网站 | 成人在线视频播放 | 日本va欧美va国产激情 | 999xxxxx | 国产精品久久久爽爽爽麻豆色哟哟 | 国产女教师bbwbbwbbw | 一直草| 久久人妻无码aⅴ毛片a片app | 久久久久1 | 男人的天堂在线播放 | 亚洲欧美激情精品一区二区 | 日本一级吃奶淫片免费 | 欧美性一级 | 日本高清视频免费观看 | 亚洲国产www | 久久精品免费电影 | 青草青草久热 | 91影院在线观看 | 无套白嫩进入乌克兰美女 | 激情亚洲色图 | 不用播放器看av | 国产高清在线视频观看 | 欧美成人免费观看视频 | 精品一区二区三区无码视频 | 欧美高清在线一区 | 国产成人精品亚洲日本在线观看 | www.com在线观看| 女同性做受全过程动图 | 人人爽夜夜爽 | 黄频视频在线观看 | 国产精品一区二区免费 | 水蜜桃av无码 | 欧美美女性视频 | 国产精品永久在线观看 | 成人福利视频在线观看 | 日韩性猛交ⅹxxx乱大交 | av私库| 在线观看日韩av电影 | 亚洲成av人片在线观看无码 | 福利一区二区在线观看 | 亚洲一区视频 | 国产精品视频999 | av导航在线| 亚洲AV无码精品色 | 草莓视频在线观看入口w | 国产乱子伦精品无码专区 | 东北熟女一区二区三区 | 日本色站 | 婷婷综合在线 | zzji欧美大片 | 亚洲综合视频网 | 免费黄色短片 | 日本系列第一页 | 初恋视频污 | 中文字幕亚洲色图 | 国产精品成人免费视频 | 欧美成人aaa片一区国产精品 | 国产成人无遮挡在线视频 | 欧美一区二区三区在线观看 | 欧美精品在线一区 | 99精品网 | 黄色网址在线看 | av777777| 中文字幕精品一区二 | 青青草视频污 | 亚洲一区电影在线观看 | 最好看的中文字幕 | 91玉足脚交嫩脚丫在线播放 | 一级少妇精品久久久久久久 | 日日夜夜骑| 在线视频网 |