-
Windows Win32编程 https://www.iteye.com/blog/lobin-2516633
-
Windows MFC编程 https://www.iteye.com/blog/lobin-2516413
-
C: Windows编程: 第三章 TC https://www.iteye.com/blog/lobin-2439914
https://www.iteye.com/blog/lobin-2516632
https://www.iteye.com/blog/lobin-2516634
Windows下C编程主要就是微软的VC环境。
Visual C++下的C/C++编程主要包括Win32控制台程序、Win32应用程序以及MFC应用程序,当然还可以编写Win32和MFC程序库。Win32控制台程序和Win32应用程序的区别在于链接时指定的/subsystem选项不同,Win32控制台程序链接时/subsystem选项指定的是/subsystem:console,而Win32应用程序链接时/subsystem选项指定的是/subsystem:windows。至于MFC应用程序,严格来说,这并不是一种应用程序类型,MFC全称为“Microsoft Foundation Class (MFC) Library”,这个其实只是一个库,或者说是一个编程框架。不管是开发Win32控制台程序还是Win32应用程序,都可以像引入一个第三方库一样引入MFC。这里主要是Visual C++下开发控制台程序。
C/C++程序的入口函数是main函数,这是C/C++程序的标准main入口函数。
main
Visual C++还提供了几个入口函数。比如wmain、_tmain,以及编写Win32和MFC应用程序的WinMain、wWinMain和_tWinMain。
wmain
这里的wmain和我们平常的main不同的就是前面带了一个w,这个w不是指的window或者窗口的意思,而是指的是wide宽字符的意思。wmain函数是main函数的宽字符版本。
关于main和wmain可参考这篇文章:
_tmain
这个其实就是一个宏定义,它最后还是会被替换为main或者wmain。使用_tmain做入口函数的时候要引入tchar.h头文件。
#include <tchar.h> int _tmain() { printf("this is _tmain.\n"); return 0; }
_tmain其实就只是一个在tchar.h中定义的宏,在宽字符环境下,_tmain被替换为wmain,否则还是会被替换为main,和我们平常写的main一样。
#ifdef _UNICODE ... #define _tmain wmain ... #else /* ndef _UNICODE */ ... #define _tmain main ... #endif
在上面的例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main() {...}。
#include <tchar.h> int _tmain(int argc, TCHAR* argv[]) { printf("this is _tmain.\n"); return 0; }
在这个例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main(int argc, char *argv[]) {...}。
#include <tchar.h> int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { printf("this is _tmain.\n"); return 0; }
在这个例子中,如果在窄字符环境下,替换之后就是我们熟悉的int main(int argc, char *argv[], char *envp[]) {...}。
WinMain
INT WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow);
wWinMain
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
_tWinMain
#ifdef _UNICODE ... #define _tWinMain wWinMain ... #else /* ndef _UNICODE */ ... #define _tWinMain WinMain ... #endif
编写静态链接库
在C: Linux C 编程中写过编写静态链接库:
https://www.iteye.com/blog/lobin-2326336
通过comment pragma链入静态链接库
#pragma comment( comment-type [ , "comment-string" ] )
这种方式需要在代码中通过comment pragma链入静态链接库:
#pragma comment(lib, "qt.lib")
qt.h
#include <stddef.h> #if ! defined(QT) #define QT struct qt { size_t size; char data[]; }; struct qt* qt(int i); int qt_get(struct qt* v); int qt_destroy(struct qt* v); #endif
qt.c
#include<stdlib.h> #include<string.h> #include"qt.h" struct qt* qt(int i) { size_t size = sizeof(i); struct qt* v = (struct qt*) malloc(sizeof(struct qt) + size); if (v != NULL) { v->size = size; memcpy(v->data, &i, sizeof(i)); } return v; } int qt_get(struct qt* v) { int *p = NULL; if (v == NULL) { return 0; } p = (int *) v->data; return *p; } int qt_destroy(struct qt* v) { free(v); return 0; }
编译
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c qt.c
生成静态库
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\lib.exe" /nologo qt.obj /out:./qt.lib
调用
static_test.c
#pragma comment(lib, "qt.lib") #include <stdio.h> #include "qt.h" int main() { int i = 1413; struct qt* v = qt(i); if (v == NULL) { return 1; } printf("qt: i=%d\n", qt_get(v)); qt_destroy(v); return 0; }
这里调用的时候,通过comment pragma链入静态链接库:
#pragma comment(lib, "qt.lib")
编译链接
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" static_test.c
运行
>.\static_test.exe
qt: i=1413
查看程序依赖的库
这个是查看程序依赖的动态链接库,这里是链接的静态库,静态库代码直接链入到程序中了,所以这里是查看不到依赖的静态库的。
>ldd static_test.exe
ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c92000
0)
kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7
c800000)
链接时直接指定要链入的静态链接库
编译
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c qt.c
生成静态库
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\lib.exe" /nologo qt.obj /out:./qt.lib
调用
static_test.c
#include <stdio.h> #include "qt.h" int main() { int i = 1413; struct qt* v = qt(i); if (v == NULL) { return 1; } printf("qt: i=%d\n", qt_get(v)); qt_destroy(v); return 0; }
这里调用的时候,不通过comment pragma链入静态链接库
而是在链接的时候直接指定要链入的静态链接库
编译
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c static_test.c
链接
>"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" static_test.obj ./qt.lib
运行
>.\static_test.exe
qt: i=1413
查看程序依赖的库
这个是查看程序依赖的动态链接库,这里是链接的静态库,静态库代码直接链入到程序中了,所以这里是查看不到依赖的静态库的。
>ldd static_test.exe
ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c92000
0)
kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7
c800000)
线程
线程ID
线程ID可以通过GetCurrentThreadId()获取。
线程句柄
创建线程时返回的一个线程句柄。用于指向内部创建的线程对象。
C Run-Time Libraries (CRT)
_beginthread和_beginthreadex
_beginthread
void( __cdecl *start_address )( void * ),
unsigned stack_size,
void *arglist
);
uintptr_t _beginthread( // MANAGED CODE
void( __clrcall *start_address )( void * ),
unsigned stack_size,
void *arglist
);
unsigned, void *);
_beginthread返回的是新创建线程的句柄。
void start_address(void *arg) { char * name = (char *) arg; printf("thread %s\n", name); } int main() { unsigned long th; th = _beginthread(start_address, 0, "1"); ExitThread(0); return 0; }
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthread_test.c
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthread_test.exe ./beginthread_test.obj
获取线程返回退出状态
void start_address(void *args) { unsigned exit_code = (unsigned) args; printf("%d(%u)-%u thread exit(%u)\n", getpid(), GetCurrentProcessId(), GetCurrentThreadId(), exit_code); _endthreadex(exit_code); } int main() { HANDLE hThread; DWORD exit_code = 0; hThread = (HANDLE) _beginthread(start_address, 0, (void *) 100); WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &exit_code); printf("thread id: %u, exit(%d)\n", -1, exit_code); ExitThread(0); return 0; }
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthread_test2.c
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthread_test2.exe ./beginthread_test2.obj
_beginthreadex
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
uintptr_t _beginthreadex( // MANAGED CODE
void *security,
unsigned stack_size,
unsigned ( __clrcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
unsigned (__stdcall *) (void *), void *, unsigned, unsigned *);
_beginthreadex与_beginthread不同的是,_beginthreadex多了几个参数:security,initflag以及thrdaddr。
initflag
用于指定新创建线程的初始状态。
如果指定为0,线程创建后将立即执行。
如果指定为CREATE_SUSPENDED,线程创建后不会立即执行,处于挂起状态。可以调用ResumeThread恢复执行。
如果指定为STACK_SIZE_PARAM_IS_A_RESERVATION,使用stack_size作为初始预留线程栈大小,如果没有指定为STACK_SIZE_PARAM_IS_A_RESERVATION,stack_size指定的是线程栈的commit大小。
thrdaddr
用于返回线程id。
该线程id可以通过GetCurrentThreadId()获取。
_beginthreadex返回的是新创建线程的句柄。
unsigned __stdcall start_address(void *arg) { char * name = (char *) arg; printf("thread %s\n", name); return 0; } int main() { unsigned long th; unsigned thread; th = _beginthreadex(NULL, 0, start_address, "1", 0, &thread); ExitThread(0); return 0; }
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthreadex_test.c
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthreadex_test.exe ./beginthreadex_test.obj
获取线程返回退出状态
unsigned __stdcall start_address(void *args) { unsigned exit_code = (unsigned) args; printf("%d(%u)-%u thread exit(%u)\n", getpid(), GetCurrentProcessId(), GetCurrentThreadId(), exit_code); return exit_code; } int main() { HANDLE hThread; unsigned thread; DWORD exit_code = 0; hThread = (HANDLE) _beginthreadex(NULL, 0, start_address, (void *) 100, 0, &thread); WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, &exit_code); printf("thread id: %u, exit(%d)\n", thread, exit_code); ExitThread(0); return 0; }
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /MT /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c /Fo./ beginthreadex_test3.c
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./beginthreadex_test3.exe ./beginthreadex_test3.obj
C Run-Time Library _beginthread, _beginthreadex to create thread
#ifndef _MT #error "Compiler linking options /MT not specific" #endif #include <stdio.h> #include <windows.h> #include <process.h> void start_address(void *arg) { printf("_beginthread start_address\n"); } unsigned __stdcall start_address_ex(void *arg) { printf("_beginthreadex start_address_ex\n"); return 0; } int main() { #ifdef _MT printf("MT defined\n"); #endif unsigned long th; printf("Thread _beginthread test\n"); th = _beginthread(start_address, 0, NULL); printf("_beginthread return %ld\n", th); unsigned thread; // CREATE_SUSPENDED th = _beginthreadex(NULL, 0, start_address_ex, NULL, 0, &thread); ExitThread(0); return 0; } ==================================== DEBUG=../Debug PATH_VS=D:\usr\bin\Microsoft Visual Studio\VC98 CL="$(PATH_VS)\Bin\cl.exe" LINK="$(PATH_VS)\Bin\link.exe" INCLUDE="D:\usr\bin\Microsoft Visual Studio\VC98\Include" LIB="D:\usr\bin\Microsoft Visual Studio\VC98\Lib" INCLUDE_LIB_LOG=D:\home\admin\workstation\c\liblog LIB_LIB_LOG=D:\home\admin\workstation\c\liblog\Debug liblog.lib: clean # using compiler linking options /MT, If compiles _beginthread edition of Thread $(CL) /GX /W3 /MT /I $(INCLUDE) /c /Fo$(DEBUG)/ ThreadTest__beginthread.cpp $(LINK) /LIBPATH:$(LIB) /OUT:$(DEBUG)/Thread_beginthreadTest.exe $(DEBUG)/*.obj clean: rm -Rf ./*.bak rm -Rf ./*.o rm -Rf ./*.obj rm -Rf ./*.exe rm -Rf ../Debug/* =========================================== 运行结果: MT defined Thread _beginthread test _beginthread return 2024 _beginthread start_address _beginthreadex start_address_ex
自定义控制台窗口图标
#include <stdio.h> #include <tchar.h> #include <windows.h> #include "resource.h" typedef HWND (WINAPI * GETCONSOLEPROC)(); HWND GetConsole() { HWND hRet(NULL); BOOL bLoad(FALSE); HMODULE hMod = GetModuleHandle(_T("kernel32.dll")); if(hMod == NULL) { hMod = LoadLibrary(_T("kernel32.dll")); bLoad = TRUE; } if(hMod != NULL) { GETCONSOLEPROC pFun = (GETCONSOLEPROC) GetProcAddress(hMod, "GetConsoleWindow"); if(pFun != NULL) { hRet = pFun(); } if(bLoad) { FreeLibrary(hMod); } } return hRet; } int main(int argc, char* argv[]) { HWND hConsole = GetConsole(); if(hConsole != NULL) { HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); SendMessage(hConsole, WM_SETICON, ICON_BIG, (LPARAM)hIcon); SendMessage(hConsole, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); } printf("hello c!\n"); return 0; }
resource.h
#define IDI_ICON1 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
rs.rc
#include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Chinese (中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) #ifdef _WIN32 LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #pragma code_page(936) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "icon.ico" #endif // Chinese (中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
编译源程序
>cl /c console_test.cpp
编译资源
>"D:\usr\bin\Microsoft Visual Studio\Common\MSDev98\Bin\RC.EXE" /fo"rs.res" rs.rc
链接
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:./console_test.exe ./console_test.obj rs.res user32.lib
中断
中断处理函数
C编写中断处理函数不是那么容易的。中断处理函数和普通的函数不一样,中断处理函数不像普通函数那样使用ret返回,它使用iret返回退出中断。此外,中断处理函数要求是可重入函数。现在很多编译器(包括C编译器)都不支持编写中断处理函数。C语言标准也没有对中断处理函数标准化。
一些C编译器通过扩展来提供中断处理函数,如TURBO C,GCC等。
TURBO C编写中断处理函数可参考下面的例子。
线程
C++:线程封装
/* * Thread that support cross platform and support global and local start routine, and support * Windows api and C Run-Time Library(even extension) on windows. * <p> * To implements a simple thread, only to overrides the run method. * * @author ada * @version 1.0 * @since 1.0 */ #include <windows.h> #include "Runnable.hpp" #if ! defined THREAD #define THREAD // GLOBAL_START_ROUTINE is a user defined macro, likes a switch, to determine whether to // select global thread start routine or not. GLOBAL_START_ROUTINE can be defined in program, // or using compiler preprocessor options(PREPROCESSOR) /D to define user defined macro // GLOBAL_START_ROUTINE to compiles global start routine edition of Thread #if defined GLOBAL_START_ROUTINE #define _GLOBAL_START_ROUTINE #pragma message ("GLOBAL_START_ROUTINE defined, using global thread start routine.") // using compiler linking options /MT to compiles C Run-Time Library(_beginthread, _beginthreadex) // edition of Thread #if defined(_MT) && (! defined(_MT_RT_EX)) #pragma message ("Using C Run-Time Library global thread start routine.") //#error "C Run-Time Library global thread start routine not supported." void execute(void *args); #elif defined(_MT) && defined(_MT_RT_EX) #pragma message ("Using C Run-Time Library extension global thread start routine.") //#error "C Run-Time Library extension global thread start routine not supported." unsigned __stdcall execute(void *arg); #else DWORD execute(LPVOID args); #endif #else #pragma message ("GLOBAL_START_ROUTINE not defined, do not using global thread start routine.") // If GLOBAL_START_ROUTINE not defined, for thread start routine function details, See Thread class // declaration when user defined macro defined #endif /** * * * */ class /*TK_API*/ Thread : public Runnable { private: DWORD threadID; Runnable *target; public: Thread(); Thread(const Runnable *runnable); #if ! defined _GLOBAL_START_ROUTINE #if defined(_MT) && (! defined(_MT_RT_EX)) #pragma message ("Using C Run-Time Library global thread start routine.") #error "C Run-Time Library global thread start routine not supported." #elif defined(_MT) && defined(_MT_RT_EX) #pragma message ("Using C Run-Time Library extension global thread start routine.") #error "C Run-Time Library extension global thread start routine not supported." #else static DWORD execute(LPVOID args); #endif #endif void start(); virtual void run(); }; #endif ====================================================================== /* * * * @AUTHOR ADA * @VERSION 1.0 * @SINCE 1.0 */ #include <stdio.h> #include <stdlib.h> #include <string> #include <windows.h> #include <log.h> #include "Thread.hpp" //#define _MT using namespace std; #if ! defined _GLOBAL_START_ROUTINE DWORD Thread::execute(LPVOID args) { Thread* t = (Thread *) args; t->run(); return 1; } #else #if defined(_MT) && (! defined(_MT_RT_EX)) void execute(void *args) { Thread* t = (Thread *) args; t->run(); } #elif defined(_MT) && defined(_MT_RT_EX) unsigned __stdcall execute(void *arg) { Thread* t = (Thread *) args; t->run(); return 0; } #else DWORD execute(LPVOID args) { Thread* t = (Thread *) args; t->run(); return 1; } #endif #endif /** * * * */ Thread::Thread() { this->threadID = 0; this->target = NULL; } Thread::Thread(const Runnable *runnable) { this->threadID = 0; this->target = (Runnable *) runnable; } void Thread::start() { #ifndef _GLOBAL_START_ROUTINE LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) Thread::execute; printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n"); #else LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) execute; printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n"); #endif ::CreateThread(NULL, 0, startRoutine, (LPVOID) this, 0, &(this->threadID)); debug("Thread %d started", this->threadID); } void Thread::run() { if (target != NULL) { target->run(); } else { debug("Thread::run()"); } } ================================================================================ #ifndef _MT #error "Compiler linking options /MT not specific" #endif #include <stdio.h> #include <windows.h> #include <process.h> #include "../Thread.hpp" #include "../LinkedLibrary.h" void start_address(void *arg) { printf("_beginthread start_address\n"); } unsigned __stdcall start_address_ex(void *arg) { printf("_beginthreadex start_address_ex\n"); return 0; } int main() { printf("Thread test\n"); #ifdef _MT printf("MT defined\n"); #endif unsigned long th; printf("Thread _beginthread test\n"); th = _beginthread(start_address, 0, NULL); printf("_beginthread return %ld\n", th); unsigned thread; // CREATE_SUSPENDED th = _beginthreadex(NULL, 0, start_address_ex, NULL, 0, &thread); Thread *t = new Thread(); t->start(); ExitThread(0); return 0; } =================================================================== DEBUG=../Debug PATH_VS=D:\usr\bin\Microsoft Visual Studio\VC98 CL="$(PATH_VS)\Bin\cl.exe" LINK="$(PATH_VS)\Bin\link.exe" INCLUDE="D:\usr\bin\Microsoft Visual Studio\VC98\Include" LIB="D:\usr\bin\Microsoft Visual Studio\VC98\Lib" INCLUDE_LIB_LOG=D:\home\admin\workstation\c\liblog LIB_LIB_LOG=D:\home\admin\workstation\c\liblog\Debug INCLUDE_MYSQL=D:\usr\srv\mysql51\include LIB_MYSQL=D:\usr\srv\mysql51\lib\debug INCLUDE_LUA=D:\usr\bin\Lua\5.1\include LIB_LUA=D:\usr\bin\Lua\5.1\lib liblog.lib: clean # using compiler linking options /MT, If compiles _beginthread edition of Thread $(CL) /GX /W3 /MT /DGLOBAL_START_ROUTINE /I $(INCLUDE) /I $(INCLUDE_LIB_LOG) /c /Fo$(DEBUG)/ ../Thread.cpp $(CL) /GX /W3 /MT /DGLOBAL_START_ROUTINE /I $(INCLUDE) /c /Fo$(DEBUG)/ ThreadTest__beginthread.cpp $(LINK) /LIBPATH:$(LIB) /LIBPATH:$(LIB_LIB_LOG) /LIBPATH:$(LIB_MYSQL) /LIBPATH:$(LIB_LUA) /OUT:$(DEBUG)/ThreadTest__beginthread.exe $(DEBUG)/*.obj cp ../liblog.dll $(DEBUG) clean: rm -Rf ./*.bak rm -Rf ./*.o rm -Rf ./*.obj rm -Rf ./*.exe rm -Rf ../Debug/*
C++ Thread class
/* * Thread that support cross platform and support global and local start routine, and support * Windows api and C Run-Time Library(even extension) on windows. * <p> * To implements a simple thread, only to overrides the run method. * * @author ada * @version 1.0 * @since 1.0 */ #include <windows.h> #if defined(_WIN32) && defined(_MT) #include <process.h> #endif #include "Runnable.hpp" #if ! defined THREAD #define THREAD // GLOBAL_START_ROUTINE is a user defined macro, likes a switch, to determine whether to // select global thread start routine or not. GLOBAL_START_ROUTINE can be defined in program, // or using compiler preprocessor options(PREPROCESSOR) /D to define user defined macro // GLOBAL_START_ROUTINE to compiles global start routine edition of Thread #if defined GLOBAL_START_ROUTINE #define _GLOBAL_START_ROUTINE #pragma message ("GLOBAL_START_ROUTINE defined, using global thread start routine.") // windows #ifdef _WIN32 // using compiler linking options /MT to compiles C Run-Time Library(_beginthread, _beginthreadex) // edition of Thread #if defined(_MT) && (! defined(_MT_RT_EX)) #pragma message ("Using C Run-Time Library global thread start routine.") //#error "C Run-Time Library global thread start routine not supported." void execute(void *args); typedef void (* LP_CRT_THREAD_START_ROUTINE)(void *args); #elif defined(_MT) && defined(_MT_RT_EX) #pragma message ("Using C Run-Time Library extension global thread start routine.") //#error "C Run-Time Library extension global thread start routine not supported." unsigned __stdcall execute(void *args); typedef unsigned (__stdcall * LP_CRT_EX_THREAD_START_ROUTINE)(void *args); #else DWORD execute(LPVOID args); #endif // linux #else void* execute(void *args); #endif // User defined macro GLOBAL_START_ROUTINE is not specific // Compiles global start routine edition of Thread using compiler preprocessor options(PREPROCESSOR) /D // to define user defined macro GLOBAL_START_ROUTINE #else #pragma message ("GLOBAL_START_ROUTINE not defined, do not using global thread start routine.") // If GLOBAL_START_ROUTINE not defined, for thread start routine function details, See Thread class // declaration when user defined macro defined #endif /** * * * */ class /*TK_API*/ Thread : public Runnable { private: #if defined(_WIN32) && defined(_MT) #ifdef _MT_RT_EX unsigned threadID; #else unsigned long threadID; #endif #else DWORD threadID; #endif Runnable *target; public: Thread(); Thread(const Runnable *runnable); #if ! defined _GLOBAL_START_ROUTINE // windows #ifdef _WIN32 #if defined(_MT) && (! defined(_MT_RT_EX)) #pragma message ("Using C Run-Time Library global thread start routine.") #error "C Run-Time Library global thread start routine not supported." #elif defined(_MT) && defined(_MT_RT_EX) #pragma message ("Using C Run-Time Library extension global thread start routine.") #error "C Run-Time Library extension global thread start routine not supported." #else static DWORD execute(LPVOID args); #endif // linux #else static void* execute(void *args); #endif #endif void start(); virtual void run(); }; #endif ====================================================================== /* * * * @AUTHOR ADA * @VERSION 1.0 * @SINCE 1.0 */ #include <stdio.h> #include <stdlib.h> #include <string> #include <windows.h> #include <log.h> #include "Thread.hpp" //#define _MT using namespace std; #if ! defined _GLOBAL_START_ROUTINE DWORD Thread::execute(LPVOID args) { Thread* t = (Thread *) args; t->run(); return 1; } #else #if defined(_MT) && (! defined(_MT_RT_EX)) void execute(void *args) { debug("start routine defined(_MT) && (! defined(_MT_RT_EX))"); Thread* t = (Thread *) args; t->run(); } #elif defined(_MT) && defined(_MT_RT_EX) unsigned __stdcall execute(void *args) { debug("start routine defined(_MT) && defined(_MT_RT_EX)"); Thread* t = (Thread *) args; t->run(); return 0; } #else DWORD execute(LPVOID args) { Thread* t = (Thread *) args; t->run(); return 1; } #endif #endif /** * * * */ Thread::Thread() { this->threadID = 0; this->target = NULL; } Thread::Thread(const Runnable *runnable) { this->threadID = 0; this->target = (Runnable *) runnable; } void Thread::start() { #if defined(_MT) && (! defined(_MT_RT_EX)) #ifndef _GLOBAL_START_ROUTINE LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) Thread::execute; printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n"); #else LP_CRT_THREAD_START_ROUTINE startRoutine = (LP_CRT_THREAD_START_ROUTINE) execute; printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n"); #endif #elif defined(_MT) && defined(_MT_RT_EX) #ifndef _GLOBAL_START_ROUTINE LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) Thread::execute; printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n"); #else LP_CRT_EX_THREAD_START_ROUTINE startRoutine = (LP_CRT_EX_THREAD_START_ROUTINE) execute; printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n"); #endif #else #ifndef _GLOBAL_START_ROUTINE LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) Thread::execute; printf("GLOBAL_START_ROUTINE not defined, do not using global thread start routine\n"); #else LPTHREAD_START_ROUTINE startRoutine = (LPTHREAD_START_ROUTINE) execute; printf("GLOBAL_START_ROUTINE defined, using global thread start routine\n"); #endif #endif #if defined(_MT) && (! defined(_MT_RT_EX)) debug("begin thread through _beginthread()"); threadID = _beginthread(startRoutine, 0, (void *) this); #elif defined(_MT) && defined(_MT_RT_EX) debug("begin thread through _beginthreadex()"); threadID = _beginthreadex(NULL, 0, startRoutine, (void *) this, 0, &(this->threadID)); #else ::CreateThread(NULL, 0, startRoutine, (LPVOID) this, 0, &(this->threadID)); #endif debug("Thread %d started", this->threadID); } void Thread::run() { if (target != NULL) { target->run(); } else { debug("Thread::run()"); } }
Windows下C/C++ 多线程同步(mutex)
#ifndef __LOCK #define __LOCK class Lock { public: virtual void lock() = 0; virtual void unlock() = 0; }; #endif ======================================= #include <windows.h> #include "Lock.hpp" #ifndef _MUTEX_LOCK #define _MUTEX_LOCK class MutexLock : public Lock { private: HANDLE mutex; public: MutexLock(); MutexLock(const char* name); void lock(); void lock(HANDLE mutex); void unlock(); void unlock(HANDLE mutex); HANDLE getMutex(); }; #endif ======================================== #include <stdlib.h> #include <stdio.h> #include <windows.h> #include "log.h" #include "MutexLock.hpp" MutexLock::MutexLock() { this->mutex = CreateMutex(NULL, FALSE, NULL); if (this->mutex == NULL) { DWORD error = GetLastError(); warn("create mutex error %d", error); } debug("MutexLock()"); } MutexLock::MutexLock(const char* name) { this->mutex = CreateMutex(NULL, FALSE, name); if (this->mutex == NULL) { DWORD error = GetLastError(); warn("create mutex error %d", error); } else { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { debug("mutex name %s already exists, use the existed mutex instead.", name); } } } void MutexLock::lock() { lock(this->mutex); } void MutexLock::lock(HANDLE mutex) { DWORD event = WaitForSingleObject(mutex, INFINITE); if (event == WAIT_FAILED) { DWORD error = GetLastError(); warn("wait error %d", error); } else if(event == WAIT_TIMEOUT) { debug("wait time out"); } else if(event == WAIT_ABANDONED) { debug("wait abandoned"); } } void MutexLock::unlock() { this->unlock(this->mutex); } void MutexLock::unlock(HANDLE mutex) { BOOL isr = ReleaseMutex(this->mutex); if (! isr) { DWORD error = GetLastError(); warn("release mutex error %d", error); } } HANDLE MutexLock::getMutex() { return this->mutex; } ======================================== #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include "../MutexLock.hpp" #include "../Thread.hpp" #ifndef MESSAGE_DESTINATION #define MESSAGE_DESTINATION class MessageDestination { private: MutexLock lock; int i; public: MessageDestination() { i = 0; } void add() { lock.lock(); i++; printf("[Producer] message %d\n", this->i); lock.unlock(); } void reduce() { lock.lock(); i--; printf("[Consumer] message %d\n", i); lock.unlock(); } }; #endif =========================================== #include <stdio.h> #include "../MutexLock.hpp" #include "../Thread.hpp" #include "MessageDestination.hpp" class MessageConsumer : public Thread { private: MessageDestination *destination; public: MessageConsumer() { this->destination = NULL; } void registerConsumer(MessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { this->destination->reduce(); } //Sleep(500); } } }; ========================================= #include <stdio.h> #include "../MutexLock.hpp" #include "../Thread.hpp" #include "MessageDestination.hpp" class MessageProducer : public Thread { private: MessageDestination *destination; public: MessageProducer() { this->destination = NULL; } void registerProducer(MessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { destination->add(); } //Sleep(5000); } } }; ========================================== #include "MessageDestination.hpp" #include "MessageProducer.hpp" #include "MessageConsumer.hpp" void main() { ///* MessageDestination *destination = new MessageDestination(); MessageProducer *producer = new MessageProducer(); producer->registerProducer(destination); producer->start(); MessageConsumer *consumer = new MessageConsumer(); consumer->registerConsumer(destination); consumer->start(); ExitThread(0); }
Windows下C/C++ 多线程同步(event)
#ifndef __LOCK #define __LOCK class Lock { public: virtual void lock() = 0; virtual void unlock() = 0; }; #endif =========================================================== #include <windows.h> #include "Lock.hpp" #ifndef _EVENT_LOCK #define _EVENT_LOCK class EventLock : public Lock { private: HANDLE event; public: EventLock(); EventLock(const char* name); virtual void lock(); void lock(HANDLE event); virtual void unlock(); void unlock(HANDLE event); HANDLE getEvent(); }; #endif ============================================================ #include <stdlib.h> #include <stdio.h> #include <windows.h> #include "log.h" #include "EventLock.hpp" EventLock::EventLock() { this->event = CreateEvent(NULL, FALSE, TRUE, NULL); if (this->event == NULL) { DWORD error = GetLastError(); warn("create event error %d", error); } debug("EventLock()"); } EventLock::EventLock(const char* name) { this->event = CreateEvent(NULL, FALSE, FALSE, name); if (this->event == NULL) { DWORD error = GetLastError(); warn("create event error %d", error); } else { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { debug("event name %s already exists, use the existed event instead.", name); } } } void EventLock::lock() { lock(this->event); } void EventLock::lock(HANDLE event) { DWORD e = WaitForSingleObject(event, INFINITE); if (e == WAIT_FAILED) { DWORD error = GetLastError(); warn("wait error %d", error); } else if(e == WAIT_TIMEOUT) { debug("wait time out"); } else if(e == WAIT_ABANDONED) { debug("wait abandoned"); } } void EventLock::unlock() { this->unlock(this->event); } void EventLock::unlock(HANDLE event) { BOOL isr = SetEvent(this->event); if (! isr) { DWORD error = GetLastError(); warn("release event error %d", error); } } HANDLE EventLock::getEvent() { return this->event; } ================================================================ #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include "../Lock.hpp" #include "../EventLock.hpp" #include "../Thread.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_DESTINATION #define TEST_EVENT_LOCK_MESSAGE_DESTINATION class TestEventLockMessageDestination { private: Lock *lock; //HANDLE hEvent; int i; public: TestEventLockMessageDestination() { lock = new EventLock(); //hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); i = 0; } void add() { lock->lock(); i++; printf("[Producer] message %d\n", this->i); /* if (i > 0) { SetEvent(hEvent); } */ lock->unlock(); } void reduce() { lock->lock(); /* if (i <= 0) { ResetEvent(hEvent); WaitForSingleObject(hEvent, INFINITE); } */ i--; printf("[Consumer] message %d\n", i); lock->unlock(); } }; #endif ============================================================== #include <stdio.h> #include "../Thread.hpp" #include "TestEventLockMessageDestination.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_PRODUCER #define TEST_EVENT_LOCK_MESSAGE_PRODUCER class TestEventLockMessageProducer : public Thread { private: TestEventLockMessageDestination *destination; public: TestEventLockMessageProducer() { this->destination = NULL; } void registerProducer(TestEventLockMessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { destination->add(); } Sleep(5000); } } }; #endif ====================================== #include <stdio.h> #include "../Thread.hpp" #include "TestEventLockMessageDestination.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_CONSUMER #define TEST_EVENT_LOCK_MESSAGE_CONSUMER class TestEventLockMessageConsumer : public Thread { private: TestEventLockMessageDestination *destination; public: TestEventLockMessageConsumer() { this->destination = NULL; } void registerConsumer(TestEventLockMessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { this->destination->reduce(); } Sleep(500); } } }; #endif ================================== #include "TestEventLockMessageDestination.hpp" #include "TestEventLockMessageProducer.hpp" #include "TestEventLockMessageConsumer.hpp" void main() { ///* TestEventLockMessageDestination *destination = new TestEventLockMessageDestination(); TestEventLockMessageProducer *producer = new TestEventLockMessageProducer(); producer->registerProducer(destination); producer->start(); TestEventLockMessageConsumer *consumer = new TestEventLockMessageConsumer(); consumer->registerConsumer(destination); consumer->start(); /* while(1) { Sleep(2000); } */ ExitThread(0); /* DWORD threadID; CreateThread(NULL, 0, Callback1, (LPVOID) NULL, 0, &threadID); printf("Thread %ld started...\n", threadID); CreateThread(NULL, 0, Callback2, (LPVOID) NULL, 0, &threadID); printf("Thread %ld started...\n", threadID); ExitThread(0); */ }
Windows下C/C++ 多线程同步
#include "Lock.hpp" #include "EventLock.hpp" #ifndef __SYNC #define __SYNC class Sync { private: protected: EventLock *lock; EventLock *block; public: Sync(); void wait(); void notify(); }; #endif ========================================== #include "EventLock.hpp" #include "Sync.hpp" Sync::Sync() { lock = new EventLock(); block = new EventLock(); } void Sync::wait() { block->setState(EventLock::NON_SIGNALED); lock->unlock(); block->lock(); lock->lock(); } void Sync::notify() { block->setState(EventLock::SIGNALED); } =========================================== #include <windows.h> #include "Lock.hpp" #ifndef _EVENT_LOCK #define _EVENT_LOCK class EventLock : public Lock { private: HANDLE event; public: const static int SIGNALED; const static int NON_SIGNALED; EventLock(); EventLock(const char* name); virtual void lock(); void lock(HANDLE event); virtual void unlock(); void unlock(HANDLE event); void setState(int state); HANDLE getEvent(); }; #endif ===================================== #include <stdlib.h> #include <stdio.h> #include <windows.h> #include "log.h" #include "EventLock.hpp" const int EventLock::SIGNALED = 1; const int EventLock::NON_SIGNALED = 0; EventLock::EventLock() { this->event = CreateEvent(NULL, FALSE, TRUE, NULL); if (this->event == NULL) { DWORD error = GetLastError(); warn("create event error %d", error); } debug("EventLock()"); } EventLock::EventLock(const char* name) { this->event = CreateEvent(NULL, FALSE, FALSE, name); if (this->event == NULL) { DWORD error = GetLastError(); warn("create event error %d", error); } else { DWORD error = GetLastError(); if (error == ERROR_ALREADY_EXISTS) { debug("event name %s already exists, use the existed event instead.", name); } } } void EventLock::lock() { lock(this->event); } void EventLock::lock(HANDLE event) { DWORD e = WaitForSingleObject(event, INFINITE); if (e == WAIT_FAILED) { DWORD error = GetLastError(); warn("wait error %d", error); } else if(e == WAIT_TIMEOUT) { debug("wait time out"); } else if(e == WAIT_ABANDONED) { debug("wait abandoned"); } } void EventLock::unlock() { this->unlock(this->event); } void EventLock::unlock(HANDLE event) { BOOL isr = SetEvent(this->event); if (! isr) { DWORD error = GetLastError(); warn("release event error %d", error); } } void EventLock::setState(int state) { if (state == EventLock::SIGNALED) { int error = SetEvent(this->event); if (! error) { DWORD e = GetLastError(); warn("error to set event object to signaled state"); } } else if(state == EventLock::NON_SIGNALED) { int error = ResetEvent(this->event); if (! error) { DWORD e = GetLastError(); warn("error to set event object to nonsignaled state"); } } } HANDLE EventLock::getEvent() { return this->event; } ========================================== #define _WIN32_WINNT 0x0400 #include <stdio.h> #include <windows.h> #include "../Sync.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_DESTINATION #define TEST_EVENT_LOCK_MESSAGE_DESTINATION class TestEventLockMessageDestination : public Sync { private: int i; public: TestEventLockMessageDestination() { i = 0; } void add() { lock->lock(); i++; printf("[Producer] message %d\n", this->i); if (i > 0) { this->notify(); } lock->unlock(); } void reduce() { lock->lock(); if (i <= 0) { this->wait(); } i--; printf("[Consumer] message %d\n", i); lock->unlock(); } }; #endif ======================================== #include <stdio.h> #include "../Thread.hpp" #include "TestEventLockMessageDestination.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_CONSUMER #define TEST_EVENT_LOCK_MESSAGE_CONSUMER class TestEventLockMessageConsumer : public Thread { private: TestEventLockMessageDestination *destination; public: TestEventLockMessageConsumer() { this->destination = NULL; } void registerConsumer(TestEventLockMessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { this->destination->reduce(); } //Sleep(500); } } }; #endif =================================================== #include <stdio.h> #include "../Thread.hpp" #include "TestEventLockMessageDestination.hpp" #ifndef TEST_EVENT_LOCK_MESSAGE_PRODUCER #define TEST_EVENT_LOCK_MESSAGE_PRODUCER class TestEventLockMessageProducer : public Thread { private: TestEventLockMessageDestination *destination; public: TestEventLockMessageProducer() { this->destination = NULL; } void registerProducer(TestEventLockMessageDestination *destination) { this->destination = destination; } void run() { while (1) { if (destination != NULL) { destination->add(); } //Sleep(5000); } } }; #endif ========================================== #include "TestEventLockMessageDestination.hpp" #include "TestEventLockMessageProducer.hpp" #include "TestEventLockMessageConsumer.hpp" void main() { ///* TestEventLockMessageDestination *destination = new TestEventLockMessageDestination(); TestEventLockMessageProducer *producer = new TestEventLockMessageProducer(); producer->registerProducer(destination); producer->start(); TestEventLockMessageConsumer *consumer = new TestEventLockMessageConsumer(); consumer->registerConsumer(destination); consumer->start(); ExitThread(0); }
Windows下网络编程Socket定义:WINSOCK2.H头文件SOCKET
通信_网络编程_WINDOWS下网络编程_SOCKET编程_VC中WINSOCK2.H头文件SOCKET.doc
通信 网络编程 WINDOWS SOCKET 编程 VC WINSOCK2.H 头文件
Socket ,形象点可以把它理解为插槽,就像电源插座上面的插孔(不过电源插座上面的插孔有一孔的,还有两孔的,甚至还有三孔的,不知道还有没有四孔的,到目前为止我还没有看过有这么多孔的插座)。电器设备通过一条电源线,一端通过插头插入到能够输送电源的另一端的插座接入另一端,自己的一端也通过插头插入到自己的一个插孔上,将自己和能够输送电源的另一端建立一条物理连接。通过这样的一条物理连接,输送电源的另一端便可以将电源源源不断的输送过来,为电器设备提供电源,电器设备才可以借电力运转。
Socket 就类似这种情况,应用程序之间需要通信,就需要建立连接(这里的连接不是逻辑上的连接,而是物理上的连接,无线在这里也暂且把它归为是物理上的连接,只是连接的媒介不同而已)。现在假设连接的线有了,两端的节点也有了,并且连接的线两端也都套了一个能插入的插头,要实现通信,通信的应用程序还需要分别提供一个插槽以便将两头的插头都插入到插槽,这就是 SOCKET !
以上只是举了些例子以便更形象的理解 Socket ,它只是逻辑上的概念, Sockets 也有专门的协议规范来标准化。在 rfc1928.txt 中,根据 OSI 模型, SOCKET 在概念上是一种位于应用层与传输层之间的中间层的网络传输协议。在实际实现上,例如在不同平台上的 Socket 的实现也有些差别。
在 WINDOWS 平台上, Socket 实现是在动态链接库 ws2_32.dll 中, VC 中的头文件 WINSOCK2.H 及 WINSOCK.H 有定义。
查看头文件定义,在 WINSOCK2.H 头文件中, SOCKET 由一个简单的类型定义将 SOCKET 定义为一个 u_int 类型,而 u_int 类型其实就是一个 unsigned int 类型:
/* * The new type to be used in all * instances which refer to sockets. */ typedef u_int SOCKET; |
typedef unsigned int u_int; |
创建 SOCKET
#if INCL_WINSOCK_API_PROTOTYPES WINSOCK_API_LINKAGE SOCKET WSAAPI socket( int af, int type, int protocol ); #endif // INCL_WINSOCK_API_PROTOTYPES |
INCL_WINSOCK_API_PROTOTYPES 定义
#ifndef INCL_WINSOCK_API_PROTOTYPES #define INCL_WINSOCK_API_PROTOTYPES 1 #endif
#ifndef INCL_WINSOCK_API_TYPEDEFS #define INCL_WINSOCK_API_TYPEDEFS 0 #endif
|
WINSOCK_API_LINKAGE 定义
#ifndef WINSOCK_API_LINKAGE #ifdef DECLSPEC_IMPORT #define WINSOCK_API_LINKAGE DECLSPEC_IMPORT #else #define WINSOCK_API_LINKAGE #endif #endif |
DECLSPEC_IMPORT 定义(在 WINNT.H 头文件中)
#if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC) || defined(_M_IA64)) && !defined(MIDL_PASS) #define DECLSPEC_IMPORT __declspec(dllimport) #else #define DECLSPEC_IMPORT #endif |
WSAAPI 定义
#ifdef WIN32
#define WSAAPI FAR PASCAL 。。。 。。。 #else /* WIN16 */
#define WSAAPI FAR PASCAL 。。。 。。。 #endif /* WIN32 */ |
创建 SOCKET 函数 socket 返回创建的 SOCKET ,类型如上定义。此函数传入三个参数:
int af,
int type,
int protocol
第一个参数 af 传入的是地址家族( address family ) , 也就是地址簇或者协议簇。
该参数在不同的系统下参数不一定相同,另外注意不同的版本可以使用的参数也不相同,可以参考相关文档。这里列出了所有要求的参数可用值。
参数 a. 地址族(与 TCP/IP 协议下的协议族等价)可以使用的参数如下
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_IPX AF_NS /* IPX protocols: IPX, SPX, etc. */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_VOICEVIEW 18 /* VoiceView */
#define AF_FIREFOX 19 /* Protocols from Firefox */
#define AF_UNKNOWN1 20 /* Somebody is using this! */
#define AF_BAN 21 /* Banyan */
#define AF_ATM 22 /* Native ATM Services */
#define AF_INET6 23 /* Internetwork Version 6 */
#define AF_CLUSTER 24 /* Microsoft Wolfpack */
#define AF_12844 25 /* IEEE 1284.4 WG AF */
#define AF_MAX 26
AF_UNIX // 表示 Unix 内部协议
AF_NS // 表示使用的是 Xerox NS 协议族
AF_IMPLINK// 表示 IMP 连接层
另外 AF_LOCAL 是用于 Unix/Linux 系统中本机进程间通信
第二个参数传入的是 SOCKET 类型,可传入的 SOCKET 类型如下:
参数 b.Socket 类型
可以取如下的一些值:
SOCK_STREAM 流套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW 未加工套接字(可以用它来接收原始的数据包,即不经过传输层的,常用来抓包)
SOCK_SEQPACKET 顺序包套接字
#define SOCK_STREAM 1 /* stream socket */
#define SOCK_DGRAM 2 /* datagram socket */
#define SOCK_RAW 3 /* raw-protocol interface */
#define SOCK_RDM 4 /* reliably-delivered message */
#define SOCK_SEQPACKET 5 /* sequenced packet stream */
第三个参数传入的是协议类型,可传入的协议类型如下:
参数 c.Socket 使用的协议类型
通常将此设为 0 即 IPPROTO_IP ,是因为协议类型可以根据 Socket 的类型来确定,比如 Sock_STREAM 就是使用 TCP 协议,而 SOCK_DGRAM 就是使用 UDP 协议。
其他的类型还有 :
#define IPPROTO_ICMP 1 /* control message protocol */
#define IPPROTO_IGMP 2 /* internet group management protocol */
#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
#define IPPROTO_TCP 6 /* tcp */
#define IPPROTO_PUP 12 /* pup */
#define IPPROTO_UDP 17 /* user datagram protocol */
#define IPPROTO_IDP 22 /* xns idp */
#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
网络编程-SOCKET-创建SOCKET-WINDOWS下socket函数声明问题
今天翻了下VC下SOCKET头文件WINSOCK2.H,又看了下socket函数的声明:
#if INCL_WINSOCK_API_PROTOTYPES
WINSOCK_API_LINKAGE
SOCKET
WSAAPI
socket(
int af,
int type,
int protocol
);
#endif // INCL_WINSOCK_API_PROTOTYPES
注意到#if INCL_WINSOCK_API_PROTOTYPES这个条件编译,通常我们是通过#if, #ifdef或者#ifndef来判断选择哪一部分来编译以及在#include时解决因为重复包含的问题。
但这里的#if INCL_WINSOCK_API_PROTOTYPES这个条件编译是啥意思?在WINSOCK2.H文件靠近开头的位置有有如下定义:
#ifndef INCL_WINSOCK_API_PROTOTYPES
#define INCL_WINSOCK_API_PROTOTYPES 1
#endif
也就是INCL_WINSOCK_API_PROTOTYPES始终被替换为1,那么既然为1,干嘛还需要这样一个条件?
Windows CryptoAPI
// win32-test.cpp : 定义控制台应用程序的入口点。 // // Defines the entry point for the console // application. #include "stdafx.h" #include <tchar.h> #include <stdio.h> #include <windows.h> #include <wincrypt.h> #include <conio.h> #include <atlenc.h> #include "encrypt.h" // Link with the Advapi32.lib file. #pragma comment (lib, "advapi32") typedef struct { BYTE * keyData; int keyDataLen; } B_RSAW; typedef struct { char *keyData; int keDataLen; } RSAW; B_RSAW* RSA_key_w() { HCRYPTPROV hCryptProv = NULL; // handle to a cryptographic service provider (CSP) //--------------------------------------------------------------- // Get the handle to the default provider. // #param pszProvider Cryptographic Provider Names // MS_ENHANCED_PROV "Microsoft Enhanced Cryptographic Provider v1.0" CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_DELETEKEYSET); if(CryptAcquireContext( &hCryptProv, NULL, MS_ENHANCED_PROV, // "Microsoft Enhanced Cryptographic Provider v1.0" PROV_RSA_FULL, CRYPT_NEWKEYSET)) { _tprintf( TEXT("A cryptographic provider has been acquired. \n")); } else { return NULL; } HCRYPTKEY hKey;// handle of the key if(CryptGenKey( hCryptProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey)) { printf("A session key has been created.\n"); } else { printf("Error during CryptGenKey.\n"); exit(1); } DWORD dwTempPriLen; int r = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, NULL, NULL, &dwTempPriLen); BYTE *pbTempPriData = (BYTE *)malloc(dwTempPriLen+1); r = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, NULL, pbTempPriData, &dwTempPriLen); //------------------------------------------------------------------- // The key created can be exported into a key BLOB that can be // written to a file. // ... // When you have finished using the key, free the resource. if (!CryptDestroyKey(hKey)) { printf("Error during CryptDestroyKey.\n"); exit(1); } if (! CryptReleaseContext(hCryptProv, 0)) { printf("Error during CryptReleaseContext.\n"); exit(1); } B_RSAW *rsa = (B_RSAW *) malloc(sizeof(B_RSAW)); rsa->keyData = pbTempPriData; rsa->keyDataLen = dwTempPriLen; return rsa; } void RSA_key_write_RSAPrivateKey_W(const char* fn, B_RSAW* rsa) { FILE *fp = NULL; fp = fopen(fn, "wb"); if (fp == NULL) { fprintf(stderr,"%s open error", fn); } printf("file %s opened...\n", fn); fwrite(rsa->keyData, 1, rsa->keyDataLen+1, fp); fclose(fp); } RSAW* RSA_key_base64_w(B_RSAW *rsa) { //B_RSAW *rsa = RSA_key_w(); int len = Base64EncodeGetRequiredLength(rsa->keyDataLen, ATL_BASE64_FLAG_NONE); LPSTR szDest = (LPSTR) malloc(len + 1); memset(szDest, 0, len + 1); Base64Encode(rsa->keyData, rsa->keyDataLen, szDest, &len, ATL_BASE64_FLAG_NONE ); RSAW *_rsa = (RSAW *) malloc(sizeof(RSAW)); _rsa->keyData = szDest; _rsa->keDataLen = len + 1; return _rsa; } void RSA_key_write_RSAPrivateKey_base64_W(const char* fn, RSAW* rsa) { FILE *fp2 = NULL; fp2 = fopen(fn, "wb"); if (fp2 == NULL) { fprintf(stderr,"%s open error", fn); return; } //fwrite(rsa->keyData, 1, rsa->keyDataLen+1, fp); fprintf(fp2, "%s", rsa->keyData); //fclose(fp); fclose(fp2); } int _tmain(int argc, _TCHAR* argv[]) { /* if(argc < 3) { _tprintf(TEXT("Usage: <example.exe> <source file> ") TEXT("<destination file> | <password>\n")); _tprintf(TEXT("<password> is optional.\n")); _tprintf(TEXT("Press any key to exit.")); _gettch(); return 1; } */ B_RSAW *rsa = RSA_key_w(); char *fn = "D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\test-g-win.key"; RSA_key_write_RSAPrivateKey_W(fn, rsa); RSAW *_rsa = RSA_key_base64_w(rsa); char *fn2 = "D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\test-g-2-win.key"; RSA_key_write_RSAPrivateKey_base64_W(fn2, _rsa); /* LPTSTR pszSource = NULL; LPTSTR pszDestination = NULL; LPTSTR pszPassword = NULL; pszSource = L"D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\plain-text.txt"; pszDestination = L"D:\\home\\workspace1\\tst_edit\\MFCActiveXControl1\\win32-test\\encrypt-text.txt"; pszPassword = L"yihaodian"; //--------------------------------------------------------------- // Call EncryptFile to do the actual encryption. if(MyEncryptFile(pszSource, pszDestination, pszPassword)) { _tprintf( TEXT("Encryption of the file %s was successful. \n"), pszSource); _tprintf( TEXT("The encrypted data is in file %s.\n"), pszDestination); } else { MyHandleError( TEXT("Error encrypting file!\n"), GetLastError()); } */ return 0; }
有关 SOCKET 资料可参考:
维基百科 http://zh.wikipedia.org/wiki/SOCKS
IETF RFC 1928, rfc1928.txt, SOCKS Protocol Version 5
IETF RFC 1929, rfc1929.txt, Username/Password Authentication for SOCKS V5
各平台( Linux 、 Unix 、 Windows 等)对 SOCKET 的实现
互联网传输协议的性能优化: http://shop.zte.com.cn/main/include/showemagazinearticle.jsp?articleId=369&catalogId=12165
VC下相关工具
lib
>LIB.EXE /LIST liblog_static.lib
Microsoft (R) Library Manager Version 6.00.8168
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
.\Debug\SocketAppender.obj
.\Debug\LoggerWrapper.obj
.\Debug\log.obj
.\Debug\GenericAppender.obj
.\Debug\FileAppender.obj
.\Debug\AsynchronizedAppender.obj
.\Debug\Appender.obj
.\Debug\StandardAppender.obj
Makefile
Windows Make file(VC, NMAKE)
>NMAKE /f "nmake_test.mak" CFG="nmake_test - Win32 Debug" /y /d
@echo "$(OS)"
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
DEBUG=../Debug
PATH_VS=D:\usr\bin\Microsoft Visual Studio\VC98
CL="$(PATH_VS)\Bin\cl.exe"
LINK="$(PATH_VS)\Bin\link.exe"
INCLUDE="D:\usr\bin\Microsoft Visual Studio\VC98\Include"
LIB="D:\usr\bin\Microsoft Visual Studio\VC98\Lib"
INCLUDE_LIB_LOG=D:\home\admin\workstation\c\liblog
LIB_LIB_LOG=D:\home\admin\workstation\c\liblog\Debug
INCLUDE_MYSQL=D:\usr\srv\mysql51\include
LIB_MYSQL=D:\usr\srv\mysql51\lib\debug
liblog.lib: clean
$(CL) /GX /W3 /I $(INCLUDE) /c /Fo$(DEBUG)/ ../SQLException.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Mysql.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Connection.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlConnection.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlStatement.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../MysqlResultSet.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ ../Mysql.cpp
$(CL) /GX /W3 /I $(INCLUDE) /I$(INCLUDE_LIB_LOG) /I$(INCLUDE_MYSQL) /c /Fo$(DEBUG)/ MysqlTest.cpp
#$(CL) /GX /W3 /I $(INCLUDE) /c StdAfx.cpp
#$(CL) /GX /W3 /I $(INCLUDE) /c *.cpp
#$(CL) /GX /W3 /I $(INCLUDE) /c /Fo$(DEBUG)/ *.cpp
#lib /nologo log.obj /out:./liblog.lib
$(LINK) /LIBPATH:$(LIB) /LIBPATH:$(LIB_LIB_LOG) /LIBPATH:$(LIB_MYSQL) /OUT:$(DEBUG)/MysqlTest.exe $(DEBUG)/*.obj
#$(LINK) /DLL /LIBPATH:$(LIB) /OUT:$(DEBUG)/liblog.dll *.obj
#$(LINK) /DLL /LIBPATH:$(LIB) /OUT:$(DEBUG)/liblog.dll $(DEBUG)/*.obj
# $(LINK) *.obj /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib"
cp ../liblog.dll $(DEBUG)/
clean:
rm -Rf ./*.bak
rm -Rf ./*.o
rm -Rf ./*.obj
rm -Rf ./*.exe
rm -Rf ../Debug/*
VC命令行环境下生成.DLL, .LIB库
创建make文件
Makefile.nmake
make文件内容
DEBUG=./Debug
liblog.lib:
#"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c log.cpp
#"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c liblog.cpp
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\cl.exe" /GX /W3 /I "D:\usr\bin\Microsoft Visual Studio\VC98\Include" /c *.cpp
#lib /nologo log.obj /out:./liblog.lib
#"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /DLL /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:$(DEBUG)/liblog.dll log.obj
"D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" /DLL /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib" /OUT:$(DEBUG)/liblog.dll *.obj
# "D:\usr\bin\Microsoft Visual Studio\VC98\Bin\link.exe" *.obj /LIBPATH:"D:\usr\bin\Microsoft Visual Studio\VC98\Lib"
命令行下MAKE
nmake /f Makefile.nmake
wxWidgets
第一个简单的程序
下面是一个完整的程序,这是一个C++程序,这个程序中没有看到有入口函数。
#include "wx/wx.h" IMPLEMENT_APP(wxApp)
$ `wx-config --cxx` -c `wx-config --cxxflags --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0` window_test.cpp -o window_test.o
$ `wx-config --cxx` -o window_test window_test.o `wx-config --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0 --libs core,base`
可以通过以下命令看下程序是怎样的
$ `wx-config --cxx` -E `wx-config --cxxflags --unicode=yes --static=no --toolkit=osx_cocoa --version=3.0` window_test.cpp -o window_test.i
* int main(int argc, char **argv)
* {
* ;
* ;
* return wxEntry(argc, argv);
* }
*
* wxApp& wxGetApp()
* {
* return *static_cast<wxApp*>(wxApp::GetInstance());
* }
* wxAppConsole *wxCreateApp()
* {
* wxAppConsole::CheckBuildOptions("3" "." "0" " (" "wchar_t" ",compiler with C++ ABI " "1002" ",wx containers" ",compatible with 2.8" ")", "your program");
* return new wxApp;
* }
* wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);
窗口
#include "wx/wx.h" class MyApp : public wxApp { public: virtual bool OnInit(); }; class MyFrame : public wxFrame { public: MyFrame(const wxString& title); void OnExit(wxCommandEvent& WXUNUSED(event)) { Close(); } private: wxDECLARE_EVENT_TABLE(); }; wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_EXIT, MyFrame::OnExit) wxEND_EVENT_TABLE() IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { if (! wxApp::OnInit()) return false; MyFrame *frame = new MyFrame("主窗口"); frame->Show(true); return true; } MyFrame::MyFrame(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(500, 400)) { }
工具
wx-config
相关推荐
在Windows编程领域,开发者需要掌握一系列技术和工具来创建应用程序,这些应用程序可以与操作系统无缝交互,提供用户友好的界面和高效的功能。本课件主要聚焦于Windows编程的核心概念和技术,通过以下章节来深入探讨...
Windows 编程基础 本书将着重介绍 Windows 应用程序在 C# 环境下的开发应用,涵盖了 C# 编程基础和抽象的软件设计思想,为期望快速进入 C# Windows 程序设计领域的读者提供了一个适合的入门级教材。 课程简介 ...
在IT领域,Windows编程是开发桌面应用程序的重要组成部分。Windows编程主要涉及使用Microsoft的API(应用程序接口)和其他开发工具,如Visual C++(简称VC),来创建可以在Windows操作系统上运行的应用程序。以下是...
在Windows编程领域,新手往往面临着许多挑战,但随着丰富的学习资源和适当的指导,这些挑战将变得不再难以克服。本教程“Windows编程新手教程”旨在为初学者提供一个全面且易于理解的学习路径,涵盖基础概念、关键...
《Windows编程API手册》是一本深入探讨Windows操作系统编程核心的宝贵资源,主要涵盖了Windows API函数的使用和功能解析。Windows API是开发Windows应用程序的基础,它提供了丰富的函数接口,供程序员调用来实现各种...
《Windows编程基础与实践》PDF课程资料是一份全面介绍Windows编程的宝贵资源,尤其适合初学者入门学习。这份课件涵盖了从基础知识到高级技术的全方位内容,旨在帮助读者建立起扎实的Windows程序设计基础。 首先,...
《Windows编程:推箱子游戏开发详解》 在计算机科学领域,Windows编程是一项基础且重要的技能,它涉及到系统级的交互和应用开发。本教程将通过一个经典的“推箱子”游戏来深入探讨Windows编程的原理与实践。推箱子...
Windows 编程入门 Windows 编程入门是指使用微软的 Windows 操作系统进行软件开发的入门指南。本指南涵盖了 Windows 编程的基本理论、开发工具和框架、 Demo 实战等方面的知识点。 Windows 操作系统 Windows 操作...
VC++编程基础主要涵盖Windows API和MFC框架的使用,是初学者进入Windows编程领域的基础知识。Windows编程涉及一系列概念和技术,下面将详细阐述这些知识点。 首先,了解Windows编程基础至关重要,这包括可视化程序...
根据提供的文件信息,“Windows编程启示录.pdf”似乎是一本深入探讨Windows操作系统内部工作原理和技术细节的书籍。本书作者Raymond Chen是微软公司的资深员工,在Windows操作系统的发展历程中扮演了重要角色。下面...
在Windows游戏编程的世界里,Windows编程模型是构建游戏的基础,它是所有交互式应用程序的核心。这一章节将深入探讨如何利用Microsoft的Visual C++ 6.0(VC++6.0)来实现这一模型,并通过实例来加深理解。让我们一...
《Windows编程基础详解》 Windows编程是计算机科学领域的一个重要分支,主要涉及在Windows操作系统平台上设计和开发应用程序。本教程将深入浅出地介绍Windows编程的基础知识,包括其历史、核心概念以及用户界面的...
武大国软 Windows编程实践 三个项目和实验报告 高分作业 包括:实验一:用Visual C++开发简单的WinAPI程序 实验二:用MFC开发计算器程序 实验三:用MFC开发简单文本查看程序 和总的实验报告
根据提供的文件信息,“C#Windows编程.pdf”似乎是一份关于使用C#进行Windows应用程序开发的技术文档。接下来将根据这份文档的标题、描述以及部分可见内容,深入探讨与C# Windows编程相关的几个关键知识点。 ### C#...
标题 "C++,Windows编程" 涉及到的是利用C++这一强大编程语言进行Windows平台下的应用程序开发。C++是一种通用、面向对象的编程语言,以其高效性、灵活性和广泛的库支持而闻名。Windows编程则涉及到如何利用Windows ...
《C# Windows编程》这本书是针对使用C#语言进行Windows应用程序开发的专业指南。它涵盖了从基础知识到高级技术的全面内容,旨在帮助读者掌握利用C#在Windows平台上构建高效、稳定和用户友好的应用程序的技能。 在C#...
《白话Windows编程》是一本面向初学者和中级程序员的指南,旨在用通俗易懂的语言讲解Windows操作系统下的程序开发技术,主要关注C++语言在Windows平台的应用。这本书深入浅出地介绍了如何使用C++进行Windows API编程...
### Windows编程(第6版) #### 书籍概览与作者介绍 《Windows编程》第六版是Charles Petzold的经典著作,专注于编写适用于Windows 8的Metro风格应用。本书由Microsoft Press出版,是一本针对消费者预览版的电子书...
《Windows编程循序渐进》是一本针对初学者和进阶者设计的教程,它旨在帮助读者逐步掌握Windows操作系统下的程序开发技术。该书随附的光盘包含了丰富的源代码和示例程序,使得理论学习与实践操作相结合,极大地提升了...