天天看點

MFC 飛信發短信

這段時間,我在學習vc。以前一直是在用C#和Java的,最近發現MFC還是有一定的用處的,是以就利用暑假這段時間來學習一下。但是光看書沒有用,幾 個月之前,我用C#實作了一個飛信發短信的接口。是以這次,以學習MFC為目的,寫了一個MFC版的飛信發短信接口。開發工具用的是Visual studio 2005。

    其中用到了MFC中的衆多功能,如Socket、CString類的使用、Winnet、加密(hash)、ATl提供的正規表達式庫和調用Dom解析 xml等等。最後,我将該接口做成了一個MFC dll,進而也學習了MFC dll的制作和使用。編譯的時候采用預設的Unicode編碼。另外,其中還涉及到編碼的轉換等等。在處理字元串的時候基本都用CString,不知道這 種習慣好不好。

    接口中隻提供一個CFetion類,其中提供3個函數,功能主要登陸、發送短信和登出,相當簡單,一看就明白。由于其中調用了Com,是以調用的時候需要進行Com的初始化工作。下面是一個使用的例子:

#include "Fetion.h"

#pragma comment(lib, "MFCFetionSDK.lib")

CoInitialize(NULL);

CFetion fetion(_T("你的手機号"), _T("你的密碼"));

fetion.Login();

fetion.SendSMSToPhone(_T("好友手機号"), _T("要發送的消息。"));

fetion.Logout();

CoUninitialize();

    速度方面,我測試一下,還是相當快的,占的記憶體也非常的少。

    關于飛信協定方面,還是采用MD5進行加密的,改成SHA1也相當簡單。在我之前的文章中,我講到一些關鍵技術的實作方法。由于剛剛初學MFC,其中肯定寫得很爛,是以代碼先不提供了。如果有需要,可以發郵件給我。mailto:[email protected]

    下面說一下,我解決的幾個關鍵性的問題,也友善剛初學MFC的朋友。

    1、如何導出MFC類?

    這個問題折磨了我很久,vs2005中建立一個MFC dll的時候會産生一個.def檔案,用來導出函數,但我上網查了好多資料,都沒有實作用.def導出類。網上有說可以生成map檔案後,通過檢視其中的 資訊導出類中的函數。我嫌麻煩,最後通過AFX_CLASS_EXPORT進行導出的。導入用AFX_CLASS_IMPORT。

    2、如何用afxinet.h通路https

    飛信在登入的時候用到https,好像我試了一下http同樣是可行的,但是我覺得不夠安全,是以選擇使用https。但是這和C#中一樣,通路 https的是有會出現證書的問題。網上資料很少,可能是我找資料的方法不對,最後在一個國外網站上找到一個solution。

AfxParseURL(url, type, server, param, port);

connection = session.GetHttpConnection(server, port);

if(type == 4107)

{

file = connection->OpenRequest(CHttpConnection::HTTP_VERB_GET, param, NULL, 1, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID);

}

    3、編碼轉換和hash的計算

    編碼轉換用的Windows api中的WideCharToMultiByte和MultiByteToWideChar。而hash用的是#include <wincrypt.h>。下面是我用到的工具類。

MFC 飛信發短信

#pragma once

// CUtils

#pragma region  編碼CodePage表

enum CodePages

    IBM037=37,

    IBM437=437,

    IBM500=500,

    ASMO_708=708,

    DOS_720=720,

    ibm737=737,

    ibm775=775,

    ibm850=850,

    ibm852=852,

    IBM855=855,

    ibm857=857,

    IBM00858=858,

    IBM860=860,

    ibm861=861,

    DOS_862=862,

    IBM863=863,

    IBM864=864,

    IBM865=865,

    cp866=866,

    ibm869=869,

    IBM870=870,

    windows_874=874,

    cp875=875,

    shift_jis=932,

    gb2312=936,

    ks_c_5601_1987=949,

    big5=950,

    IBM1026=1026,

    IBM01047=1047,

    IBM01140=1140,

    IBM01141=1141,

    IBM01142=1142,

    IBM01143=1143,

    IBM01144=1144,

    IBM01145=1145,

    IBM01146=1146,

    IBM01147=1147,

    IBM01148=1148,

    IBM01149=1149,

    utf_16=1200,

    unicodeFFFE=1201,

    windows_1250=1250,

    windows_1251=1251,

    Windows_1252=1252,

    windows_1253=1253,

    windows_1254=1254,

    windows_1255=1255,

    windows_1256=1256,

    windows_1257=1257,

    windows_1258=1258,

    Johab=1361,

    macintosh=10000,

    x_mac_japanese=10001,

    x_mac_chinesetrad=10002,

    x_mac_korean=10003,

    x_mac_arabic=10004,

    x_mac_hebrew=10005,

    x_mac_greek=10006,

    x_mac_cyrillic=10007,

    x_mac_chinesesimp=10008,

    x_mac_romanian=10010,

    x_mac_ukrainian=10017,

    x_mac_thai=10021,

    x_mac_ce=10029,

    x_mac_icelandic=10079,

    x_mac_turkish=10081,

    x_mac_croatian=10082,

    utf_32=12000,

    utf_32BE=12001,

    x_Chinese_CNS=20000,

    x_cp20001=20001,

    x_Chinese_Eten=20002,

    x_cp20003=20003,

    x_cp20004=20004,

    x_cp20005=20005,

    x_IA5=20105,

    x_IA5_German=20106,

    x_IA5_Swedish=20107,

    x_IA5_Norwegian=20108,

    us_ascii=20127,

    x_cp20261=20261,

    x_cp20269=20269,

    IBM273=20273,

    IBM277=20277,

    IBM278=20278,

    IBM280=20280,

    IBM284=20284,

    IBM285=20285,

    IBM290=20290,

    IBM297=20297,

    IBM420=20420,

    IBM423=20423,

    IBM424=20424,

    x_EBCDIC_KoreanExtended=20833,

    IBM_Thai=20838,

    koi8_r=20866,

    IBM871=20871,

    IBM880=20880,

    IBM905=20905,

    IBM00924=20924,

    EUC_JP=20932,

    x_cp20936=20936,

    x_cp20949=20949,

    cp1025=21025,

    koi8_u=21866,

    iso_8859_1=28591,

    iso_8859_2=28592,

    iso_8859_3=28593,

    iso_8859_4=28594,

    iso_8859_5=28595,

    iso_8859_6=28596,

    iso_8859_7=28597,

    iso_8859_8=28598,

    iso_8859_9=28599,

    iso_8859_13=28603,

    iso_8859_15=28605,

    x_Europa=29001,

    iso_8859_8_i=38598,

    iso_2022_jp=50220,

    csISO2022JP=50221,

    iso_2022_kr=50225,

    x_cp50227=50227,

    euc_jp=51932,

    EUC_CN=51936,

    euc_kr=51949,

    hz_gb_2312=52936,

    GB18030=54936,

    x_iscii_de=57002,

    x_iscii_be=57003,

    x_iscii_ta=57004,

    x_iscii_te=57005,

    x_iscii_as=57006,

    x_iscii_or=57007,

    x_iscii_ka=57008,

    x_iscii_ma=57009,

    x_iscii_gu=57010,

    x_iscii_pa=57011,

    utf_7=65000,

    utf_8=65001

};

