2009年11月29日 星期日

簡單的COM範例

簡單的COM範例

環境:Visual C++ 2008

1. 新增一個ATL專案,取名叫SimpleATL,伺服程式類型選擇DLL。
2. 在類別檢視下,可以看見SimpleATL類別,按右鍵加入類別,選擇ATL簡單物件,簡短名稱就設為MyATL。
3. 接著就是在IMyATL interface加上method。在IMyATL按右鍵加入method,方法名稱為Add,參數屬性為:
[in] LONG lNum1, [in] LONG lNum2, [out] LONG * plResult
4. 實作Add Method
STDMETHODIMP CMyATL::Add(LONG lNum1, LONG lNum2, LONG * plResult)
{
*plResult = lNum1 + lNum2;
return S_OK;
}

5. 建置專案即完成。


接著我們就用VC++來寫程式來使用這個COM
建立一個新的Win32 Console Application,選擇主控台應用程式和空專案選項。
先將SimpleATL_i.h及SimpleATL_i.c複製並加入到這個專案資料夾。
新增TestATL.cpp
#include "SimpleATL_i.h"
#include <iostream>

using namespace std;

void main(void)
{
HRESULT hr;
IMyATL *pIMyATL;

hr = CoInitialize(NULL);

if(SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_MyATL, NULL, CLSCTX_INPROC_SERVER, IID_IMyATL, (void**) &pIMyATL);

if(SUCCEEDED(hr))
{
long lResult;

hr = pIMyATL->Add(5, 10, &lResult);
cout << "5 + 10 = " << lResult << endl;
hr = pIMyATL->Release();
}
else
cout << "CoCreateInstance Failed." << endl;
}
CoUninitialize();
}

2009年11月28日 星期六

SO_REUSEADDR

當一個Socket server如果重新啟動時,在bind的過程就會出現:Address already in use的錯誤訊息,必須等待TCP TIME_WAIT state的時間(2 * MSL)才能使用這個Address。為了避免這個問題發生,我們可以透過修改socket參數來讓socket可以馬上bind之前的Address。

sock = socket(AF_INET, SOCK_STREAM, 0);

int on = 1;
int status = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
if (status == -1)
perror("setsockopt() error");

簡單的DLL範例

簡單的DLL範例

環境:Visual C++ 2008

建立一個新的,選擇Win32 Console Application
最後選擇DLL和Empty Porject選項

建立AddInt.h及AddInt.cpp

AddInt.h
#ifndef _ADD_INT_H_
#define _ADD_INT_H_

#define DLLExport __declspec( dllexport )

extern "C"
{
DLLExport int Add(int a, int b);
}

#endif


function必須export才能被使用,有兩種方法可以使用:
使用 __declspec這個關鍵字
建立一個Module-Definition File (.DEF)

至於為什麼要加入extern "C"
因為C++ compiler在編譯時會將function name作一些修飾也就是改名字的動作(mangle)
加入extern "C"則可保留原名

AddInt.cpp
#include "AddInt.h"

int Add(int a, int b) {
return a + b;
}


Build Project即完成,我們會在資料夾找到AddInt.dll及AddInt.lib


接著我們就寫一個程式來使用這個DLL

可以用兩種方式來使用DLL

Implicit Linking - 程式需link到AddInt.lib,並將AddInt.dll放在與程式同目錄下
#include <iostream>
#include "AddInt.h"

int main()
{
std::cout << Add(5, 10) << std::endl;

return 0;
}


Explicit Linking - 不需要AddInt.h及AddInt.Lib,僅需要AddInt.dll,但使用較為複雜。
#include <iostream>
#include <windows.h>

typedef int (*pfAddIntFunction)(int,int);

int main()
{
pfAddIntFunction pfAddInt ;

HINSTANCE hLibrary = LoadLibrary(L"AddInt.dll");

if(hLibrary)
{
pfAddInt = (pfAddIntFunction)GetProcAddress(hLibrary, "Add");

if(pfAddInt)
{
std::cout << pfAddInt(5, 10) << std::endl;
}

FreeLibrary(hLibrary);
}
else
{
std::cout << "Failed To Load Library" << std::endl;
}

return 0;
}

2009年11月21日 星期六

NAT型態

NAT的類型大致可分為四種:
  • Full cone NAT
  • (Address) Restricted cone NAT
  • Port-Restricted cone NAT
  • Symmetric NAT

假設在NAT下的主機A為(iIP, iPort),實際對外為(eIP, ePort)

Full cone NAT: 任何主機皆可透過(eIP, ePort)送封包給A。

(Address) Restricted cone NAT:只有之前收過A送來封包的外部主機(hIP, any),才可透過(eIP, ePort)送封包給A,不限定原來溝通的Port。

Port-Restricted cone NAT :同上,但外部主機只能用之前用的Port才能送封包給A。

Symmetric NAT:同上,但A對每一個不同的(hIP, hPort),也就是IP或Port的任何一值改變,其(eIP, ePort)就會不同。

2009年11月17日 星期二

Dump Schema

若要匯出MySQL下某個資料庫的Schema,可以用mysqldump來達成:

# mysqldump -d -u 使用者名稱 -p 欲備份的資料庫 >> FILENAME.sql

例:
# mysqldump -d -u howard -p account > account.sql


匯入到新的MySQL資料庫

# mysql -u 使用者名稱 -p 資料庫 < account.sql