#pragma endregion

class CUtils : public CObject

public:

    CUtils();

    virtual ~CUtils();

    static void UnicodeToOther(const CStringW &src, CStringA& result, CodePages codePage);

    static void OtherToUnicode(const CStringA& src, CStringW& result, CodePages codePage);

    static void EncodingConvert(const CStringA& src, CodePages srcCodePage, CStringA& result, CodePages resultCodePage);

    static CStringA ComputeHash(const CStringA& pbData, UINT algId);

CUtils::CUtils()

CUtils::~CUtils()

void CUtils::UnicodeToOther(const CStringW &src, CStringA &result, CodePages codePage)

    int n = WideCharToMultiByte(codePage, 0, src.GetString(), -1, 0, 0, 0, 0 );

    WideCharToMultiByte(codePage, 0, src.GetString(), -1, result.GetBuffer(n), n, 0, 0 );

    result.ReleaseBuffer();

void CUtils::OtherToUnicode(const CStringA &src, CStringW &result, CodePages codePage)

    int n = MultiByteToWideChar(codePage, 0, src.GetString(), -1, NULL, 0);

    MultiByteToWideChar(codePage, 0, src.GetString(), -1, result.GetBuffer(n), n);

void CUtils::EncodingConvert(const CStringA &src, CodePages srcCodePage, CStringA &result, CodePages resultCodePage)

    CStringW buffer;

    OtherToUnicode(src, buffer, srcCodePage);

    UnicodeToOther(buffer, result, resultCodePage);

CStringA CUtils::ComputeHash(const CStringA& pbData, UINT algId)

    HCRYPTPROV hProv;

    CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);

    HCRYPTHASH hHash;

    //Alg Id:CALG_MD5,CALG_SHA

    CryptCreateHash(hProv, algId, 0, 0, &hHash);

    CryptHashData(hHash, (const BYTE*)pbData.GetString(), pbData.GetLength(), 0);

    CStringA pbOutHash;

    DWORD dwHashLen;

    DWORD dwLen = sizeof(dwHashLen);

    CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)(&dwHashLen), &dwLen, 0);

    dwLen = dwHashLen;

    CryptGetHashParam(hHash, HP_HASHVAL, (BYTE*)pbOutHash.GetBufferSetLength(dwLen), &dwLen, 0);

    CryptDestroyHash(hHash);

    CryptReleaseContext(hProv, 0);

    return pbOutHash;

    其中用到的都是CString,Unicode用的是CStringW,多位元組的用的是CStringA。這好像在VC6中隻有CString,并不分 什麼CStringA和CStringW。是以這不适合在VC6中使用。 那個Codepages是我從C#中找過來的,竟然發現一個重複的,我直接做删 除處理,也不知道對不對,但我知道utf-8是對的。

    4、關于頭檔案的問題

    我的dll中Fetion.dll中遠不隻這三個函數,還有很多私有函數和私有成員。我在提供Fetion.h中都删除了,開始發現删除之後不好用了, 後來我把其中要到的指針成員改成普通的對象就好用了。但是在debug的版本的時候,告訴我fetion對象被破壞了,不知道怎麼回事。幸好在 release版本中,一切正常。

    5、關于飛信

    飛信的協定分析,我是借助别人的成果,我自己沒有去抓包分析,也沒有去反編譯,和我寫的C#版本一樣,是通過看别人用php版本,翻譯過來的。

   總結

   通過這個簡單的小例子,基本對MFC的非窗體使用有了一個了解,會運用各種東西來處理自己想要的效果。對于窗體程式設計,我的經驗不是很多。我也編寫了一個小例子,一個隐藏和現實視窗的小程式。在以後的文章中介紹。

   dll和例子:​​MFCFetionSDK.rar​​

    由于好多人發郵件給我要源代碼,是以在此提供源代碼的下載下傳:​​mfcfetion.rar​​

    轉載請保持文章的完整性,并注明出處。

作者:小橋流水

上一篇: 鄭州Day6