关于Run-time Library

2011-10-05 了无痕

?Run-Time Library是编译器提供的标准库,提供一些基本的库函数和系统调用。
我们一般使用的Run-Time Library是C Run-Time Libraries。当然也有Standard C++ libraries。
C Run-Time Libraries实现ANSI C的标准库。VC安装目录的CRT目录有C Run-Time库的大部分源代码。 C Run-Time Libraries有静态库版本,也有动态链接库版本;有单线程版本,也有多线程版本;还有调试和非调试版本。

?动态链接库版本:
/MD Multithreaded DLL 使用导入库MSVCRT.LIB
/MDd Debug Multithreaded DLL 使用导入库MSVCRTD.LIB

?静态库版本:
/ML Single-Threaded 使用静态库LIBC.LIB
/MLd Debug Single-Threaded 使用静态库LIBCD.LIB
/MT Multithreaded 使用静态库LIBCMT.LIB
/MTd Debug Multithreaded 使用静态库LIBCMTD.LIB

若要使用此运行时库

请忽略这些库

单线程 (libc.lib)

libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib

多线程 (libcmt.lib)

libc.lib、msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib

使用 DLL 的多线程 (msvcrt.lib)

libc.lib、libcmt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib

调试单线程 (libcd.lib)

libc.lib、libcmt.lib、msvcrt.lib、libcmtd.lib、msvcrtd.lib

调试多线程 (libcmtd.lib)

libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、msvcrtd.lib

使用 DLL 的调试多线程 (msvcrtd.lib)

libc.lib、libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib

VS2008环境下开发的某些程序在其他机器运行提示“由于应用程序配置不正确,应用程序未能启动”的问题,

2010-06-29 了无痕

VC9编译的程序在没有装过VC9(确切的说是.Net Framework3.5)的机器上运行时,如果提示“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题。”这个错误,那么就说明该程序动态链接了VC9的运行时库,(如果还用到了MFC,那么可能动态链接了VC9的MFC库,同理还有ATL库),以及缺少对应的manifest文件,程序在目标机器上没有找到这些库和配置文件,因此导致了这个错误。出现这种情况的VC9编译器可能存在3个版本,接下来分别阐明:

1、没有打过任何补丁的VS2008

该版本对应的CRT/MFC/ATL库的版本号为9.0.21022.8,这个版本号在后面会用到。这个版本的程序部署比较简单,直接把VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

2、打过SP1补丁的VS2008

打过该补丁后,系统中存在着两个版本的CRT/MFC/ATL库,版本号分别为9.0.21022.8和9.0.30729.1,这导致了manifest文件中记录的版本号和实际库的版本号不一致(程序要求它们的版本号一致才能运行)。这个版本的程序部署需要两个步骤,首先要使manifest文件中依赖项的版本号与实际库的版本号一致,均为9.0.30729.1,方法是在工程设置中增加一个宏定义_BIND_TO_CURRENT_VCLIBS_VERSION,该宏定义于C:\Program Files\Microsoft Visual Studio 9.0\VC\include\crtassem.h文件中,然后重新编译程序。接下来还是将VC安装目录下的redist目录(C:\Program Files\Microsoft Visual Studio 9.0\VC\redist)中需要的库以及对应的manifest文件拷贝到执行程序同目录下,然后修改manifest文件中依赖项的版本号为9.0.21022.8,这样使得程序误以为该目录下库的版本号为9.0.21022.8(实际上是9.0.30729.1版本),这样程序到任何机器上都能够正常运行了。

3、打过SP1补丁与SP1 ATL 安全更新 (KB973675)的VS2008

这是最新的更新。在SP1补丁之后,微软又于近日发布了一个用于智能设备的 Microsoft Visual Studio 2008 Service Pack 1 ATL 安全更新 (KB973675), 该补丁又将CRT/MFC/ATL库的版本号升级,为9.0.30729.4148,这次升级比较好,manifest文件与库的版本号一致了,不像SP1一样升级的不彻底。这样只需要在工程设置中增加一个宏定义_BIND_TO_CURRENT_VCLIBS_VERSION,接下来重新编译程序,然后直接把VC安装目录下的redist目录中需要的库以及对应的manifest文件拷贝到执行程序同目录下,这样程序到任何机器上都能够正常运行了。

顺便提一下,如果不想在发布程序时带上这些库和manifest文件(如果没有必要的话),那么可以采用静态编译CRT和MFC,然后把manifest文件添加到资源中,这样编译出的程序只要一个exe就可以在任何机器上直接运行了。

参考文章:

1、“应用程序配置不正确,程序无法启动”的解决方法资料收集:http://hi.baidu.com/fairysky/blog/item/e7a8366dbaa735f3431694c8.html

有的时候,你在Visual C++上面经过好几个月的辛勤努力,终于将程序编写完成并且测试完毕,然而当你试图在客户的发布机上运行刚写好的程序时,有可能会碰到类似下面的错误,操作系统告诉你“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”:

VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题 - tangxingqt - doomgnu的博客

一般情况下,这个问题都是由于程序不能找到所需要的C运行库(CRT)而引起的。

在Windows XP SP2以后,Windows引入了Side-by-Side执行的概念,这个概念本来是.NET提出来的,但是Windows后来将这个概念集成到操作系统层面上来了。大家都应该知道Dll Hell的问题,为了解决Dll Hell的问题,Side-By-Side提出不同版本的dll文件可以同时存在于同一个系统里面,而且依赖于不同版本dll的应用程序在运行的时候可以使用到它当初被编译生成的dll。前面的话,有点绕,举个例子:

1.         假定你编写了一个C++程序A,是使用MFC 8.0(这个版本是随着Visual Studio 2005)发布的。

2.         之后你的机器升级了Visual Studio的版本,从2005升级到2008,2008的MFC库是9.0版本的,这个时候你的操作系统里面安装了两个版本的MFC,分别是8.0和9.0。

3.         你在Visual Studio 2008编写了另外一个C++程序B,B依赖与MFC 9.0。

4.         如果你运行程序A的话,操作系统会将MFC 8.0加载到A的进程里面。

5.         如果你这时同时运行程序B,操作系统会将MFC 9.0加载到B的进程里面。这就是Side-by-side的执行概念。

操作系统之所以能够这样做,是因为它在加载程序A和B之前,除了查看PE格式里面A和B所依赖的Dll信息,都会查看A和B的manifest文件。Manifest文件保存了Windows可执行文件(包括exe和dll文件)要运行起来的环境设置信息,文件名一般是可执行文件的文件全名加上.manifest。例如notepad.exe的manifest文件就应该是notepad.exe.manifest。例外有的程序将manifest文件直接嵌入到可执行文件的资源里面了,这也就是为什么有的时候你看不到程序的manifest文件的原因。通常来说,一个manifest文件的内容如下(test.exe.manifest文件):

 

<?xml version=’1.0′ encoding=’UTF-8′ standalone=’yes’?>

<assembly xmlns=’urn:schemas-microsoft-com:asm.v1′ manifestVersion=’1.0′>

 <trustInfo xmlns=”urn:schemas-microsoft-com:asm.v3″>

    <security>

      <requestedPrivileges>

        <requestedExecutionLevel level=’asInvoker’ uiAccess=’false’ />

      </requestedPrivileges>

    </security>

 </trustInfo>

 <dependency>

    <dependentAssembly>

      <assemblyIdentity type=’win32′ name=’Microsoft.VC90.DebugCRT’ version=’9.0.21022.8′

                        processorArchitecture=’x86′ publicKeyToken=’1fc8b3b9a1e18e3b’ />

    </dependentAssembly>

 </dependency>

</assembly>

上面的例子里面,就说明这个程序依赖于CRT 9.0,而且是调试版的,CPU架构是32位的CPU。对于将manifest文件嵌入到资源文件的程序我们也有办法看到manifest的信息。

1.         一种是使用mt.exe(Visual Studio自带的manifest处理程序):

mt -inputresource:test.exe;#1 /out:test.manifest

2.         另外一种是使用dumpbin程序将整个exe的内容打印到一个文件,然后用文本编辑器打开,搜索Assem字符串样式就能找到manifest信息:

VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题 - tangxingqt - doomgnu的博客 

解决方案

知道了程序依赖于具体哪一个dll以后,你可以将所依赖的dll拷贝到程序的安装文件夹里面,以CRT库绑定失败为例,介绍解决步骤:

1.         从上例中我们知道程序依赖的Microsoft.VC90.DebugCRT库,版本号是9.0.21022.8,需要32位机器版本的CRT。这个依赖项一般是因为你的程序是调试版,所以Visual Studio在编译的时候,将调试版的CRT加入程序的依赖项。

2.         从Visual Studio的安装文件夹里面将D:”Program Files”Microsoft Visual Studio 9.0″VC”redist”Debug_NonRedist”x86中的Microsoft.VC90.DebugCRT整个文件夹拷贝到应用程序所在的文件夹里面,注意:

a)         如果你的程序依赖的是32位的CRT,则要拷贝x86文件夹里面的Microsoft.VC90.DebugCRT文件夹,如果是先x64程序,则要拷贝x64文件夹里面。

b)         你需要确定Microsoft.VC90.DebugCRT文件夹里面的Microsoft.VC90.DebugCRT.manifest文件里面保存的版本信息而你程序依赖的版本信息匹配,Microsoft.VC90.DebugCRT.manifest里面的版本信息大版本号一定要一致,小版本号一定要等于或者大于你程序依赖的CRT的小版本号。比如上例中,我们的程序是依赖于CRT 9.0.21022.8,而我们的Microsoft.VC90.DebugCRT.manifest的版本是9.0.30729.1,这样是可以的;而8.0.30729.1就会有问题。如果大版本号一样,小版本号不一致的话,一个比较简单的方案就是修改程序的manifest文件,使其互相匹配就可以了。

3.         如果你的程序不是依赖调试版本的CRT,而是release版本的CRT,直接去微软的官方网站下载一个crt redist包安装上就可以了。

应用程序内存消耗和虚拟内存【1】

2010-04-20 了无痕

物理内存和虚拟内存

物理内存,在应用中,自然是顾名思义,物理上,真实的插在板子上的内存是多大就是多大了.看机器配置的时候,看的就是这个物理内存.

如果执行的程序很大或很多,就会导致物理内存消耗殆尽.为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张.

一个程序,不可避免地要用到虚拟内存,因为不频繁执行或者已经很久没有执行的代码,没有必要留在物理内存中,只会造成浪费;放在虚拟内存中,等执行这部分代码的时候,再调出来.
Windows 的任务管理器可以帮助我们看到进程的虚拟内存.调出任务管理器,点击菜单“查看”-“选择列”,在出现的窗口中,钩上“虚拟内存大小”,如下

点“确定”,这个时候,进程列表中已经显示各进程的虚拟内存大小,如下

一个程序到底应该使用多少虚拟内存呢?不一定,但是应该以恰到好处的符合虚拟内存原本作用为最好.

下面将揭穿表面看起来调用了大量图片、大量运行库的程序,为什么才“占用”不到 1 MB 的内存的诡计.

原来是 SetProcessWorkingSetSize 函数

MSDN 对该函数的表述(翻译):使用这个函数来设置应用程序最小和最大的运行空间,只会保留需要的内存.当应用程序被闲置或系统内存太低时,操作系统会自动调用这个机制来设置应用程序的内存.应用程序也可以使用 VirtualLock 来锁住一定范围的内存不被系统释放;当你加大运行空间给应用程序,你能够得到的物理内存取决于系统,这会造成其他应用程序降低性能或系统总体降低性能,这也可能导致请求物理内存的操作失败,例如:建立 进程,线程,内核池,就必须小心的使用该函数.

也就是说,该函数不是节省内存,而是强制把进程的物理内存搬到虚拟内存中.

另外有一些资料上说,该函数“将有可能导致缺页中断,严重影响性能”.
函数原型:
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
我们用 VB 来做这么一个简单的例子,是程序占用 300 KB 内存吧.

建立一个标准的 VB 工程,在 Form1 中放置一个 Timer1 ,把 Interval 属性设置为 1000 (即 1 秒).然后在代码编辑框中输入以下代码:

Private Declare Function SetProcessWorkingSetSize Lib "kernel32" (ByVal hProcess As Long, ByVal dwMinimumWorkingSetSize As Long, ByVal dwMaximumWorkingSetSize As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Sub Timer1_Timer()
SetProcessWorkingSetSize GetCurrentProcess(), 50000, 100000
End Sub

然后生成 工程1.exe,执行,调出任务管理器查看,发现内存占用才 320 KB.如果把定时器关闭,这进程的内存一般 4 MB左右.
必须定时执行该函数,否则虚拟内存会慢慢被调出来,恢复原来的内存大小.
如果要使一个本来需要占用大量内存的程序减低到几百 KB ,使用同样的方法即可.

诡计带来的危害

如果 SetProcessWorkingSetSize 函数被正常使用,是非常有用处的.但是为了蒙骗用户的眼睛,每秒,甚至几十毫秒就把大量内存往虚拟内存里面压,就会带来无可预计的危害.看看这篇文章怎么说:“因为他只是暂时的将应用程序占用的内存移至虚拟内存,一旦,应用程序被激活或者有操作请求时,这些内存又会被重新占用.如果你强制使用该方法来设置程序占用的内存,那么可能在一定程度上反而会降低系统性能,因为系统需要频繁的进行内存和硬盘间的页面交换.”.

没错,如果你使用了这类软件,意味着你的硬盘将每秒将 I/O 大量数据;硬盘的磁针将拼命旋转…(当然硬盘磁针不可能不旋转^_^,只是选择得更厉害而已).

不是说 BT 很伤内存吗?不然,因为现在大多 BT 软件都有缓存技术.且看 Bitcomet 官方对缓存技术的说明:“传统BT高速下载时硬盘会响得很厉害,这是大量的随机读取造成的…. BitComet可以由用户设置缓存大小…. 可以明显地看出牺牲一小部分内存作缓存对硬盘的保护作用.”

是不是有种心寒的感觉?一类软件宁愿牺牲内存,也要减少保护硬盘;而另外一类软件,却为了欺骗用户,让CPU、硬盘更加奔波……

抓一个凶手

这类软件不少,我以其中一个桌面工具为例,揭穿它的假面具(不点名字了).运行该软件后,随意操作一下,然后打开进程管理器,把虚拟内存列调出来。

OK,20 MB 虚拟内存,而只有 632 KB 物理内存.细心的你会发现,大概每 1 秒,该行都有闪烁的感觉,没错,这正是每秒调用 SetProcessWorkingSetSize 的结果.另外,我们打开 Norton Process Viewer ,查看该进程的 CPU 占用情况,可以看到,就算没有操作该软件,但是每秒,都有 3% 的CPU占用起伏(虽然这并不能说明什么).另外,内存框中可以看到物理内存和虚拟内存的占用,两者相去甚远.此外,可以用 Hook API 技术来证明每秒调用 SetProcessWorkingSetSize 的行为.

应该怎么做

这篇文章只想让用户了解软件占用资源的实际.而程序员应该把下功夫,真正从代码中减少内存的消耗,而不是一味忽悠用户.调用 SetProcessWorkingSetSize 会带来某些好处,但是何时调用、如何调用应该符合两个要求:
1,在程序暂时不被使用的时候(例如最小化);
2,物理内存和虚拟内存应处于一个合适的比例(而不是 600 KB 比 20 MB 这么荒唐);
3,或者不调用,让 Windows 去处理.

各种 C++ 字符串类型转换(char *、wchar_t*、_bstr_t、CComBSTR、CString、basic_string 和 System.String)

2010-04-08 了无痕

本主题演示如何将各种 C++ 字符串类型转换为其他字符串。可以转换的字符串类型包括 char *wchar_t*_bstr_tCComBSTRCStringbasic_stringSystem.String。在所有情况下,在将字符串转换为新类型时,都会创建字符串的副本。对新字符串进行的任何更改都不会影响原始字符串,反之亦然。

从 char * 转换

示例

说明

此示例演示如何从 char * 转换为上面列出的其他字符串类型。

// convert_from_char.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
 char *orig = "Hello, World!";
 cout << orig << " (char *)" << endl;

 // Convert to a wchar_t*
 size_t origsize = strlen(orig) + 1;
 const size_t newsize = 100;
 size_t convertedChars = 0;
 wchar_t wcstring[newsize];
 mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(orig);
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr(orig);
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a CString
 CString cstring(orig);
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a basic_string
 string basicstring(orig);
 basicstring += " (basic_string)";
 cout << basicstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String(orig);
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 wchar_t * 转换

示例

说明

此示例演示如何从 wchar_t * 转换为上面列出的其他字符串类型。

// convert_from_wchar_t.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
 wchar_t *orig = L"Hello, World!";
 wcout << orig << L" (wchar_t *)" << endl;

 // Convert to a char*
 size_t origsize = wcslen(orig) + 1;
 const size_t newsize = 100;
 size_t convertedChars = 0;
 char nstring[newsize];
 wcstombs_s(&convertedChars, nstring, origsize, orig, _TRUNCATE);
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(orig);
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr(orig);
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a CString
 CString cstring(orig);
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a basic_string
 wstring basicstring(orig);
 basicstring += L" (basic_string)";
 wcout << basicstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String(orig);
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (wchar_t *)
Hello, World! (char *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 _bstr_t 转换

示例

说明

此示例演示如何从 _bstr_t 转换为上面列出的其他字符串类型。

// convert_from_bstr_t.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
 _bstr_t orig("Hello, World!");
 wcout << orig << " (_bstr_t)" << endl;

 // Convert to a char*
 const size_t newsize = 100;
 char nstring[newsize];
 strcpy_s(nstring, (char *)orig);
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a wchar_t*
 wchar_t wcstring[newsize];
 wcscpy_s(wcstring, (wchar_t *)orig);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr((char *)orig);
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a CString
 CString cstring((char *)orig);
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a basic_string
 string basicstring((char *)orig);
 basicstring += " (basic_string)";
 cout << basicstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String((char *)orig);
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (_bstr_t)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CComBSTR 转换

示例

说明

此示例演示如何从 CComBSTR 转换为上面列出的其他字符串类型。

// convert_from_ccombstr.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
 CComBSTR orig("Hello, World!");
 CW2A printstr(orig);
 cout << printstr << " (CComBSTR)" << endl;

 // Convert to a char*
 const size_t newsize = 100;
 char nstring[newsize];
 CW2A tmpstr1(orig);
 strcpy_s(nstring, tmpstr1);
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a wchar_t*
 wchar_t wcstring[newsize];
 wcscpy_s(wcstring, orig);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(orig);
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CString
 CString cstring(orig);
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a basic_string
 wstring basicstring(orig);
 basicstring += L" (basic_string)";
 wcout << basicstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String(orig);
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (CComBSTR)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CString 转换

示例

说明

此示例演示如何从 CString 转换为上面列出的其他字符串类型。

// convert_from_cstring.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
 CString orig("Hello, World!");
 wcout << orig << " (CString)" << endl;

 // Convert to a char*
 const size_t newsize = 100;
 char nstring[newsize];
 strcpy_s(nstring, orig);
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a wchar_t*
 // You must first convert to a char * for this to work.
 size_t origsize = strlen(orig) + 1;
 size_t convertedChars = 0;
 wchar_t wcstring[newsize];
 mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(orig);
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr(orig);
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a basic_string
 string basicstring(orig);
 basicstring += " (basic_string)";
 cout << basicstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String(orig);
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (CString)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (basic_string)
Hello, World! (System::String)

从 basic_string 转换

示例

说明

此示例演示如何从 basic_string 转换为上面列出的其他字符串类型。

// convert_from_basic_string.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
 string orig("Hello, World!");
 cout << orig << " (basic_string)" << endl;

 // Convert to a char*
 const size_t newsize = 100;
 char nstring[newsize];
 strcpy_s(nstring, orig.c_str());
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a wchar_t*
 // You must first convert to a char * for this to work.
 size_t origsize = strlen(orig.c_str()) + 1;
 size_t convertedChars = 0;
 wchar_t wcstring[newsize];
 mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(orig.c_str());
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr(orig.c_str());
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a CString
 CString cstring(orig.c_str());
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a System::String
 String ^systemstring = gcnew String(orig.c_str());
 systemstring += " (System::String)";
 Console::WriteLine("{0}", systemstring);
 delete systemstring;
}

输出

Hello, World! (basic_string)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (System::String)

从 System::String 转换

示例

说明

此示例演示如何从 System.String 转换为上面列出的其他字符串类型。

// convert_from_system_string.cpp
// compile with /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
 String ^orig = gcnew String("Hello, World!");
 Console::WriteLine("{0} (System::String)", orig);

 pin_ptr<const wchar_t> wch = PtrToStringChars(orig);

 // Convert to a char*
 size_t origsize = wcslen(wch) + 1;
 const size_t newsize = 100;
 size_t convertedChars = 0;
 char nstring[newsize];
 wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
 strcat_s(nstring, " (char *)");
 cout << nstring << endl;

 // Convert to a wchar_t*
 wchar_t wcstring[newsize];
 wcscpy_s(wcstring, wch);
 wcscat_s(wcstring, L" (wchar_t *)");
 wcout << wcstring << endl;

 // Convert to a _bstr_t
 _bstr_t bstrt(wch);
 bstrt += " (_bstr_t)";
 cout << bstrt << endl;

 // Convert to a CComBSTR
 CComBSTR ccombstr(wch);
 if (ccombstr.Append(L" (CComBSTR)") == S_OK)
 {
 CW2A printstr(ccombstr);
 cout << printstr << endl;
 }

 // Convert to a CString
 CString cstring(wch);
 cstring += " (CString)";
 cout << cstring << endl;

 // Convert to a basic_string
 wstring basicstring(wch);
 basicstring += L" (basic_string)";
 wcout << basicstring << endl;

 delete orig;
}

输出

Hello, World! (System::String)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)

[转载] Install erlang and mochiweb on windows

2010-02-26 了无痕

1. 到 http://www.erlang.org/download.html 下载 erlang,当前的最新版本是
R13A, 下载后按提示安装,建议不要安装到有空格的路径,免得导致不必要的路径
问题,比如我的安装路径是 d:\programs\erl5.7,把 man 文档解压后,复制 man
子目录到上述安装路径下, 以下是具体要下载的文件:

http://www.erlang.org/download/otp_win32_R13A.exe (安装程序)
http://www.erlang.org/download/otp_doc_man_R13A.tar.gz (man 文档)

2. 配置 Emacs, 把下面这段内容加入你的 Emacs 配置文件

;; erlang
(add-to-list ‘load-path “d:/programs/erl5.7/lib/tools-2.6.3/emacs”)
(setq erlang-root-dir “d:/programs/erl5.7″)
(add-to-list ‘exec-path “d:/programs/erl5.7/bin”)
(require ‘erlang-start)
;; erlang manual
(require ‘woman)
(add-to-list ‘woman-manpath “d:/programs/erl5.7/man”)

3. 到 http://www.mingw.org/ 下载 MinGW, 安装后就可以使用make来编译程序

4. 安装 subversion for windows, 这样可以用 svn 来 checkout 出来 MochiWeb 的源码

5. 设置环境变量 PATH,加入如下路径

d:\programs\MinGW\bin
d:\programs\erl5.7\bin
d:\programs\GnuWin32\bin
d:\Programs\Subversion\bin

6. 到 http://downloads.sourceforge.net/gnuwin32/which-2.20-setup.exe 下载
which for windows,然后查看相关程序是否能正确找到

which -a which svn make erl escript
d:\programs\GnuWin32\bin\which.EXE
d:\Programs\Subversion\bin\svn.EXE
d:\programs\MinGW\bin\make.EXE
d:\programs\erl5.7\bin\erl.EXE
d:\programs\erl5.7\bin\escript.EXE

7. 获得 MochiWeb 的源码,比如我把它放在 d:/devel/erlang/mochiweb

cd d:/devel/erlang
svn co http://mochiweb.googlecode.com/svn/trunk/ mochiweb

8. 编译 MochiWeb 的源码

cd d:/devel/erlang/mochiweb
make

到此为止,如果一切正常的话,你已经有了一个完整的 erlang 环境,和一份已经
编译好的 MochiWeb。下一部分主要说明如何用 MochiWeb 来开发你自己的应用。

RAD Studio 2009 发布最新ISO 已集成Update1-4和HelpUpdate1

2010-01-30 了无痕

RAD Studio 2009 发布最新ISO 已集成Update1-4和HelpUpdate1
(请用下载工具下载,不要直接点击)

http://altd.embarcadero.com/download/Delphi_C++Builder2009/Delphi_C++Builder2009_ISO_June2009.iso

破解
方法1:
ftp://uploads@uploads.2ccc.com/JCD_Delphi2009v12.0.3420.21218Cracked.rar

方法2:
下载完后用Delphi2009V12.0.3420.21218Crack.exe进行破解,此文件已上传到FTP里了.
ftp://uploads@uploads.2ccc.com

CodeGear RAD Studio 2009 CHM 格式帮助文件下载[官方]
BlackfishSQL 帮助

http://docs.codegear.com/docs/radstudio/delphiAndcpp2009/GARelease/EN/chm/bfsql.chm

Common 帮助

http://docs.codegear.com/docs/radstudio/delphiAndcpp2009/GARelease/EN/chm/devcommon.chm

Win32 帮助http://docs.codegear.com/docs/radstudio/delphiAndcpp2009/GARelease/EN/chm/devwin32.chm
VCL 帮助

http://docs.codegear.com/docs/radstudio/delphiAndcpp2009/GARelease/EN/chm/delphivclwin32.chm

禁止联网 可用上一版本的bds替换

2009-6-8 0:23:48
31楼: 上传完后才发现FTP中已有破解过的BDS.EXE,不过在安装的时候可以用Delphi2009V12.0.3420.21218Crack.exe中的工具生成SN进行安装.

2009-6-10 16:26:57
33楼: ftp上的那两个bds.exe没用啊,用Distiller1.69有问题,运行老出错。有没有好点的破解啊?
———————————————-
-

2009-6-10 19:42:08
34楼: 先用Distiller1.69破解完后,再替换ftp上的BDS.exe,就可以完美地使用了,经检验3300版的一点问题也没有。我把版本号换成3420的,只是为了心理上的满足而已。不是欺骗,只是玩笑,哈,有的人真的认真,竟然揭穿我。
———————————————-

原来在运行破解工具后,需要按CTRL+ALT+L
会多一个选项卡出来,检查有Remove license..

RAD 2009 ISO 2009.06.12

http://altd.embarcadero.com/download/Delphi_C++Builder2009/Delphi_C++Builder2009_ISO_June2009.iso

试图运行项目时出错:无法在web服务器上启动项目得解决办法

2008-08-14 了无痕

1:确认在“配置属性”中的“启用ASP.NET调试"为"True"
操作步骤:
VS环境里面,菜单-项目-项目属性(最下得选项)-配置属性(左边第二项)-Debugging-Enable Asp.Net Debugging 设置为True
作用:
确定调试器能过启动IIS来调试asp.net页面!

2:确认你的"web.config"中的"debug=true"
操作步骤
打开web.config文件,设置debug="true";
作用:配置调试器可以调试该应用程序

3:在IIS里查看站点信息,选中"目录安全性",里面有"匿名访问和身份验证控制",再点击"编辑..",确认"集成Windows身份验证"选项被选中
操作步骤:
我的电脑-右击-管理-应用程序管理-IIS-默认网站-你得站点-右击-目录安全性-认证和访问方式-勾选匿名访问和身份验证控制,编辑-勾选确认"集成Windows身份验证“
作用:
匿名访问:此处设置不是为了解决你得调试问题,是为了能够使局域网或者广域网中其他用户通过输入你得Ip和网站名称来访问该网站
集成Windows身份验证:刚建立得网站身份验证方式为Windows要求必须用windows用户身份访问该网站,不更该IIS,将无法正常调试

5:在IE选项->"安全设置"->"自定义级别"里有"用户验证"->"登陆",确认选中"自动使用当前用户名和密码登录"
步骤上述已经详细
作用不详

6:重新注册Asp.Net版本到IIS
操作步骤;

在命令行中运行:
cd到C:\WINNT\Microsoft.NET\Framework\v1.0.3705\目录
aspnet_regiis.exe -i
或者start=all progames – visual studio.net 2003-visual studio.net tools – command prompt-aspnet_regiis.exe -i
作用:
重新注册当前得.net framework版本即(v1.0.3705)到iis,为了解决调试得时候出现您所运行得.net版本不是v1.1得问题

7:控制面板–管理工具–计算机管理–本地用户和组–用户,双击ASPNET用户,为其隶属于添加Administrators用户
步骤已祥,作用不知

Winsock Programmer’s FAQ 中文翻译 Section 3.7 What’s UDP?

2008-07-23 了无痕

问:什么是UDP?
答:
用户数据报协议是TCP的替代品。 通常所指的"TCP/IP" 包含了所有的基本的互联网技术,包括UDP。但是UDP/IP这个词仅仅表示在IP中的UDP。

当你将SOCK_DGRAM作为参数传递给函数socket(),winsock会返回一个UDP的套接字。

UDP是一种不可靠的协议:堆栈对数据丢失,重复包,以及乱序不做任何处理。UDP会检查数据完整性,但是一个损坏的数据仅仅是被悄悄地简单丢弃。

当数据包比网络的MTU(最大传输单元)大事,堆栈会将UDP包分包。而远端主机的堆栈会在江数据递交到上层应用之前进行组包。如果一个分包丢失或者被破坏,整个数据报就会被丢弃。这种规则使得大数据的传输很难实现:例如:MTU的值为1500字节,所以 一个8K大小的UDP数据包就需要被分成6个分包在网络上传输。 如果6个数据包中的任何一个丢失或者损坏,那么整个8K的数据都会被丢弃。

数据包的丢失也可能发生在发送端或者接受端,这通常是因为缓冲区空间不足。对于运行在同一机器上的并使用UDP的两个程序来说,数据丢失也常常可能发生。(这种情况常发生在Windows系统处于高负荷状态下,因为当缓冲区满后,系统就开始丢弃数据了。)这就将UDP的价值限制成本地的进程通信机制一样。

如过任何这种类型的数据丢失发生了,即使这样的丢失发生在堆栈内,也不会有任何通知发送给接收端或者发送端。

重复包并不会被丢弃:他们被提交给接收端。这依靠应用程序本上来检查到这个问题,并且由程序来决定如何来处理重复的数据。

UDP数据包可能会以任意顺序提交上去。当两个数据包通过不同的路由传输,而第二个路由恰巧比较快,数据常常会产生乱序。

注:使用UDP需要注意的地方上文已经讲得很清楚了,尽管存在这样那样的问题,但是并不妨碍UDP广泛的使用,比如视频传输等等对数据安全不那么高的应用。

Winsock Programmer’s FAQ 中文翻译 Section 3.6 What’s TCP?

2008-07-21 了无痕

 翻译:keo321
关键字:Winsock ,TCP, SOCK_STREAM, socket()
说明:转载请注明出处。

问:什么是TCP协议?

答:
传输控制协议(TCP)是一种可靠的流协议。 “Reliable(可靠)” 意味着套接字总能成功地将数据发送到远端主机:TCP能够处理数据丢失,数据损坏,重复包,包碎片等问题。“Stream”(流)表示,远端主机收到的数据是流形式的独立字节块。从程序的角度看,不存在包的概念。

当你将socket()的第二个参数设置为 SOCK_STREAM的时候,Windows套接字会创建一个TCP套接字。

TCP能够合并数据进行发送来提升效率:如果套接字4次调用send()来分别发送100字节,50字节,30字节, 120字节的数据,当TCP准备一起将这些数据发送到网络的时候,套接字可能会将所有的数据打包成一个300字节的TCP包。(这种方式被称为 Nagle算法。在后文会有详述)。

关于Delphi中使用FFMpeg avcodec模块出现C0000090错误(Floating-point invalid operation)

2008-07-17 了无痕

描述:
         Delphi中调用对avcodec模块,对数据进行编码。提示异常,错误码C0000090(Floating-point invalid operation).
        1. 经检查编码库的封装调用没有任何问题。
        2. 图像编码前保存后,图像数据正常。

解读:
        以下是从网上找到的相关资料,大致阅读一下了解出现异常的原因:
        Floating-point exceptions are, as you might expect by virtue of the name, rare. The ones that happen most commonly by mistake in my experience are the zero-divide and invalid operation exceptions. Zero divide tends to happen whenever you have an unchecked normalization operation, such as resetting a 2D or 3D vector to unit length — which works fine, until someone hands you a vector of length zero. Another example would be trying to normalize a portion of audio that was totally silent. When the zero-divide exception is masked, the FPU spits out a signed infinity instead, which sometimes works out in the end. For instance, if the expression is of the form |x/y| > n, then the infinity would give you the correct result.

     Invalid operation exceptions are more serious and result from operations that don’t have a graceful way to degrade, such as 0/0, the square root of -1, etc. These too often result from the lack of bounds checks. For instance, a common way to determine the angle between two vectors is through dot product, since the shortest angle between two vectors is acos(dot(v1 / |v1|, v2 / |v2|)). Unfortunately, the common way of normalizing vectors is to multiply by the reciprocal square root of the squared length (dot(v,v)), which can give you a not-quite-unit-length vector since the squaring operation discards half of the usual precision. This can then lead to taking the arccosine of a number slightly larger than 1. When such an operation occurs and invalid operation exceptions are masked, the FPU spits out a Not a Number (NaN) value and keeps going. You can also trip such an exception by trying to operate on NaNs, especially by loading garbage data that isn’t a valid IEEE finite number.

     In general, you don’t want to be tripping floating-point exceptions, even if they are masked. The reason is that when the FPU hits one, the fast hardware can’t handle it and punts to the microcode, which then takes about twenty times longer. This is especially bad with NaNs since any operation with a NaN produces another NaN, causing them to spread throughout your calculations (NaN disease) and slow down everything massively. You can even crash due to NaNs blowing past clamp expressions, since any comparison with a NaN is false and converting one to integer form results in integer indefinite (0×80000000). Despite the erroneous results, though, NaNs can appear sporadically in a large Win32 program without anyone knowing, and may go unnoticed in a code base for years.

     Note that although exceptions are really slow and usually indicate mistakes, the results when the exceptions are masked are well-defined. It is possible, and sometimes reasonable, to actually depend on and test for specific results from masked exceptions. So it isn’t valid to simply say "don’t do that."

      解决办法:
      When running floating point code, such as that found in Direct 3D, you will often get a series of floating point exceptions. Microsoft supporesses these exceptions by default, but we raise them. It is easy to turn this option off in both C++Builder and Delphi.

    C++ Bulider:
   

#include float.h__fastcall TForm1::TForm1(TComponent* Owner)    : TForm(Owner){  _control87(MCW_EM, MCW_EM);}

  Delphi:

  const    MCW_EM = DWord($133f);  begin    Set8087CW(MCW_EM);  end;

     

Xvid解码中的数据结构及相关规定

2008-07-10 了无痕

/*************************************************************
* Xvid解码中的数据结构及相关规定
* 说明:文档是在XvidCore.0.92版中有的,在后续的版本中没有再看到该文档,所以发出来给大家欣赏
* 希望会有所帮助。
* 更多的详细情况,可以到Xvid的邮件列表或者Xvid官网上看看,也希望可以同大家一起学习进步 *
 **************************************************************/

/* these are are structures/routines from xvid.h needed for decoding */

————————————————————————–

#define API_VERSION ((1 << 16) | (0))

This is the revision of the xvid.h file that you have in front of you.
Check it against the
library’s version.

————————————————————————–

typedef struct
{
 int cpu_flags;  [in/out]
 int api_version; [out]
 int core_build;  [out]
} XVID_INIT_PARAM;

This is filled by xvid_init with the correct CPU flags for initialization
(auto-detect), unless you pass flag to it (cpu_flags!=0). Do not use that
unless you really know what you are doing.
api_version can (should) be checked against API_VERSION, to see if you
have the right core library.

Used in:  xvid_init(NULL, 0, &xinit, NULL);

————————————————————————–

typedef struct
{
 int width; [in] (should be a multiple of 16, max is )
 int height; [in]    (should be a multiple of 16, max is )
 void *handle; [out]
} XVID_DEC_PARAM;

When creating decoder, you have to provide it with height and width of the
image to decode (this is _not_ in the bytestream itself!).
In handle a unique handle is given back, that has to be used to identify
this instance of decoding.

Used in:  xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL);

————————————————————————–

typedef struct
{
 void * bitstream; [in]
 int length;  [in]

 void * image;  [in]
 int stride;  [in]
 int colorspace;  [in]
} XVID_DEC_FRAME;

This is the main structure for decoding itself. You provide the
MPEG4-bitstream and it’s length,
image is the position where the decoded picture should be stored.
stride is the difference between the memory address of the first pixel of
a row in the image and the first pixel of the next row. If the image is
going to be one big block, then stride=width, but by making it larger you
can create an "edged" picture.
By colorspace the output format for the image is given, XVID_CSP_RGB24 or
XVID_CSP_YV12 might be might common.

A special case is XVID_CSP_USER. If you use this, then *image will not
filled with the image but with a structure that contains pointers to the
decoder’s internal representation of it. That’s faster, because no memcopy
is involved, but don’t use it, if you don’t know what you’re doing.

Used in:   xerr = xvid_decore(dechandle, XVID_DEC_DECODE, &xframe, NULL);

————————————————————————–

int xvid_decore(void * handle,  [in/out]
  int opt,  [in]
  void * param1,  [in]
  void * param2);  [in]

XviD uses a single-function API, so everything you want to do is done by
this routine. The opt parameter chooses the behaviour of the routine:

XVID_DEC_CREATE:   create a new decoder, XVID_DEC_PARAM in param1,
     a handle to the new decoder is returned in handle
   
XVID_DEC_DECODE:   decode one frame, XVID_DEC_FRAME-structure in param1

XVID_DEC_DESTROY:  shut down this decoder, do not use handle afterwards

Xvid编码中的数据结构及相关规定

2008-07-10 了无痕

+——————————————————————–+
  Xvid 结构及规定的简要说明
 –编码部分
说明:本文来自Xvid.org, 文档简单易懂,不再作翻译了!
希望对玩Xvid的朋友有帮助。更多的详细情况你可以访问Xvid.org

+——————————————————————–+

文档版本:
$Id: xvid-encoder.txt,v 1.3 2002/06/27 14:49:05 edgomez Exp $

+——————————————————————–+
| Abstract
+——————————————————————–+

This document presents the basic  structures and API of XviD. It tries
to explain how to use them  to obtain a simple profile compliant MPEG4
stream feeding the encoder with a sequence of frames.

+——————————————————————-+
| Document
+——————————————————————-+

 

     Chapter 1 : The XviD version
+—————————————————————–+

The  Xvid version  is defined  at library  compilation time  using the
constant defined in xvid.h

#define API_VERSION ((2 << 16) | (1))

Where 2 stands for the major XviD version, and 1 for the minor version
number.

The current version  of the API is 2.1 and  should be incremented each
time   a  user   defined  structure   is   modified  (XVID_INIT_PARAM,
XVID_ENC_PARAM … we will discuss about them later).

When you’re writing a program/library which uses the XviD library, you
must  check  your  XviD  API  version against  the  available  library
version.  We will  see how  to check  the version  number in  the next
chapter.

 

   Chapter 2 : The XVID_INIT_PARAM
+—————————————————————–+

typedef struct
{
int cpu_flags; [in/out]
int api_version; [out]
int core_build; [out]
} XVID_INIT_PARAM;

Used in:  xvid_init(NULL, 0, &xinit, NULL);

This tructure is  used and filled by the  xvid_init function depending
on the cpu_flags value.

List of valid flags for the cpu_flags member :

- XVID_CPU_MMX      : cpu feature
- XVID_CPU_MMXEXT   : cpu feature
- XVID_CPU_SSE      : cpu feature
- XVID_CPU_SSE2     : cpu feature
- XVID_CPU_3DNOW    : cpu feature
- XVID_CPU_3DNOWEXT : cpu feature
- XVID_CPU_TSC      : cpu feature
- XVID_CPU_IA64     : cpu feature
- XVID_CPU_CHKONLY  : command
- XVID_CPU_FORCE    : command

In order to set a flag : xinit.cpu_flags |= desired_flag_constant;

1st case : you call  xvid_init without setting the XVID_CPU_CHKONLY or
the XVID_CPU_FORCE flag, the xvid_init function detects auto magically
the host  cpu features and  fills the cpu_flags member.  The xvid_init
function also  performs all internal  function pointers initialization
according to deteced features and then returns XVID_ERR_OK.

2nd case :  you call xvid_init setting the  XVID_CPU_CHKONLY flag, the
xvid_init function will  just detect the host cpu  features and return
XVID_ERR_OK without  initializing the internal  function pointers (NB:
The XviD library is not usable after such a call to xvid_init).

3rd case  : you call  xvid_init with the cpu_flags  XVID_CPU_FORCE and
desired feature  flags set up  (eg : XVID_CPU_SSE |  XVID_CPU_MMX). In
this case you  force XviD to use the given cpu  features passed in the
cpu_flags member. Use this if you know what you’re doing.

NB for PowerPC  archs : the ppc arch has  not automatic detection, the
library must  be compiled  for a specific  ppc target using  the right
Makefile  (the  cpu_flags  is   irrevelevant  for  these  archs).  Use
Makefile.linuxppc   for   standard   ppc   optimized   functions   and
Makefile.linuxppc_altivec for altivec simd optimized functions.

NB for IA64 archs : There’s optimized ia64 assembly functions provided
in    the    library,    they     must    be    forced    using    the
XVID_CPU_FORCE|XVID_CPU_IA64 pair of flags.

To check the  XviD library version against your  own XviD header file,
you have just to call the xvid_init function (no matter the cpu_flags)
and  compare   the  returnded  xinit.api_version   integer  with  your
API_VERSION number. The core_build build member is not relevant at the
moment but is reserved for future  use (when XviD would have reached a
certain stability in its API and releases).

 

Chapter 3 : XVID_ENC_PARAM structure
+—————————————————————–+

Used in:    xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);

This structure has to be filled to create a new encoding instance:

- width and height.

They have to be set to the size of the image to be encoded.

- fincr and fbase (<0 forces default value 25fps – [25,1]).

They  are the  MPEG-way of  defining the  framerate.  If  you  have an
integer framerate, say 24,  25 or 30fps, use fincr=1, fbase=framerate.
However,  if   framerate  is  non-integer,  like   23.996fps  you  can
e.g. multiply  with 1000,  getting fincr=1000 and  fbase=23996, giving
you integer values again.

- rc_bitrate (<0 forces default value : 900000).

This  the desired  target bitrate.  XviD will  try to  do its  best to
respect this setting but keep in mind XviD is still in development and
it has not been tuned for very low bitrates.

- Any other rc_xxxx parameter are for the bit rate controler in order
   to  respect your  rc_bitrate setting  the best  it can.  (<0 forces
   default values)

Default’s are good enough and you should not change them.

ToDo :  describe briefly their impact  on the bit  rate variations and
the rc_bitrate setting respect.

- min_quantizer and max_quantizer (<0 forces default values : 1,31).

These  2 memebers limit  the range  of allowed  quantizers.  Normally,
quantizer’s range is [1..31], so min=1 and max=31.

NB : the HIGHER the quantizer, the LOWER the quality.
     the HIGHER the quantizer, the HIGHER the compression ratio. 

min_quant=1 is somewhat overkill, min_quant=2 is good enough max_quant
depends on what you encode, leave  it with 31 or lower it to something
like 15 or  10 for better quality (but encoding  with very low bitrate
might fail then).

- max_key_interval (<0 forces default value : 10*framerate == 10s)

This   is  the  maximum   value  of   frames  between   two  keyframes
(I-frames). Keyframes  are also inserted dynamically  at scene breaks.
It is important to have some  keyframes, even in longer scenes, if you
want to skip position in  the resulting file, because skipping is only
possible from  one keyframe to  the next. However, keyframes  are much
larger than non-keyframes, so do not use too many of them.  A value of
framerate*10 is a good choice normally.

- handle

This is the returned internal encoder instance.

 

      Chapter 4 : the XVID_ENC_FRAME structure.
+—————————————————————–+

typedef struct
{
int general; [in]
int motion; [in]
void *bitstream; [in]
int length; [out]
void *image; [in]
int colorspace; [in]
unsigned char *quant_intra_matrix;  [in]
unsigned char *quant_inter_matrix;  [in]
int quant;     [in]
int intra;     [in/out]
HINTINFO hint;     [in/out]
}
XVID_ENC_FRAME;

 

This is  the main structure to encode  a frame, it gives  hints to the
encoder on how to process an image.

- general flag member.

The general flag member informs XviD on general algorithm choices made
by the library client.

Valid flags :

    – XVID_CUSTOM_QMATRIX  :  informs  xvid  to use  the  custom  user
      matrices.

    – XVID_H263QUANT   :  informs  xvid   to  use   H263  quantization
      algorithm.

    – XVID_MPEGQUANT   :  informs  xvid   to  use   MPEG  quantization
      algorithm.

    – XVID_HALFPEL  : informs  xvid  to perform  a  half pixel  motion
      estimation.

    – XVID_ADAPTIVEQUANT  :  informs  xvid  to perform  an  adaptative
      quantization.

    – XVID_LUMIMASKING : infroms xvid to use a lumimasking algorithm.

    – XVID_LATEINTRA : ???

    – XVID_INTERLACING  : informs  xvid  to use  the MPEG4  interlaced
      mode.

    – XVID_TOPFIELDFIRST : ???

    – XVID_ALTERNATESCAN : ???

    – XVID_HINTEDME_GET  : informs  xvid to  return  Motion Estimation
      vectors from the ME encoder algorithm. Used during a first pass.

    – XVID_HINTEDME_SET :  informs xvid to  use the user  given motion
      estimation vectors as hints  for the encoder ME algorithms. Used
      during a 2nd pass.

    – XVID_INTER4V : forces XviD to search a vector for each 8×8 block
      within the 16×16  Macro Block. This mode should  be used only if
      the  XVID_HALFPEL mode is  activated (this  could change  in the
      future).

    – XVID_ME_ZERO : forces XviD to use the zero ME algorithm.

    – XVID_ME_LOGARITHMIC  :  forces   XviD  to  use  the  logarithmic
      ME algorithm.

    – XVID_ME_FULLSEARCH  : forces  XviD  to use  the  full search  ME
      algorithm.

    – XVID_ME_PMVFAST : forces XviD to use the PMVFAST ME algorithm.

    – XVID_ME_EPZS : forces XviD to use the EPZS ME algorithm.

ToDo :  fill the void entries  in flags, and describe  briefly each ME
algorithm.

- motion member.

Valid flags for  16×16 motion estimation (no XVID_INTER4V  flag in the
general flag).

    – PMV_ADVANCEDDIAMOND16  : XviD has  a modified  diamond algorithm
      that performs a bit faster  than the original one. Use this flag
      if  you want  to use  the  speed optimized  diamond serach.  The
      quality loss is  not big (better quality than  square search but
      less than the normal diamond search).

    – PMV_HALFPELDIAMOND16 : switches the search algorithm from 1 or 2
      full pixels precision to 1 or 2 half pixel precision.

    – PMV_HALFPELREFINE16  :  After normal  diamond  search, an  extra
      halfpel refinement step is  performed.  Should always be used if
      XVID_HALFPEL is  on, because it  gives a rather big  increase in
      quality.

    – PMV_EXTSEARCH16 :  Normal PMVfast predicts one  start vector and
      does diamond search around this position. EXTSEARCH means that 2
      more  start vectors  are used:  (0,0) and  median  predictor and
      diamond search  is done for  those, too.  Makes  search slightly
      slower, but quality sometimes gets better.

    – PMV_EARLYSTOP16 :  PMVfast and EPZS stop search  if current best
      is  below some dynamic  threshhold. No  diamond search  is done,
      only halfpel  refinement (if active).  Without EARLYSTOP diamond
      search is always done. That would be much slower, but not really
      lead to better quality.

    – PMV_QUICKSTOP16   :  like  EARLYSTOP,   but  not   even  halfpel
      refinement is  done. Normally worse  quality, so it  defaults to
      off. Might be removed, too.

    – PMV_UNRESTRICTED16   :  "unrestricted  ME"   is  a   feature  of
      MPEG4. It’s not  implemented, so this flag is  ignored (not even
      checked).

    – PMV_OVERLAPPING16 :  same as unrestricted.  Not implemented, nor
      checked.

    – PMV_USESQUARES16  : Replace  the  diamond search  with a  square
      search.

Valid flags  when using 4 vectors  mode prediction. They  have the same
meaning as their 16×16 counter part so we only give the list :

    – PMV_ADVANCEDDIAMOND8
    – PMV_HALFPELDIAMOND8
    – PMV_HALFPELREFINE8
    – PMV_EXTSEARCH8
    – PMV_EARLYSTOP8
    – PMV_QUICKSTOP8
    – PMV_UNRESTRICTED8
    – PMV_OVERLAPPING8
    – PMV_USESQUARES8

- quant member.

The quantizer value  is used when the DCT  coefficients are divided to
zero those coefficients not important (according to the target bitrate
not the image quality :-)

Valid values :

     – 0 (zero) : Then the  rate controler chooses the right quantizer
       for you.  Tipically used in ABR encoding or first pass of a VBR
       encoding session.

     – !=  0  :  Then you  force  the  encoder  to use  this  specific
       quantizer   value.     It   is   clamped    in   the   interval
       [1..31]. Tipically used  during the 2nd pass of  a VBR encoding
       session.

- intra member.

[in usage]
The intra value  decides wether the frame is going to  be a keyframe or
not.

Valid values :

    – 1 : forces the encoder  to create a keyframe. Mainly used during
      a VBR 2nd pass.

    – 0 :  forces the  encoder not to  create a keyframe.  Minaly used
      during a VBR second pass

    – -1   :  let   the  encoder   decide  (based   on   contents  and
       max_key_interval). Mainly  used in ABR  mode and dunring  a 1st
       VBR pass.

[out usage]

When first set to -1, the encoder returns the effective keyframe state
of the frame.

    – 0 : the resulting frame is not a keyframe

    – 1 : the resulting frame is a keyframe (scene change).

    – 2  : the resulting  frame is  a keyframe  (max_keyframe interval
      reached)

- quant_intra_matrix and quant_inter_matrix members.

These are  pointers to  to a pair  of user quantization  matrices. You
must set the  general XVID_CUSTOM_QMATRIX flag to make  sure XviD uses
them.

When set to NULL, the default XviD matrices are used.

NB : each time the matrices  change, XviD must write a header into the
bitstream, so  try not changing  these matrices very often.  This will
save space.

 

       Chapter 5 : The XVID_ENC_STATS structure
+—————————————————————–+

Used in:
  xerr = xvid_encore(enchandle, XVID_ENC_ENCODE, &xframe, &xstats);

In  this  structure the  encoder  return  statistical  data about  the
encoding process,  e.g. to be  saved for two-pass-encoding.   quant is
the quantizer  chosen for  this frame (if  you let ratecontrol  do it)
hlength  is  the  length  of  the  frame’s  header,  including  motion
information etc.  kblks, mblks, ublks are unused at the moment.

 

Chapter 6 : The xvid_encode function
+—————————————————————–+

int xvid_encore(void * handle,
int opt,
void * param1,
void * param2);

XviD uses a single-function API, so  everything you want to do is done
by  this routine.  The  opt  parameter chooses  the  behaviour of  the
routine:

XVID_ENC_CREATE:  create a  new encoder,  XVID_ENC_PARAM in  param1, a
handle to the new encoder is returned in handle.

XVID_ENC_ENCODE: encode one frame, XVID_ENC_FRAME-structure in param1,
XVID_ENC_STATS  in param2  (or  NULL,  if you  are  not interested  in
statistical data).

XVID_DEC_DESTROY: shut down this encoder, do not use handle afterwards.

 

typedef struct
{
int quant; // [out] frame quantizer
int hlength; // [out] header length (bytes)
int kblks, mblks, ublks; // [out]
} XVID_ENC_STATS;

Used in:
  xerr = xvid_encore(enchandle, XVID_ENC_ENCODE, &xframe, &xstats);

 

typedef struct
{
int width, height; [in]
int fincr, fbase; [in]
int rc_bitrate; [in]
int rc_reaction_delay_factor; [in]
int rc_averaging_period; [in]
int rc_buffer; [in]
int max_quantizer; [in]
int min_quantizer; [in]
int max_key_interval; [in]
void *handle; [out]
}
XVID_ENC_PARAM;

Winsock Programmer’s FAQ 中文翻译 Section 3.5 端口的选择

2008-07-09 了无痕

   翻译:keo321
   关键字:端口,IANA,getservbyname,服务器
   说明:转载请注明出处。

    问: 我正在写一个服务器程序,使用哪个端口比较好?

    答:  如果你正在写一个基于现有协议的服务器,一般都已经确定的端口与之匹配。 你可以在IANA(http://www.iana.org/)的网站上找到大多数的端口号。
         如果你正在写一个新协议的服务器,那么下面有一些规则和建议也许对你选择服务器端口有用:
  1. Ports 1-1023 被禁止在新协议中使用。 他们被IANA保留给标准协议比如Pop3 ,http(分别是110 ,80)。除非你的协议被IANA分配了一个在该范围内的端口,否则你需要在此之外找一个端口号。id Software(注:很牛的一家游戏公司,玩过Quake的兄弟们应该知道)选择666作为其DOOM服务器的端口是很聪明之举,但是它违反了这条准则。在Quake中,他们改正了这一点,使用了端口6112.

  2. 从端口1024 – 49151 是注册端口, 你可以从中选择端口使用。但是你需要知道的是,全世界的人都在从该区间中选择端口,因此你有必要注册你的端口或者检查当前端口分配列表(http://www.iana.org/assignments/port-numbers)。

  3. 端口49152 – 65535 是动态端口, 意味着系统会随机的使用这些端口(FTP协议为例,在传输过程中使用随机端口)。这并不是一个合适的选择范围,因为你的程序很可能和操作系统会为一个已分配的随机端口产生冲突。

  4.很多操作系统为客户端程序在1024-5000的范围内选择端口,你最好选择大于5000的端口号,但这并不像前面的规则那么严格。

  5.在5000-49151之间有足够的空闲端口供你选择。你需要避免一些比较花哨的号码,或者被人熟知的号码。人们倾向于选择这些端口是因为它们更容易记忆,但这更容易引起冲突。比如端口6969, 5150,22222等就不是个好的选择。

你应该考虑让你程序的端口可配置,比如你的程序运行在一台主机上,而另一个服务器也运行在上面并占用了端口。一种方法是使用getservbyname(),如果该功能返回一个端口,就使用这个,否则就使用默认的端口。这样用户可以通过更改SERVICES文件来更改端口,在WINNT系列系统下,该文件位于%WINSYSDIR%\DRIVERS\ETC ,对于95系列系统则位于C:\Windows目录下。

H.264开源编码器评测-Peter Lee

2008-07-08 了无痕
[Peter Lee]
20035月,当H.264编码标准草案发布时,很多人都觉得H.264太复杂,不宜实用。眨眼间3年过去了,以往的论断、疑惑被如今的现实冲洗的干干净净。随着硬件性能的提高和视频编码工作者对H.264的不断优化,如今的H.264已完全实用,最新的达芬奇芯片上能实现D1分辨率(720*480)视频的实时编码,而对于解码,普通的PC机就能实现x264编码的DVDrip电影的流畅播放。纵观过去的三年,有多少人对H.264倾注了热情和汗水才换来今天的成绩,而那些H.264的开源项目以及参与这些项目的开发者自然是功不可没。
本文评测的是作者接触过的H.264开源解码器,包括:JM decoder, T264 decoder, x264 decoder, ffmpeg libavcodec, Intel IPP simple player。评测的内容有:对H.264特性的支持、解码速度以及二次开发难易程度。
一、H.264开源解码器介绍
1JM decoder
JM decoderH.264的官方源码,通常也称为校验模型。其特点是支持特性好,实用性差。本文选用的程序是JM86,不支持high profile,因为本文不对high profile部分进行实验比较。
NOTE: JM一直没有做实用化方面的努力,所以其解码速度代表的是2003年的水平。
 
2T264 decoder
T264是国内的开源项目,T264 decoder的程序做过汇编优化,速度还可以,但只能解T264本身的码流。作者对T264 decoder version 0.142005-3-29)作了修改,支持baseline的解码。
 
3x264 decoder
x264本没有decoder,但其包含decoder的部分函数雏形,猜想作者在一开始时是准备实现decoder,后来可能是因为有了ffmpeg,就放弃了这个想法(纯粹属于猜测,呵呵)。
本文的x264 decoder是作者在x264 svn check out 2005.12.26的基础上实现的,支持baseline的解码。
 
4ffmpeg libavcodec
ffmpeg是一个大项目,它包含各种音视频标准的codec,还支持各类file format.avi, .mp4, .mkv and etc)的parsing。所以,很多开源项目都有直接或间接地采用了ffmpeg,如mplayer播放器就是直接采用了ffmpeg,而mpc播放器则是先采用了ffdshow filter,而ffdshow又采用了ffmpegffmpeg是一个非常棒的音视频编解码库,支持的标准非常全,而且编解码速度也很快。
本文实验采用的是cvs check out 2006.02.20的版本,作者对其中的apiexample demo进行了简单的修改,用于解码h.264码流
 
5Intel IPP simple player
IntelIPP库,全称为Integrated Performance Primitives,在Intel的各种处理器平台(IA-32, Itanium, xscale and etc)上实现了信号处理常用算法、常用数学运算及音视频编解码算法等等。IPP给我的第一感觉是,在Intel的处理器平台上,它实现的各种算法应该是最快的,至于实际结果如何,待等到实验比较后见分晓。
本文采用的IPP库版本为IA32 5.1.017 评估版
Intel IPP simple player是用于播放各种音视频文件的简单播放器,用c++实用,具体算法调用IPP库来实现。本文采用的simple player版本是5.0.017
 
二、对于H.264特性的支持
1JM86 decoder
support baseline, extended, main profile
 
2T264 decoder
baseline
 
3x264 decodeer
baseline
 
4ffmpeg libavcodec
support baseline, main profile, high profile except the feature: paff, mbaff…
 
5Intel IPP simple player
support baseline and main profile
 
三、评测条件
1、所用测试序列
1 所用测试序列
分辨率
序列名称
特点
编码帧数
QCIF
foreman
纹理复杂度一般
运动剧烈:画面人物和镜头均运动,还有场景的切换
300
CIF
foreman
同上
300
mthr_dotr
背景简单
画面人物运动幅度不大
100
mobile
纹理复杂度极高
运动形式丰富——画面有多个运动物体,但各运动物体运动方向规则且平缓,镜头也在移动
200
D1(720*480)
soccer2
镜头有移动,画面的足球运动员的运动也很剧烈
300
puppy
镜头无运动,画面中的玩具小狗也只有简单的运动
100
 
2、编码参数
编码程序:x264 svn check out 2006.05.06
参数设置示例:x264enc --frames 300 --no-cabac --qp 26 -o test.264 foreman.cif 352x288(相当于baseline
量化步长:2636
 
2、环境
CPU: Pentium4 2.4GHz, RAM: DDR 512M
OS: windows2000 professional+sp4
 
3、解码器程序编译环境
JM86 decoder: vc71 release
T264 decoder: vc71 release
x264 decodeer: vc71 release
ffmpeg libavcodec: MinGW
Intel IPP simple player: vc71 release + directX 9.0c sdk
 
4、解码参数设置
不保存重建序列(note: 是否保存重建序列对于解码速度的影响很大)
 
四、解码速度比较结果
待补充完整。。。
2 解码速度比较(单位:fps
分辨率
序列名称
量化步长
JM86 decoder
x264 decodeer
ffmpeg libavcodec
QCIF
foreman
26
50fps左右
684.93
1196
36
874.64
1916.67
CIF
foreman
26
15fps左右
168.44
303.86
36
190.11
503.37
mthr_dotr
26
182.82
421.28
36
200
634.62
mobile
26
129.28
190.07
36
173.01
353.46
D1(720*480)
soccer2
26
5fps左右
53.04
105.17
36
60.19
158.12
puppy
26
61.54
192.23
36
64.64
253.85
 
note
t264的解码程序能解jm baseline的码流,但无法解上面x264生成的码流,故无法给出实验结果。但通过对自身t264 fast mode码流的解码速度进行统计,t264 decoderx264 decoder,解码速度降低40%左右
Intel IPP simple player在我的电脑上编译未成功,在其它成功编译的电脑(xp系统,directx, vs.net, IPP均安装于C盘)上进行简单测试,其解码速度和ffmpeg的解码速度相比,降低10%左右
 
【简单结论】
解码速度:ffmpeg > IPP simple player > x264 decoder > t264 decoder > jm86 decoder
ffmpeg的编码速度为基准,假设为100fps,则:
IPP simple player90fps
x264 decoder50fps
t264 decoder30fps
jm86 decoder3fps
 
五、程序开发上的比较
我估计阅读本文的大部分读者都是搞开发的,因此,阅读过程中自然会思考如何在程序开发上借鉴或者采用以上开源的H.264解码器,下面就针对程序开发上的难易、适用场合等作个比较。
1JM86 decoder
适合写paper群体
 
2T264 decoder
3x264 decodeer
两者代码非常相似,所以就合在一起讲了。这两个源码的程序结构都比较清晰,支持vcgcc的编译环境,但对H.264的特性支持不好,解码速度和ffmpeg相比,还有差距。
 
4ffmpeg libavcodec
程序结构比较差,H.264解码的代码基本上在h264.c一个文件中,这个文件有8000多行,不利于阅读。
编译环境为gccMinGW,移植到vc下比较难(我尝试过)。
解码速度快(BTW: 通过doom9论坛了解到,目前最快的h.264解码器是CoreAVC decoder,比ffmpeg50%左右)。
对于H.264特性的支持好。
 
5Intel IPP simple player
分两个方面讲:
aIPP
我觉得是非常棒的,但实现的是H.264解码(IPP中也有H.264编码)的一些关键函数,如deblockdct,插值补偿等,不能直接拿来用。
其它的缺点:IPP库是商业软件,要money的,而且只支持Intel平台
bsimple player
开源,用c++写的,而且是directshow编程,也就是说只支持windows平台。
其解码速度比ffmpeg10%左右,我觉得原因不在于IPP库,而是simple player的代码不够完善。
 
 
  谨以本文对所有参与过H.264开源项目的开发者致以滔滔江水连绵不绝的敬意之情

网络营销十准则

2008-07-08 了无痕

现在作为电子商务核心的网络营销,掀起了网站建设新的高潮,以往大多企业网站只是注重展示,营销性不强,而当今企业建设网站更考虑的是营销,是以营销为导向的网站才能更好的为企业创造更大的利益。据网络营销学院统计分析,营销型网站最显注的参考标准有以下十条。

一、方便和易于维护的网站内容管理系统

企业网站建设经历过了html纯静态页面,动态的ASP页面,前一个有利于优化,但不利于维护,后一个利于维护,但不利于优化。现在需要可以操作的动态后台,而前台可以生成静态html。方便和易于管理的网站系统,可以减少企业的维护成本,增加网站内容的维护的快捷。

二、友善的用户体验

首先强调的是营销型网站是以营销为目的的网站,应采用div和css的架构,减少网页打开的速度,导航明确,没有死链接,页面之间有良好的链接。

三、良好的搜索引擎表现

搜索引擎作为网站推广的重要方法,在企业网站的建设中要考虑是否对搜索引擎有着良好的表现,每个页面要有相对应的标题、关键词、描述。

四、完好的内容支持

对于营销型网站,要有完好的网站内容,能更好的促进客户进一步了解产品或服务,客户常见的问题解答,这些内容可以更高的提高工作效率。

五、强大的在线沟通功能

对于营销型的网站来说,要利用网络的交互性,更好的为营销服务,在线的QQ,在线的客服,在线的留言回答。

六、完善的网站监测

作为营销型的网站,完善的网站监测,对网站的的来源,客户的信息进行详细的统计是特别重要的,这样就可以跟踪到客户的动向,对于企业的网站的效果统计,也可以用在后期网站的进一步改善与调整。

七、比较高的客户信任度

对企业网站来说,要提高自己的公信力,如相关的证件和证书,相关的媒体报道,企业地址和产品等真实的图片,还有以往用户的案例,都应放在网站上去,客户在网站上消费,信任你的网站才可能消费。

八、详细的联系方式

对于营销型的网站,要有企业详细的联系方式,地址的地图,方便于客户联系和找到企业。

九、在线支付和购买功能

在线支付和购买,这样会更好的方便网站营销,更好的促进客户消费,如果在自己的网站不方便操作,可以借助第三方平台。

十、完善的网站营销流程

对于网站营销的流程,需要详细的介绍和说明,便于客户操作或在线完成营销。

计算机行业发展方向

2008-07-08 了无痕

一、关于企业计算方向

  企业计算(Enterprise Computing)是稍时髦较好听的名词,主要是指企业信息系统,如ERP软件(企业资源规划)、CRM软件(客户关系管理)、SCM软件(供应链管理,即物流软件),银行证券软件,财务软件,电子商务/政务(包括各种网站),数据仓库,数据挖掘,商务智能等企业信息管理系统.

  企业计算领域对人才的需求显然永远是数量最大的,因为这是计算机应用最多的领域. 搞这方面的好处是:

  (1)人才需求量极大,从事企业计算的公司在IT企业中占了大多数。除非在专业上一无特长,一般在这一领域总能找到工作。

  (2)这方面的入门门槛相对较低(如果你的软件功底不是很深,可考虑这一领域)

  (3)这方面的大公司较多,大公司要赚大钱,所以多将精力花在企业计算业务上.如与正规高校软件学院同学目前实习的CitiCorp、HP、IBM、SAP、NEC等公司都属这一领域的公司。如果将来想到大公司找一份相对稳定的工作,从事这方面机会要大很多。

  但从事这一领域的缺点也是明显的:

  由于这方面的入门门槛相对较低,虽然这方面的人才需求量是最大的,但将来竞争对手会较多。您会发现,即使他原不是学IT专业的人,也许他突击几个月后,做得照样像模像样。特别是当您年纪渐大后,您可能会发现,后面的年轻人可能很容易追上你的水平。如果您将来到国外去工作,你可能会发现从事这领域的人更多且高手如云。当然,若您在这一领域经过多年企业经验,达到较高境界(如能设计软件架构),则身价永远是高的。国内在这方面人才领域的主要问题是,有经验的高手太少,皮毛了解的人太多。

  从事企业计算领域,最重要的技能型技术课程是(1)J2EE架构与程序设计(2)大型数据库系统(如Oracle)(3)基于UML的系统分析与设计。如果说还有什么重要的技能,还可将XML与Web Service技术包含进来,若您在这几个领域掌握较好,则不愁找不到工作。其中尤其以J2EE最为重要,目前J2EE已成为企业计算软件开发的最主要平台,也是正规高校软件学院的最重要课程之一。尽管该课程只能作为选修课,我们希望正规高校软件学院同学无论将来想从事何种方向,都应学一下J2EE课程,至少可为将来找工作备一手关键功夫。包括想从事嵌入式或其它领域的同学,也是很有必要学一下J2EE的,毕竟J2EE是目前最重要的平台之一,即使您将来不想从事企业计算领域,了解一下J2EE也是必要的,就像一门常识课程一样。其它与企业计算关系较密切的技能还包括:Dot Net架构与程序设计、软件测试技术、软件配置管理,该领域较高层次的技能包括数据仓库技术、构件与中间件技术、设计模式等。像通信协议分析与网络程序设计,Unix系统管理等也属有些关系的课程。02级本学期开设的企业计算课程不多,主要是J2EE、Oracle/MSSQL、UML等企业计算领域的最关键技能型技术课程都已学完了(但不知有多少同学学得较深入,将来找工作时会用到这些技能)。下学期我们将在该领域中拟再开设XML与Web Service技术、软件配置管理等课程。本学期开设的企业计算领域课程的确不多,但您应在空余时间将J2EE,DB、UML等技术再深入地钻研下去,一定要在某个领域有深入的掌握。只是跟着听课,即使学了再多课程也是没用处的,自己钻研下去才是最重要的。只一个J2EE便是博大精深的,足够你啃下去的,钻研下去,您会发现你还要学的相关知识还有很多(包括EJB、XML、Web Service、Design Pattern等)。

  虽然从事企业计算的人才很多,但以下企业计算领域无论国内外都属稀缺人才:

  (1)掌握大型ERP系统,主要是SAP系统,包括SAP Basis(系统管理)或SAP ABAP(编程)或SAP功能模块实施(特别是财务模块FI的实施)。SAP顾问身价是最高的,而且非常难找。其它大型ERP系统,掌握PeopleSoft、Oracle Finacial、J.D.Edward、Siebel等大型ERP软件系统的人也很值钱。这方面的人之所以身价奇高,主要是因为这些软件很专业,特别大,很难有D版可学习,只有特大企业(如世界500强,90%以上使用SAP)才用得起,而且必须有实际工作经验才能掌握。如果是一个个人人都很容易有机会接触的软件,那么这方面的人通常就不会稀缺。如果大家将来有机会接触学习这些大型ERP软件系统的机会,建议毫不犹豫地抓住,那将捧上一辈的金饭碗。在国外,会SAP的人特别值钱。物以稀为贵,这永远是颠扑不破的真理。SAP的价值不仅是因为他是一个ERP软件, 而是其中体现的现代企业管理理念(如根据订货需求自动安排原料采购和生产计划等)。一般500强公司绝不会像国内很多企业那样,用J2EE从头设计企业的ERP系统(即将是怎样的人力投入,而且设计出来的系统怎么可能是完善的?),一定都会使用SAP这样成熟的ERP软件。用不起SAP的公司可能会用J2EE设计ERP系统。

  (2)掌握IBM大型机技术的人,如S/390主机,MVS操作系统,JCL作业控制语言,COBOL程序设计语言,DB2关系数据库或IMS层次数据库,CISC中间件交易控制系统等IBM大型机专用技术。国内五大银行,以及国外绝大多数银行的后台系统使用的都是以上平台。IBM大型机号称永不宕机而且平台相对封闭(这样最安全),所以这些要求在24*7环境中连续运行的关键应用(术语叫mission critical applications)都采用IBM大型机。这方面的人才之所以稀缺,是因为会大型机的人都是老人(90年代以前搞IT的人),全世界新毕业的IT毕业生不可能再去学IBM大型机(这是一种相对“古老“的技术),没有新人补上,而银行的系统必须维持下去而且银行还要不断开发新业务(如新的存款品种),虽然对IBM大型机人才的绝对需求量不很大,但相对恒定,银行到哪里找这方面的新人,很难找到. 若好找,花旗软件也不会花那么大的代价去培训我们的实习同学了(去年培训20多个人,听说公司就花了数十万元培训费). 如果您将来到国外找工作,会IBM大型机可能是最好找工作的领域之一了,而且保证找的都是大银行等好工作,我以前教过的计算机专业90-94级的一些同学,凡是毕业后从事大型机开发的,现多在国外一些很好的公司工作(有几位同学在各国各公司跳来跳去,简直如履平地). 其实我觉得我们最幸福的同学就是在花旗软件做IBM大型机银行软件的同学,这样的机会太难得了.正规高校软件学院00级2+2班一位同学,当初放弃保研,看准在花旗软件做大型机并且非常努力,还未毕业,公司便派她到国外参加一个项目的开发,成了项目骨干,我觉得她当初选择是完全正确的(01级一位女同学刚刚也自愿放弃了保研机会去花旗做大型机,我们祝愿她将来也能有好的前景。其实像花旗软件主动安排并鼓励员工读在职研究生,这样开明的公司目前并不多的,在职读研也是一种不错的选择,又不会失去自己喜欢的实习工作机会,能兼顾),读书的最终目地还是为了工作. 如果您将来在国外找工作,根本没人管您是什么文凭,国外企业绝不会花冤枉钱,只会招有领域工作经验能立即上手的人,用最少的钱在限定的时间完成项目. 而在国内,因为人力成本较低,公司招聘一很多高学历的人才,尽管可能根本用不到这么高的学历,但国内的人力太便宜了,为什么不高消费一下人才呢?这样公司的门面还要好看些。

  .(3)其它如掌握数据仓库技术的人在国内也很少. 目前最主流的数据仓库平台应是ORACLE的数据仓库工具. 在国外,会一些特殊数据仓库的人,如NCR/TEREDATA的人非常难找.

  我们的同学现在年纪都很轻,年轻人充满热情,喜欢追逐一些热门技术,这当然正确的,毕竟学习SAP和大型机的机会毕竟不多,毕业时先能找到一份工作是重要的. 但我相信随着年纪的增长,大家将来慢慢都会思考的,掌握一项竞争对手较少的绝技的重要性,将来如果自己到国外工作什么技术最好找工作(对搞软件的人到国外工作或移民是最容易的,也许您现在不想,但我相信工作多年以后,很大一部分同学可能想到国外闯荡一下),你要考虑你今后一生的出路,什么样的绝技是最稳定最轻松最高收入的. 搞软件的人,当年纪大些时,您可能更向住像搞医学人的那样能更多靠经验吃饭,而不须整天像年轻人那样不得不去追逐不断出现的软件新技术,这个时候也许您也许会发现,如果您在SAP或大型机等方面有些绝技,您会有很大优势,因为这些较偏的领域其技术变化是相对很缓慢的.

  我还记得在2000年时我曾在业余时间与一位德国人合作面试一些IT人才到德国去,那时德方各公司发来的需求有很多是SAP和IBM大型机的,我们在众多应聘者中最后也未找到一个在这方面有经验,甚至是有一点经验的. 相反,掌握流行技术的人因太多而不很值钱.

  我们的同学将来找工作时,不仅要盯着国内市场,还要有一种放眼全球的眼光,对搞软件的人您将来完全可能到其它国家去工作. 尤其是在欧美、日本、新加坡等国家,对SAP(包括IBM大型机)人才的需求是很大的。毕竟比同学见得多些,提醒同学将来多留意有学习这些绝技的机会,一旦有机会建议当仁不让. 国内的人才市场可访问www.51job.com,国外的IT人才需求可访问www.hotjobs.com、www.workopolis.com、www.monster.com等著名网站。应经常访问这些网站,以了解市场对人才的具体需求,早做准备。

  以上对企业计算领域的观点,供大家参考.虽然观点未必正确,但确是直言不讳. 总之,每个人的脑袋都长在自己脖子上,每个人都应有自己的判断.

  还要注意,我以上纯粹是从将来就业的角度谈问题. 如果您将来准备到国外读书,则应重视基础课,像C,Assembly,OOP,Discrete Math,Data Structure,Opeating System,Database Principle,Network,Software Engineering,Compiler,Digital Circuit,Computer Graphics,Computer Component and Architecture等基础课,在国外大学IT专业中一般都能找到相同课程,若国内学过,到国外读书时一般可申请免修一部分. 但我也想提醒同学,如果您将来毕业时万一申请国外大学不成,不得不去找工作时,若只将精力花在这些IT专业学生都会的基础课上(传统IT教育模式), 未掌握一些像J2EE等技能型技术,是不容易找到一份工作的,我们已有同学有这样的教训。从找工作的角度讲,企业关心的不是您学过什么课程,而是关心您能做什么,有什么技能,能做什么项目。

  二、关于嵌入式系统方向

  嵌入式系统无疑是当前最热门最有发展前途的IT应用领域之一。嵌入式系统用在一些特定专用设备上,通常这些设备的硬件资源(如处理器、存储器等)非常有限,并且对成本很敏感,有时对实时响应要求很高等。特别是随着消费家电的智能化,嵌入式更显重要。像我们平常常见到的手机、PDA、电子字典、可视电话、VCD/DVD/MP3 Player、数字相机(DC)、数字摄像机(DV)、U-Disk、机顶盒(Set Top Box)、高清电视(HDTV)、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电控制系统、医疗仪器、航天航空设备等等都是典型的嵌入式系统。

  嵌入式系统是软硬结合的东西,搞嵌入式开发的人有两类。

  一类是学电子工程、通信工程等偏硬件专业出身的人,他们主要是搞硬件设计,有时要开发一些与硬件关系最密切的最底层软件,如BootLoader、Board Support Package(像PC的BIOS一样,往下驱动硬件,往上支持操作系统),最初级的硬件驱动程序等。他们的优势是对硬件原理非常清楚,不足是他们更擅长定义各种硬件接口,但对复杂软件系统往往力不从心(例如嵌入式操作系统原理和复杂应用软件等)。

  另一类是学软件、计算机专业出身的人,主要从事嵌入式操作系统和应用软件的开发。如果我们学软件的人对硬件原理和接口有较好的掌握,我们完全也可写BSP和硬件驱动程序。嵌入式硬件设计完后,各种功能就全靠软件来实现了,嵌入式设备的增值很大程度上取决于嵌入式软件,这占了嵌入式系统的最主要工作(目前有很多公司将硬件设计包给了专门的硬件公司,稍复杂的硬件都交给台湾或国外公司设计,国内的硬件设计力量很弱,很多嵌入式公司自己只负责开发软件,因为公司都知道,嵌入式产品的差异很大程度在软件上,在软件方面是最有“花头“可做的),所以我们搞软件的人完全不用担心我们在嵌入式市场上的用武之地,越是智能设备越是复杂系统,软件越起关键作用,而且这是目前的趋势。

  从事嵌入式软件开发的好处是:

  (1) 目前国内外这方面的人都很稀缺。一方面,是因为这一领域入门门槛较高,不仅要懂较底层软件(例如操作系统级、驱动程序级软件),对软件专业水平要求较高(嵌入式系统对软件设计的时间和空间效率要求较高),而且必须懂得硬件的工作原理,所以非专业IT人员很难切入这一领域;另一方面,是因为这一领域较新,目前发展太快,很多软硬件技术出现时间不长或正在出现(如ARM处理器、嵌入式操作系统、MPEG技术、无线通信协议等),掌握这些新技术的人当然很找。嵌入式人才稀缺,身价自然就高,越有经验价格就越高。其实嵌入式人才稀少,根本原因可能是大多数人无条件接触,这需要相应的嵌入式开发板和软件,另外需要有经验的人进行指导开发流程。

  (2) 与企业计算等应用软件不同,嵌入式领域人才的工作强度通常低一些(但收入不低)。搞企业应用软件的IT企业,这个用户的系统搞完了,又得去搞下一个用户的,而且每个用户的需求和完成时间都得按客户要求改变,往往疲于奔命,重复劳动。相比而言,搞嵌入式系统的公司,都有自己的产品计划,按自己的节奏行事。所开发的产品通常是通用的,不会因客户的不同而修改。一个产品型号开发完了,往往有较长一段空闲时间(或只是对软件进行一些小修补),有时间进行充电和休整。另外,从事嵌入式软件的每个人工作范围相对狭窄,所涉及的专业技术范围就是那些(ARM、RTOS、MPEG、802.11等),时间长了这些东西会越搞越有经验,卖卖老本,几句指导也够让那些初入道者琢磨半年的。若搞应用软件,可能下一个客户要换成一个完全不同的软件开发平台,那就苦了。

  (3) 哪天若想创业,搞自已的产品,那么嵌入式是一个不错的主意,这可不像应用软件那样容易被盗版。土木学院有一个叫启明星的公司开发出一个好象叫“工程e”的掌上PDA(南校区门口有广告),施工技术人员用该PDA可当场进行土木概预算和其它土木计算,据说销路特好。我认识的某大学老师,他开发的饭馆用的点菜PDA(WinCE平台,可无线连网和上网),据他说销路不错,饭馆点点PDA让客户点菜,多显派头档次。我记得00级2+2班当年有一组同学在学Windows程序设计课程时用VC++设计了一个功能很强的点菜系统做为课程项目,当时真想建议他们将这个软件做成PDA,估计会有些销路(上海火车站南广场的Macdonald便使用很漂亮的PDA给用户点食品,像摸像样的)。这些PDA的硬件设计一般都是请其它公司给订做(这叫“贴牌”:OEM),都是通用的硬件,我们只管设计软件就变成自己的产品了。

  从事嵌入式软件开发的缺点是:

  (1) 入门起点较高,所用到的技术往往都有一定难度,若软硬件基础不好,特别是操作系统级软件功底不深,则可能不适于此行。

  (2) 这方面的企业数量要远少于企业计算类企业。特别是从事嵌入式的小企业数量较多(小企业要搞自己的产品创业),知名大公司较少(搞嵌入式的大公司主要有Intel、Motorola、TI、Philip、Samsung、Sony、Futjtum、Bell-Alcatel、意法半导体、Microtek、研华、华为、中兴通信、上广电等制造类企业)。这些企业的习惯思维方式是到电子、通信等偏硬专业找人。由于正规高校软件学院以前毕业生以企业计算为主,所以正规高校软件学院与这些企业联系相对较少。正规高校软件学院正积极努力,目前已与其中部分公司建立了联系,争取今后能有正规高校软件学院同学到这些企业中实习或就业。

  (3)有少数公司经常要硕士以上的人搞嵌入式,主要是基于嵌入式的难度。但大多数公司也并无此要求,只要有经验即可。

  正规高校软件学院同学若学习嵌入式,显然应偏重于嵌入式软件,特别是嵌入式操作系统方面,应是我们的强项。对于搞嵌入式软件的人,最重要的技术显然是(实际上很多公司的招聘广告上就是这样写的):

  (1) 掌握主流嵌入式微处理器的结构与原理

  (2) 必须掌握一个嵌入式操作系统

  (3) 必须熟悉嵌入式软件开发流程并至少做过一个嵌入式软件项目。

  正规高校软件学院在嵌入式软件方面最重要的课程包括:

  (1) 嵌入式微处理器结构与应用:这是一门嵌入式硬件基础课程,正规高校软件学院用这门课取代了传统的“微机原理与接口”课程(目前国内已有少部分高校IT专业这样做了,因为讲x86微机原理与接口很难找到实际用处,只为教学而已)。我们说过,嵌入式是软硬件结合的技术,搞嵌入式软件的人应对ARM处理器工作原理和接口技术有充分了解,包括ARM的汇编指令系统。若不了解处理器原理,怎么能控制硬件工作,怎么能写出节省内存又运行高速的最优代码(嵌入式软件设计特别讲究时空效率),怎么能写出驱动程序(驱动程序都是与硬件打交道的)?很多公司招聘嵌入式软件人员时都要求熟悉ARM处理器,将来若同学到公司中从事嵌入式软件开发,公司都会给你一本该设备的硬件规格说明书 (xxx Specification),您必须能看懂其中的内存分布和端口使用等最基本的说明(就像x86汇编一样),否则怎么设计软件。有些同学觉得嵌入式处理器课程较枯燥,这主要是硬件课程都较抽象的原因,等我们的嵌入式实验室10月份建好后,您做了一些实验后就会觉得看得见摸得着。还有同学对ARM汇编不感兴趣,以为嵌入式开发用C语言就足够了。其实不应仅是将汇编语言当成一个程序设计语言,学汇编主要是为了掌握处理器工作原理的。一个不熟悉汇编语言的人,怎么能在该处理器写出最优的C语言代码。在嵌入式开发的一些关键部分,有时还必须写汇编,如Bootloader等(可能还包括BSP)。特别是在对速度有极高要求的场合(如DSP处理器的高速图像采集和图像解压缩),目前主要还要靠汇编写程序(我看到过很多公司是这样做的)。当您在一个嵌入式公司工作时,在查看描述原理的手册时,可能很多都是用汇编描述的(我就遇到过),这是因为很多硬件设计人员只会写或者喜欢用汇编描述,此时您就必须看懂汇编程序,否则软硬件人员可能就无法交流。很多嵌入式职位招聘时都要求熟悉汇编。

  (2) 嵌入式操作系统类课程

  除了WinCE的实时性稍差外,大多数嵌入式操作系统的实时性都很强,所以也可称为实时操作系统Real Time Operating System.从事嵌入式的人至少须掌握一个嵌入式操作系统(当然掌握两个更好),这在嵌入式的所有技术中是最为关键的了。目前最重要的RTOS主要包括:

  第一类、传统的经典RTOS:最主要的便是Vxworks操作系统,以及其Tornado开发平台。Vxworks因出现稍早,实时性很强(据说可在1ms内响应外部事件请求),并且内核可极微(据说最小可8K),可靠性较高等,所以在北美,Vxworks占据了嵌入式系统的多半疆山。特别是在通信设备等实时性要求较高的系统中,几乎非Vxworks莫属。Vxworks的很多概念和技术都和Linux很类似,主要是C语言开发。像Bell-alcatel、Lucent、华为等通信企业在开发产品时,Vxworks用得很多。但Vxworks因价格很高,所以一些小公司或小产品中往往用不起。目前很多公司都在往嵌入式Linux转(听说华为目前正在这样转)。但无论如何,Vxworks在一段长时间内仍是不可动摇的。与Vxworks类似的稍有名的实时操作系统还有pSOS、QNX、Nucleus等RTOS。

  第二类、嵌入式Linux操作系统:Linux的前途除作为服务器操作系统外,最成功的便是在嵌入式领域的应用,原因当然是免费、开源、支持软件多、呼拥者众,这样嵌入式产品成本会低。Linux本身不是一个为嵌入式设计的操作系统,不是微内核的,并且实时性不强。目前应用在嵌入式领域的Linux系统主要有两类:一类是专为嵌入式设计的已被裁减过的Linux系统,最常用的是uClinux(不带MMU功能),目前占较大应用份额,可在ARM7上跑;另一类是跑在ARM 9上的,一般是将Linux 2.4.18内核移植在其上,可使用更多的Linux功能(当然uClinux更可跑在ARM 9上)。很多人预测,嵌入式Linux预计将占嵌入式操作系统的50%以上份额,非常重要。缺点是熟悉Linux的人太少,开发难度稍大。另外,目前我们能发现很多教材和很多大学都以ucOS/II为教学用实时操作系统,这主要是由于ucOS/II较简单,且开源,非常适合入门者学习实时操作系统原理,但由于ucOS/II功能有限,实用用得较少,所以正规高校软件学院不将其作为教学重点,要学习就应学直接实用的,比如 uClinux就很实用。况且熟悉了Linux开发,不仅在嵌入式领域有用,对开发Linux应用软件,对加深操作系统的认识也有帮助,可谓一举多得。据我所知,目前Intel、Philip都在大搞ARM+LINUX的嵌入式开发,Fujitum则是在自己的处理器上大搞Linux开发。目前在嵌入式Linux领域,以下几个方面的人特别难找,一是能将Linux移植到某个新型号的开发版上;二是能写Linux驱动程序的人;三是熟悉Linux内核裁减和优化的人。正规高校软件学院在该嵌入式Linux方面的课程系列是:本科生操作系统必修课,然后是Linux程序设计选修课,最后是嵌入式Linux系统选修课。正规高校软件学院在Linux方面目前已有较强力量,魏老师和张老师熟悉Linux开发,金老师和唐老师熟悉Linux系统管理。

  第三类、 Windows CE嵌入式操作系统:Microsoft也看准了嵌入式的巨大市场,MS永远是最厉害的,WinCE出来只有几年时间,但目前已占据了很大市场份额,特别是在PDA、手机、显示仪表等界面要求较高或者要求快速开发的场合,WinCE目前已很流行(据说有一家卖工控机的公司板子卖得太好,以至来不及为客户裁减WinCE)。WinCE目前主要为4.2版(.NET),开发平台主要为WinCE Platform Builder,有时也用EVC环境开发一些较上层的应用,由于WinCE开发都是大家熟悉的VC++环境,所以正规高校软件学院学过Windows程序设计课程的同学都不会有多大难度,这也是WinCE容易被人们接受的原因,开发环境方便快速,微软的强大技术支持,WinCE开发难度远低于嵌入式Linux。对于急于完成,不想拿嵌入式Linux冒险的开发场合,WinCE是最合适了(找嵌入式Linux的人可没那么好找的),毕竟公司不能像学生学习那样试试看,保证开发成功更重要。根据不同的侧重点 ,WinCE还有两个特殊版本,一个是MS PocketPC操作系统专用于PDA上(掌上电脑),另一个是MS SmartPhone操作系统用于智能手机上(带PDA功能的手机),两者也都属于WinCE平台。在PDA和手机市场上,除WinCE外,著名的PDA嵌入式操作系统还有Palm OS(因出现很早,很有名)、Symbian等,但在WinCE的强劲冲击下,Palm和Symbian来日还能有多长?正规高校软件学院可能是全国高校中唯一一家开设专门的“Windows CE嵌入式操作系统“课程的学校,这主要是基于以下原因:正规高校软件学院本身前面便有Windows程序设计课程,同学学过VC++后再学WinCE,非常方便自然,通过学习WinCE同样也可了解嵌入式软件的一般开发过程,对Linux有惧怕心理的同学也很合适。很显然,嵌入式Linux永远不可能替代WinCE,而且将来谁占份额大还很难讲,毕竟很多人更愿意接受MS的平台,就像各国政府都在大力推LINUX已好长时间,但您能看到几个在PC机上真正使用LINUX的用户?据我观察,目前在嵌入式平台上,LINUX是叫得最响,但还是WinCE实际用得更多.嵌入式LINUX可能更多地是一些有长远产品计划的公司,为降低成本而进行长远考虑; 二是微软亚洲研究院对正规高校软件学院WinCE课程的支持计划,我们也很希望将来正规高校软件学院能有同学通过微软的面试去实习。WinCE和多媒体(如MPEG技术)是微软亚洲工程院目前做得较多的项目领域之一,他们很需要精通WinCE的人。

  总结关于嵌入式操作系统类课程,若您觉得自己功底较深且能钻研下去,则可去学嵌入式Linux;若您觉得自己VC++功底较好且想短平快地学嵌入式开发,则正规高校软件学院的WinCE课程是最好的选择。

  (3) 嵌入式开发的其它相关软件课程

  搞嵌入式若能熟悉嵌入式应用的一些主要领域,这样的人更受企业欢迎。主要的相关领域包括:

  A、数字图像压缩技术:这是嵌入式最重要最热门的应用领域之一,主要是应掌握MPEG编解码算法和技术,如DVD、MP3、PDA、高精电视、机顶盒等都涉及MPEG高速解码问题。为此,正规高校软件学院已预订了一位能开设数字图像处理课程的博士。

  B、通信协议及编程技术:这包括传统的TCP/IP协议和热门的无线通信协议。首先,大多数嵌入式设备都要连入局域网或Internet,所以首先应掌握TCP/IP协议及其编程,这是需首要掌握的基本技术;其次,无线通信是目前的大趋势,所以掌握无线通信协议及编程也是是很重要的。无结通信协议包括无线局域网通信协议802.11系列,Bluetooth,以及移动通信(如GPRS、GSM、CDMA等)。

  C、网络与信息安全技术:如加密技术,数字证书CA等。正规高校软件学院有这方面的选修课。

  D、DSP技术:DSP是Digital Signal Process数字信号处理的意思,DSP处理器通过硬件实现数字信号处理算法,如高速数据采集、压缩、解压缩、通信等。数字信号处理是电子、通信等硬件专业的课程,对于搞软件的人若能了解一下最好。目前DSP人才较缺。如果有信号与系统、数字信号处理等课程基础,对于学习MPEG编解码原理会有很大帮助。

  (4)嵌入式开发的相关硬件基础

  对于软件工程专业的学生,从事嵌入式软件开发,像数字电路、计算机组成原理、嵌入式微处理器结构等硬件课程是较重要的。另外,汇编语言、C/C++、数据结构和算法、特别是操作系统等软件基础课也是十分重要的。我们的主要目地是能看懂硬件工作原理,但重点应是在嵌入式软件,特别操作系统级软件,那将是我们的优势。

  我们的研究生里有些是学电子、通信类专业过来的,有较好的模拟电路和单片机基础,学嵌入式非常合适。嵌入式本身就是从单片机发展过来的,只是单片机不带OS,而现在很多嵌入式应用越来越复杂,以至不得不引入嵌入式操作系统。另外,为追求更高速的信号处理速度,现在在一些速度要求较高的场合,有不少公司是将一些DSP算法,如MPEG压缩解压缩算法等用硬件来实现,这就涉及到HDL数字电路设计技术及其FPGA/IP核实现技术,这方面的人目前市场上也很缺。

  (5) 题外话

  另外,能写驱动程序的人目前是非常紧缺的(驱动程序也可归于嵌入式范畴),包括桌面Windows中的DDK开发环境和WDM驱动程序。公司每时每刻都要推出新产品,每一个新产品出来了,要能被操作系统所使用,是必须写驱动程序的。写驱动程序就必须掌握操作系统(如Windows或Linux)的内部工作原理,还涉及到少量硬件知识,难度较大,所以这方面的人很难找。想成为高手的同学,也可从驱动程序方面获得突破。我可说一下自己的经历,三年前我曾短暂地在一家公司写过WinCE驱动程序(正是因为知道这方面的人紧缺,所以才要做这方面的事),尽管那以前从未做过驱动程序,应聘那个职位时正是看准了公司是很难招聘到这方面的人,既然都找不到人,驱动还得有人做,这正是可能有机会切入这一领域的大好机会。面试时大讲自己写过多少万行汇编程序,对计算机工作原理如何清楚,简历中又写着我曾阅读完两本关于Windows Driver Model的两本英文原版书,写过几个小型的驱动程序练习程序(其实根本没写过,我们的同学将来千万不要像我这样,早练就些过硬功夫,就不至于沦落到我这等地步,就不用像我那样去“欺骗”公司了,我这是一个典型的反面教材),居然一切都PASS(当然最重要的是笔试和面试问题还说得过去),这只能说明这一领域找人的困难程度。公司本就未指望找到搞过驱动的人,找个有相关基础的人就算不错了。做了以后,发现也并不是怎样难的。其实搞驱动程序的工作是很舒服的,搞完一个版本就会空一段时间,只有等公司新的芯片推出或新的OS出现后,才需要再去开发新一版驱动,那时有将近一个月时间空闲着在等WinCE .NET Beta版推出,准备将驱动程序升级到CE .NET上,现在在软件学院工作整日忙,无限怀念那段悠闲时光。

  很巧合,最近本人无意中再次体会到了嵌入式的迷人之处。上周我那用了3年的手机终于不能WORK了。此次更新,除要求有手机常见功能外,最好有MP3功能(现在很多英语听力都有MP3文件),最好有英汉词典,最好还能读WORD文档。最后选了个满足以上条件的最便宜的手机DOPOD 515(斩了我2.2K,但想想这也算自己对嵌入式事业的支持,这样便也想开了),算得上最低档的智能手机了。回来一查,手机的about显示,本手机Processor是ARM,其OS是MS Smartphone(即WinCE .NET 4.2),这么巧合,简直可做为学习嵌入式课程的产品案例了(等我们的WinCE课程开得有声有色后,希望能从微软研究院搞些Smartphone来开发开发)。有OS的手机果然了得,金山词霸、WORD、EXCEL、REGEDIT等居然都有smartphone版的,PC上的MP3、DOC等居然在download时都可被自动转换成smartphone格式,真是爽。完全可用Windows CE自己开发一些需要的程序download到自己的手机上。现在市面销售PDA智能手机火爆,MS总是财源滚滚。但我已发现国产的ARM+LINUX手机出现在市面上,价格只1.2K。

  在GOOGLE网上能搜索太多的关于嵌入式系统的讨论了,我刚发现一个http://www.embyte.com 非常不错,有很多有经验者谈自己的体会,投入到其中的论坛中,你会切身感到嵌入式学习的热潮。

  要么走ARM+WinCE,要么走ARM+LINUX,要么走ARM+VXWORKS。每个搞嵌入式的人都可选一条路,条条大路通罗马。

  三、关于游戏软件方向

  将游戏软件人才称为数字媒体软件人才可能更好听些,包括游戏软件策划(最缺游戏策划的人)、游戏软件美术设计、游戏软件程序设计等多方面的人才,对软件学院,游戏软件程序设计当然是最合适的了。

  游戏软件人才的确目前很缺,听说很多游戏软件公司苦于没新人才补充,特别是没有高手补充,不得不相互挖人才,以至将游戏软件人才身价越抬越高。网上说日本教育部刚刚批准成立了日本第一家专门培养四年制游戏软件人才的本科大学。其实国内很多大学,特别是软件学院都有搞游戏软件人才的设想,但目前很少有做成的,主要原因是找不到能上游戏软件课的教师,听说有个学校只能花很大的价钱从Korea找老师来上课,果真缺到此等地步?

  已有很多青少年沉湎于网游而颓废的实例,好在还不至于上升到制造精神鸦片的高度,所以开发游戏软件的人也不必每日惭悔(但开发儿童益智类游戏软件的人是不需惭悔的),如果想想这是为发展民族软件产业做贡献,那反倒是一件有意义的事情了。不过听一家游戏软件公司的老板讲,搞游戏软件开发是非常辛苦的。

  若想自己创业,搞搞游戏软件是不错的主意。现在网上网站或公司都在收购游戏软件(特别是手机游戏软件,因为手机游戏用户可选从网站上download到手机上,不像网游那么复杂),按download次数分成或一次性收购的都有。我们的同学在校期间是否也可发点小财?搞得好,说不定可卖到国外网站,直接挣$$$呢。

  大致游戏分成以下几类:

  (1) PC类游戏,包括单机和网游。这类游戏开发平台基本上都是基于VC++和DitrectX(如DirectShow,DirectDraw,D3D等,DirectX资料可直接到MS网站上查)。DirectX和OpenGL是两个主要的图形标准,OpenGL跨平台(Unix/Windows上都可跑),尽管很多搞研究的人对OpenGL赞不绝口,将DirectX骂得一文不值,但事实是,在Windows平台上,DirectX是最快最方便的,所以在Windows平台上的游戏还是DirectX当家。

  (2) 手机游戏:目前手机游戏主要开发平台有两类:

  第一类手机游戏是J2ME平台(Java 2 Micro Edition),J2ME本是为嵌入式平台设计的Java,但由于Java生来就需要Java虚拟机(JVM)来解释,所以在嵌入式产品很少用J2ME(太慢太耗内存)。但在手机游戏中J2ME倒有用武之地,我想这可能主要是Java可跨OS平台的原因,因为手机的OS是千奇百怪的。我对J2ME完全外行,但上次听Square Enix公司的人说,J2ME与我们同学学过的J2EE还是有较大差别的。据我所知,目前手机中用的较多的是KJava语言,KJava是运行在一种叫K Java Virtual Machine的解释器上(K JVM是SUN早期为演示J2ME在嵌入式系统应用而开发的一个虚拟机),所以将在K JVM上运行的J2ME叫KJava。尽管SUN说今后不保证支持K JVM,将开发新的更高性能的J2ME虚拟机取而代之,但由于KJava出现较早,很多早期的手机游戏软件都将K JVM假想成J2ME虚拟机的标准了,所以目前有大量的KJava手机游戏软件存在,而且还在用KJava继续开发。特别是日本的手机游戏软件由于开发较早(像叫什么docomi的日本最大的电信运营商手机游戏搞得很火),多是基于KJava的。所以目前市场上在招聘手机游戏软件人才时,很多要求掌握KJava。有关J2ME请到Sun的网站上找资料。

  另一类手机游戏是BREW平台,BREW是美国高通公司(Qualcomm,CDMA核心技术都是该公司开发的,有无数移动通信技术专利)发明的,据说可编译成二进制代码,那当然快了。主要的开发语言是C/C++。但迫于被指责为较封闭的压力,目前Qualcomm已推出BREW平台上的J2ME虚拟机(但可想像那将是怎样慢的速度)。Qualcomm搞定了很多手机制造商签定BREW授权许可协议,最狠的是Qualcomm与中国联通绑在一起大堆基于BREW的手机游戏,所以有些公司招聘时要求掌握BREW也就不奇怪了。

  去年00级2+2班毕业答辩时,有一位同学讲的是在公司做的KJava游戏(那是一家日本游戏软件公司),还一位同学讲的是另一家公司做的BREW游戏,看来不同的公司有不同的选择。将来谁会更火,我估计随着手机硬件资源的不断提高,不会在乎一个JVM的开销,J2ME应更有前途,毕竟它是更开放的。

  (3) 专用游戏机:如电视游戏,XBOX等,我不太了解,不过这些游戏也太偏了。

  从著名游戏公司发来的对网游和手机游戏的人才需求,很有代表性。从中我们可看出,游戏公司对人才的需求主要是以下技术:

  (1) 计算机图形学,特别是3D编程与算法,包括DirectX或OpenGL。开发平台是VC++/DIRECTX或KJAVA。

  (2) 公司说,手机游戏因手机资源有限,必须对图像进行压缩,所以若有一些图像压缩算法知识比较好。像若能有MPEG压缩算法较好,手机上采用的是比MPEG压缩得更狠的一些特殊算法,但触类旁通。

  (3) TCP/IP Socket编程是搞网游开发的人必须掌握的。

  (4) 人工智能知识:复杂游戏可能需要一些AI算法。

  (5) 网络与信息安全知识:网游要防外挂。

  一般游戏公司的网游服务器是基于Linux平台的,所以还提出了对游戏服务器端软件工程师的技术需求(精通MSSQL、ORACLE、MYSQL等数据库,精通Linux Programming,特别是Socket编程)。还有对维护游戏网站人才需求(ASP .NET和数据库)。详细请同学自己看服务器。注意一条,最好有自己的游戏软件作品,若您应聘时能带一个DirectX作品,那将有多强的竞争力,所以最重要的是现在就要行动,实践,实践,再实践。

你尽力了吗

2008-07-08 了无痕

发信人: cloudsky (小四), 信区: Security
标 题: 你尽力了吗
发信站: 武汉白云黄鹤站 (Mon Apr 17 19:52:54 2000), 站内信件

很多人问如何入门如何入门,我却不知道要问的是入什么门。很少把某些好文章耐心
从头看完,我这次就深有体会。比如袁哥的sniffer原理,一直以为自己对sniffer原
理很清楚的,所以也就不曾仔细看过袁哥的这篇。后来有天晚上和袁哥讨论,如何通
过端口读写直接获取mac地址,为什么antisniff可以获得真正的mac地址,而不受更
改mac地址技术的影响,如何在linux下获得真正的mac地址。我一直对linux下的端口
读写心存疑虑,总觉得在保护模式下的端口都做了内存映象等等。结果袁哥问了我一
句,你仔细看我写的文章没有,我楞,最近因为要印刷月刊,我整理以前的很多文档,

被迫认真过滤它们,才发现袁哥的文章让我又有新认识。再后来整理到tt的几篇缓冲
区溢出的,尤其是上面的关于Solaris可装载内核模块,那就更觉得惭愧了。以前说
书非借不能读,现在是文章留在硬盘上却不读。其实本版已经很多经典文章了,也推
荐了不少经典书籍了,有几个好好看过呢。W.Richard.Stevens的UNP我算是认真看过
加了不少旁注,APUE就没有那么认真了,而卷II的一半认真看过,写过读书笔记,卷
III就没有看一页。道格拉斯的卷I、卷III是认真看过几遍,卷II就只断续看过。而
很多技术文章,如果搞到手了就懒得再看,却不知道这浪费了多少资源,忽略了多少
资源。BBS是真正能学到东西的地方吗?rain说不是的,我说也不是的。不过这里能开
阔人的视野,能得到对大方向的指引,足够了。我一直都希望大家从这里学到的不是
技术本身,而是学习方法和一种不再狂热的淡然。很多技术,明天就会过时,如果你
掌握的是学习方法,那你还有下一个机会,如果你掌握的仅仅是这个技术本身,你就
没有机会了。其实我对系统安全是真不懂,因为我一直都喜欢看程序写程序却不喜欢
也没有能力攻击谁谁的主机/站点。我所能在这里做的是,为大家提供一个方向,一种
让你的狂热归于淡然的说教。如果你连<Windows NT设备驱动程序编写>、< win9x系统编
程>都没有看过,却要写个什么隐藏自己的木马,搞笑。如果你看都不看汇编语
言,偏要问exploit code的原理,那我无法回答也不想回答你。总有人责问,要讨个
说法纭纭,说什么提问却没有回答。不回答已经是正确的处理方式了,至少没有回你
一句,看书去,对不对,至少没有扰乱版面让你生闷气。Unix的man手册你要都看完了,

想不会Unix都不行了。微软的MSDN、Platform SDK DOC你要看完了,你想把Win编程想
象得稍微困难点都找不到理由。还是那句话,一个程序员做到W.Richard.Stevens那个
份上,做到逝世后还能叫全世界的顶级hacker们专门著文怀念,但生前却不曾著文攻
击,想想看,那是一种什么样的境界,那是一份什么样的淡然。我们可以大肆讨论技
术问题,可以就技术问题进行激烈的卓有成效的讨论,却无意进行基础知识、资源信
息的版面重复。我刚在前面贴了一堆isbase的文章,开头就是主页标识,却在后面立
刻问什么主页在哪里?前面刚刚讨论过如何修改mac地址,后面马上又来一个,前后
相差不过3篇文章。选择沉默已经是很多朋友忍耐力的优异表现了。
很多东西都是可以举一反三的。vertex的lids,被packetstorm天天追踪更新,你要是
看了THC的那三篇,觉得理解一个就理解了一堆,都是内核模块上的手脚。你不看你怎
么知道。我不想在这里陷入具体技术问题的讨论中去,你要是觉得该做点什么了,就
自己去看自己去找。没有什么人摆什么架子,也没有什么人生来就是干这个的。你自
己问自己,尽力了吗?

研发工程师之路

2008-07-08 了无痕

  恭喜,你选择开发工程师做为自已的职业
  悲哀,你选择开发工程师做为自已的职业

  本文所指的开发工程师,仅指程序开发人员和以数字电路开发为主的电子工程师。
  当你选择计算机或者电子、自控等专业进入大学时,你本来还是有机会从事其它行业的,可你毕业时执迷不悟,仍然选择了开发做为你的职业,真是自做孽不可活。不过,欢迎你和我一样加入这个被其它人认为是风光无限的“白领”吧。
  如果你不是特别的与人世隔绝,我想你一定看过金老先生的名著《笑傲江湖》吧,里面有一门十分奇特的武功叫做"辟邪剑法",你看这个小说第一次看到这种功夫的练法时,我想你当时一定笑歪了牙“呵呵,真好玩!”,可是现在我很痛心的告诉你:你选择的开发工作就是你人生路上的"辟邪剑法",而你现在已经练了,并且无法再回头。
  相对同时刚出校门同学从事其它行业而言优厚的薪水,以及不断学习更新的专业知识不仅仅让你感到生活的充实,更满足了你那不让外人知的虚荣心。在刚出校门的几年中,你经常回头看看被你落在后面的同学们,在内心怜悯他们的同时,你也会对自已天天加班的努力工作感到

心里平衡:“有付出才会有回报”这句话在那几年中你说的最多,不管是对自已的朋友们还是自已的爱人。第二句最常说的话是对公司的领导:“不行我就走人!”,实际上你也真的走过几回。对了,在这几年中,因为你的经济条件不错,你开始买房、开始谈恋爱、结婚、开始有了自已的小孩。有时候你会对自已说再过两年就去买车。当然其中可能有许多大件是需要分期付款的,但你对前途充满了信心,你确信认为这种日子会永远的持续下去,即使不是变得更好的话。
  日子总是在这种平淡中一天天的过去,就在那么不经意间,你突然发现自已已经快30岁了,或者已经30了,莫名的,你心里会漫延着一种说不清楚的不安情绪,你好像觉得前途并非像前几年那样变得越来越好,你也忽然发现你以前所瞧不起的同学里好像已经有不少开着车的了,也有几个人住着比你还大的房子,好像房款还是一次付清的,你突然明白你现在的生活比起你的同学来最多是中游偏上了。工作中最让你感到心里不舒服的是,你越来越不敢对你的领导说不了,即使比你来的晚的同事升职或提薪,你也只是在私下与朋友们一起喝酒时才敢发发牢骚,在头的面前你的声间越来越小、笑脸是越来越温柔。
  你终于开始迷茫“再过几年我会是在干什么呢?”,这句话常常出现在你的心里。
  计算机开发工作,是一种以年轻为资本的工作,说句通俗点的话是“吃青春饭的”,嗯,这句话好像在一种特别的行业也听到过。

其标志就是一:工作的时间性非常强,一个开发项目被定的时限通常是很紧张的,更有甚者,有些号称开发管理的书里面还非常卑鄙的号召将一个项目切成多个小片,每个小片都定一个叫“里程碑”的东东来严格跟踪开发进度,加班加点在其它行业是需要加班工资的,而在开发行业,加班工资好像还没见到几个公司发过,是啊,反正有时间限制着,你干不完我再找你算账.所以开发工作通常有着其它工作所没有的精神上的压力。

一旦一个人步入而立之年,因为家庭和孩子的负担,加上精力上面的衰退,加班工作时间变得越来越少,这点让很多老板们感到:这些人已经老了,不好用了。指示人事部门:“以后招开发人员限制在30岁以下!”,相对而言硬件开发会年龄方面限制会稍好一点点,但也是五十步笑百步。还有一个很重要的一点就是:计算机这个烂东东实在是进步的太快了,前两年买的顶级配置电脑,现在怎么看怎么像废品,这还是小事,更可气的是好像每天都需要学习新的知识,刚毕业时只会书本上的PASCAL,学会了用腐蚀的办法来做电路板,一上班就开始学习TURBOC和TANGER2.0,刚刚学会,还没来得及高兴,马上开始学Borland C++和Protel3.0,好不容易学会了,却发现需要学习VC和Protel98了。单片机也是啊:Z80的指令背的很熟,工作中没来得及用就要学8031,好好学吧,本来想着这辈子就吃它了,又发现又出来什么PIC、DSP、CPLD、FPGA、ARM等等….这还不包括中间要学一大堆74系列、4000系列、XX系列…IC卡居然里面还有CPU卡..如果学习的知识里每个字都能变成一分钱,我想所有的开发工程师都是腰缠万贯的富翁。
  一眼看去,这种日子好像见不到头,年轻时乐此不彼,但现在你一定对自已能坚持到什么时候感到怀疑了。我们都玩过像仙剑奇侠传这样的RPG游戏,刚开始时你只是一个一名不文的少年,随着你去打怪物、捡宝贝、学秘芨,最后终于有一天你会变成一个大英雄!那么你在实际生活中过得比那些小侠们还辛苦,为什么成不了一个生活中的大侠呢?呵呵,原因在这里:因为开发工作是邪门功夫,它虽然可以让你速成的变成小资,但它最大的特点是经验不积累!日新月异的知识更新,让你总是感到自已在退步,你就像在RPG中的主人公,开始时就给了你一把好剑和好盔甲,而且让你的级别很高,但让你的经验不累积,虽然刚开始打小怪物时你觉得自已很爽,但越到后来,你会发现你会死的很惨!比较一下你与其它非开发行业的同学你就可以知道了,例如和你学医的同学比起来。套用岳不群他老人家说华山剑宗和气宗的区别那段话:前十年你比你那些学医的同学收入和地位要好的多,但十年以后你和他基本上各方面都会持平,而二十年以后你的各方面远远不能与你学医的同学相提并论!嗯,你已经开始不笑辟邪剑法了吧。
  “敢问路在何方?路在脚下…”,不过猴兄和八戒兄这么认为是可以的,你呢?
总结了许多开发朋友在30岁以后的生活之路,让我们一起看看开发人员“路在何方?”那么开发人员在30岁以后都干些什么呢?
其路一:继续做你这个很有“前途”的职业吧!
  偶掰着脚指头仔细数了数,发现还真的有很多朋友在30岁以后还在从事开发工作,我这里说的从事,是指你还需要天天在电脑边上编程序和画电路板,与你手下是否有几个小兵无关,也与你是否头上顶着什么项目经理、主任工程师的帽子无关,只要你还需要亲自开发,你就属于这一类。其中有个年龄最大的朋友是63年的,从事医疗仪器的开发工作,35岁左右还在从事软硬件开发工作的仍有一大堆,分析这些仍然从事开发的朋友,基本上都有以下特点:
1 痴迷工作或者痴迷电脑,晚上八点到十二点的这段时间,基本上是在电脑桌或工作台前渡过的。
2 不喜欢与人交住,朋友很少,常联系的人不超过五个。
3 与朋友交往时谈工作多,但一般不主动谈钱。
4 体型偏胖或偏廋,不在正常区间。
5 无未来计划,对五年后自已生活怎么样、从事什么工作说不清楚。
6 俭省,从不乱花钱。
即使你是还不到30岁的开发人员,你也可以看看自己对以上几条是否符合,是否会在30岁后还从事开发职业,四条疑似,五条以上基本确诊你也是这类型的人。
  这些朋友们通常报着过一天是一天的态度生活,到了这个年龄,也不敢再轻易的换工作了,年轻时的锐气慢慢的也消退了。唯一不变的希望是有一天从天上掉下来一大堆钱把自己砸伤。说实在话因为他们的性格所限,基本上可以确定他们以后不可能在职场上获得更好的发展,当个小头头,带几个人开发已经是他们发展的顶点。至于以后的人生之路,不仅他们自己迷茫,可能上帝也正在头痛。
   不过像这类朋友,偶很奇怪的发现:他们的小孩都是儿子!不知是偶然还是有什么其它说法。
简单建议:要改变命运,先改变性格:坚持半年晚上不从事工作、游戏及电视,用此时间与人交往,你的人生会有改变。

其路二:转行从事技术支持、行政或生产等工作还有一些朋友,从事了几年的开发工作,因为自已并非特别的爱好,或者领导上面的强制工作安排,他们转到了技术支持、服务或行政等工作,至少当时从表面上看起来,他们的薪水较开发要少一些,但真正的统计这些人,发现他们之中有半数的人获得了更好的发展,升职为服务部经理或行政经理等职,最历害的一个朋友已升职为总经理助理,进入高层。
  这类朋友当时转行通常并非自已志愿,属被逼无奈或者其它原因,但显然,拥有专业知识技术的他们显然在非技术部门中鹤立鸡群,遇到什么事情他们均可从专业的角度提出建言,久而久之,他们获得更多的升职和加薪机会也就不足为奇。
  因为不从事开发,所以经验开始积累,这类的职业通常会给你一个很安定的感觉,你到30多岁后会发现这类职业反而比开发工作更容易获得新的工作机会。

  简单建议:你如果确定在开发部无法获得很好的发展机会,不妨转到其它几个部门试试,换个活法,钱少点就少点吧,机会多。
其路三:开发管理
  如果你现在已经是总工或开发部经理,或者你眼看就有机会被提升为这类职务,那么恭喜你,你走的是从“弼马温”到“斗战胜佛”这条金光大路,你不仅拥有很高的专业技能,而且很显然,你也有着很强的人际交往能力,你这类人根本不需要对未来有着任何的担心,你在即使一无所有的时候也很容易白手起家。
  你这种人算是练辟邪剑法练成了仙,嗯,我无话可说。
  你是不是这类人也很容易区别,就像围棋二十岁不称国手终身无望一样,你应该在工作三、四年以后,也就是说二十七岁左右就会发现自已工作中指手划脚的时间比亲自开发的时间要多了,而且大多数这类人在这个年龄手下应该有“兵”了,相反的,如果你快30岁了还天天埋头于电脑前编程序和画板子,或者30多岁了你还没升到部门经理(虽然你总是觉得自已很有希望),基本上可以确定你不是这类人。好了,如果你确定你是这类人,那么你唯一的想法就是尽快爬上中层和高层,因为有时候人生偶然性太大,不占住坑的萝卜很有可能被人拔出来!

  简单建议:天天去你的老板家里面拖地和擦桌子!

其路四:出国或考研
  有两个搞开发后出国的朋友,其中一个甚至打工打到了一个小公司总工的位置,数据库和软件方面水平巨牛,但仍感觉心里不踏实,于是将自己工作多年的钱忍痛掏出来,出国费加上机票大概将自已辛苦所攒的银子花完,然后又借了一些钱,在02年身上揣着一万美元跑去了加拿大,在加拿大不停的重复找工作,换工作,然后再找工作的循环,找的工作基本上与计算机无关,不过工资总是在1500加元左右,呵呵,折成人民币与他在国内打工拿的基本上差不多,不过租个地下室就花了300加元,然后吃吃喝喝,再买个电脑上上网这类的,基本每月平均还要倒贴一点。前段时间给我的邮件里说,现在身上花的差不多只有5、6000美元了,准备开个小公司,看看能不能往国内倒腾点东东,做最后一搏。另外一个朋友去澳州,时间稍早一些,先是大概摘了一年多的葡萄,后来总算找了个技术工作,每天的工作是画机械图纸,收入还算不错

将近3000澳元,买了个旧车,也算是过上了资本主义生活。不过前年回来一趟,唯一的感叹就是:在国外拿2000美元的生活,绝对不如在国内拿5000人民币的生活舒服。
  也有两个考研的朋友,不过其中一个严格的说不是做开发的出身,偏重于市场方面的工作性质,不过我的朋友里面考研的不多,只好凑两个人说说,一个考研后在北京找了个工作,每个月5、6000元钱,但还是做开发,生活仍然与没考研之前没有任何的改变,前途仍然没见到什么大亮的光,还是搞不清楚以后再干些什么,标准的过一天算一天了。另外一个考研后在大学里面找了个工作,工资虽然比他原来打工少了不少,但毕竟终身有靠,稳定了下来,也算修成了正果,这位哥们心情一放松下来,也开始有时间琢磨着业余时间自已做点什么,好像现在慢慢的也开始有了点眉目。
  简单建议:这两条路,对开发人员来说都不算是很好,出国十年前是好事,现在难说,考研能成功转行的概率恐怕也不是很大,多半仍然去搞开发,只不过研究生可以多干几年罢了。

其路五:转行到市场
  绞尽脑汁的想想,我所知道的人之中只有两个开发人员去了市场,这两个人都不能说是朋友,认识而已。他们都是主动要求去了市场,结果是这两个人均在市场都是干到一年左右,然后都自已开公司了。呵呵,很奇怪,极高的转行成功率!不过仔细想想,我对这两个人的思路佩服的五体投地。能下决心仍掉每月5、6000元的开发职位,从事一个自已并不熟悉的岗位,每月拿个2000多元+提成,但提成那是说不清楚的事情,这个决定,只能让人感觉到他们对自已前途清晰的把握和老谋深算的心机。而且他们不去服务不去生产,挖空心思说服领导去市场(市场部门与开发部门通常是一个公司的核心部门,进入其实并不容易),可以说是有着长远的考虑的。有技术了,再与客户交成朋友,马上就会产生很大的机遇应该是正常的事情。
  有实力,有心机,也有着很强的决心力,这种人恐怕早在大学毕业时或更早的时候就已经决定了自已的人生之路,他们的每一步路在若干年前早就计划周全,现在看起来:学会技术->进入市场->寻找商机->开公司,一条多么清楚的人生之路。但就像我们上小学中学时,所有人都知道上大学是我们最清楚的人生路一样,最后只有少数人才能真正达到目标(当然,现在扩招的历害是另外一回事,我是说我们那个时候,也就是:“很久很久以前,当我像你那么大的时候”)。

  简单建议:你若是这类人,我的建议是:…嗯?….那个你.你,你别走啊,我还有个事想请你赞助一下啊…..

其路六:开公司自已干

  呵呵,看到这一条,发现你的眼睛已经圆了,你肯定千百次的想过这个事情吧,咳咳,其实我从事开发的时候也是天天梦想着这种事情。总想着过两年找个机会就自已干,这个梦想一年又一年的折磨着你也给着你希望。看看吧,开发后来开公司的还真的不少,里面有成功的也有很多失败的,通常开公司都是几个人合伙开始的,有做技术的,有做市场的,几个人一拍即合、狼狈为奸,共同策划了这一个大活动。一般说来能让这几个人下决心走出这一步,产品肯定是先进的,甚至是国内独一无二的,市场也是很大的,负责市场的那个哥们通常会拍着胸保证可以卖出去,并悄悄地告诉你他在某主管领导是他小舅子的同学的二叔,肯定没问题。于是你们几个人找地点、注册执照、买了几个破桌子,再攒了两台电脑,每个人又凑了几万银子,公司开张了!
  产品很快出来了,市场的哥们也不负重望,有几个客户表示要试用了,一切看起来都是如此的正常,“…….你坐在老板桌前,不停的有人来汇报工作或者找你签字…人进人出中…你又想起公司再穷也不能只有一把椅子的故事…..”你在梦中笑出声来。
    是如此的顺利,你们很快就有单子了,很快的单子让你们凑的那点钱不够了,你们很高兴的每个人又增加了投入,拿出钱时你眼泪汪汪的数着钱说:“这就是我那生蛋的母鸡啊”。你们的产品确实不错,市场也经营的很好,客户慢慢的多了起来,单子来的时候一笔接着一笔,你每天都处于兴奋之中,唯一美中不足的是好像客户回款总是会拖一些日子,不过客户给你保证说:过几天,过几天就付给你们,因为回款总是在计划外,所以你们为了资金的流畅运行又凑了一些钱,这个时候你有一些心事了,因为你的存款折上面的数字已经快趋向于零了。“没事,过两个月等回款了一切都OK了,谁干事业不吃点苦呢?”你这么安慰着自已又投入到工作中去,资金总是在回款和生产经营费用之间走着一个窄窄的小木桥,你的账上总是没有太多的钱,扩大了的公司规模和许多意外情况,使你又一次、二次、三次的与合作者们再次投入了自已的资金,当然,后来的钱你可能已经是借的了…..
  终于有一天,你的会计再一次告诉你,老板啊,账上又没现金了,吃过多次苦头的你终于下决心开始重视资金的运行了,你裁掉了一些不必要的人手,减少了开发的投入,要求市场人员签单的时候必须予付XX%的款,回扣也必须等收过款后再付,同时也开始对产品的生产成本开始进行控制。
  时间一天一天的过去,因为竟争对手的产品也对你的产品进行了仿造,你的产品慢慢变得不再先进,市场人员开始埋怨公司的合同资金方面规定太严格,不好签单,生产成本的下降通常也导至产品毛病的增多,客户也开始埋怨你的服务人员不能及时进行服务。
  终于有一天,你重新走进了人才交流中心,以前你是来招人的,现在你拿着自已的简历开始寻找一个工作
……
    公司的成功与否,与产品有关,与市场有关,但更重要的是与资金有关,产品与市场都可以通过资金来弥补,而却没有任何东西可以代替

资金,凡是倒下的公司,99%与资金链的断裂有关。在你决定要开公司以前,先估计一下你公司支持一年所需要的资金数额,包括人工费,生产,场地,广告宣传、市场费用、甚至电、水费等等等等,把你所想到的一切加在一起,得出的值就是..慢..如果你没有实际的开过公司的经验,你需要将此数字乘3,然后就是你开公司一年最少需要的费用,呵呵,公司的实际运营所需要的钱是你想像的3倍以上,你要是不信我也没办法。

    简单建议:开公司前最重要的是先确立你后续的资金来源!也就是说钱不够了怎么办?---因为你投入的钱肯定会不够的。

其路七:第二职业
    这类的朋友有不少,他们没有脱离开发工作,但是在业余时间又不停的接项目或者在卖产品,在单位里面他们显得并不出众,比起其它人来说他们属于最不愿意加班的一类.为此他们白天通常工作很勤奋.这类人也许不一定可以挣很多钱,但平均下来他们一年之中通常都可以比同事们多挣个几万元.有时候比上班拿得还多.但令人疑惑的是,这类人在生活中更加注重稳定,基本上没见到他们跳过蹧,即使私下里面已经开了个小公司,他们通常也不会辞职.
    你的旁边有没有这类人呢?分辨他们很容易:
–电话很多,而且更愿意来电话时离开办公室找个没人的旮旯通话.神秘兮兮给人一种"这家伙是不是有二奶啊?"的感觉的人,通常是这类人。这类人是女性最佳的选择对象:很顾家,不象那些富人容易花心,而比起一般人来说,他们收入相对要高得多。但总结了一下几位这类的开发朋友:也得出了一个令人沮丧的结论:这种人通常个子不高,体形类似桶状…..

   简单建议:这好像是开发人员最佳的出路了,但比较丰厚的收入通常让这类人不愿意去冒风险….到现在为止我所认识的这类人还没有一个真正算是成功的。
   好了,虽然偶的经历远远说不上丰富,也没有什么成功之处可以自满的,但或许因为比其它朋友痴长了几岁,见过的人可能会稍多一些,所

以斗胆写出了以上的一些文字,让您掉牙了。   下面是偶走过开发这条路上总结出来的一点心得,你可以不看,但看了就千万别把嘴咧的太大:   一、不管是给别人打工还是自已干,都要全心全意的工作,因为你所做的任何一点工作都会让自已的人生多一点筹码,这一点最最重要!这样的例子我至少可以举出两起,优秀的开发人员被其它新公司挖走,并给一定的股份,成为新公司的股东的例子。当时与这样的开发人员一个部门同时工作或更早工作的有许多人,他们平时经常偷点懒,能少干点工作就少干点,有时候还笑话那个平时努力工作的人傻,几年过去了,究竟谁比谁傻?   二、多与市场人员交朋友,你接触他们时可能总会觉得他们知识比你少,甚至素质比你低,可能比你还有点黄。但实际上他们比你更懂这个社会!参加到他们这个圈子中去,和他们一起赌赌钱、一起聊聊天、一起洗洗桑拿、一起.....你会通过他们接触到另外一个世界。   三、机会远比钱重要,挣不挣钱在年轻时并不是特别重要!不论是在实际生活中还是在网上或其它地方,如果有机会参与到除本职工作外的一些项目或产品的开发中(包括你的朋友拉你去做点小生意之类的非开发性质的工作),那怕是帮忙的性质,也要积极介入,至少你会交到很多的朋友,这样你的人生会多出很多的机会。

Winsock Programmer’s FAQ 中文翻译 Section 3.4 如何将数据包使用流协议传送

2008-07-08 了无痕

翻译:keo321
关键字:分包,流,TCP,长度包头
说明:转载请注明出处。

有什么合适的方法可以将一个包结构通过类似TCP的流协议投递?
原文地址:http://tangentsoft.net/wskfaq/intermediate.html#packetscheme

    两个最常见的方法是包分隔以及为包添加长度头。

    一个包分隔的例子就是为包数据添加一个插入符号(^), 一般来说,你使用的分隔符号不能出现在正常数据块中,否则你就需要更换分隔字符。

    另一个关于长度前缀头的例子是,为每一个包添加2个字节整形的包长度前缀。关于这个问题,你可以查看 FAQ中的关于发送整形数的章节(How to Use TCP Effectively),或者看(How to Packetize a TCP Stream)的例子。
   
    另外也有混合的方案。以Http协议为例,用CRLF(一种分隔符)来分离数据包头的各行,但当HTTP回应应中包含了二进制数据,服务器会在发送数据之前添加Content-length头。

    我更偏好于使用长度前缀,因为一旦你读取到数据长度的前缀,你就知道多少数据会收到。相比较而言,使用分隔符的方式的话,你就必须盲目的读取数据,直到找到包的结尾。

H264 编码器集合

2008-05-28 了无痕

最近开始着手研究H.264,而为了快速的替换现有系统,说实话,没有办法去研究技术细节。但也着实收录了一些资源。在下面与大家分享。
————————————–

LIST of MPEG-4 AVC/H.264 VIDEO CODECS
———————————————————-
SOFTWARE CODECS:
———————

  1. Ateme H.264/MPEG-4 AVC Codec (Ateme)
    No download on original site:
    http://www.ateme.com/products/h264.php
    See 30 day trial of Nero Digital (with Nero Recode) available from:
    http://www.nerodigital.com/eng/index.html

  2. VSS H.264 Video Codec (Vanguard Software Solutions, Inc.)
    Trial available, VfW.
    http://www.vsofts.com/h264/codecs.html
  3. Elecard OneClick Compressor & Elecard AVC/H.264 Decoder Package (Elecard)
    21-day free trial. Have H.264 SDK
    http://www.elecard.com/products/oneclick.shtml
  4. Mainconcept H.264 (MainConcept AG)
    Trial available on download page
    http://www.mainconcept.com/h264_encoder.shtml
    Use Elecard Encoder H.264 from March 2005.
  5. Moonlight H.264 Video Codec (Moonlight Cordless LTD.)
    21-day evaluation, DirectX filter.
    http://www.moonlight.co.il/products/…r/oneclickavc/
    This codec was developed with Elecard team.
  6. SONY Video Editor Vegas 6c with AVC support (Sony Corp.) NEW!!!
    30-days evaluation.
    http://www.sonymediasoftware.com/pro…ct.asp?PID=965
  7. QuickTime 7 H.264 (Apple Computer, Inc.)
    Integrated. Who test it? Any remarks welcome!
    http://www.apple.com/quicktime/technologies/h264/
  8. FastVDO H.264 (FastVDO LLC)
    Demo has decode time limit of 5 min.
    http://www.fastvdo.com/H.264.html
  9. LEAD H.264 Video codec (LEAD Technologies)
    Only demo, but you can buy codec online (100$). Who test it?
    http://www.leadcodecs.com/Codecs/LEAD-H264.htm
  10. Compression Master 3 (Popwire/Teleca AB)
    H264 encoder is all a part of Popwire’s Compression Master. Demo soft available (encoding is limited to 20 seconds).
    http://www.popwire.com/product_info….&products_id=2
  11. SVM H.264 Decoder Kit & MKi DVD Converter (Pegasus Information Technology Inc.)
    H.264 encoder and decoder with non standart format.
    http://www.h-264.com/downloads.htm
  12. AVC Alliance free demo player (AVC Alliance, written by Philips Electronics)
    Poor but free.
    http://www.avc-alliance.nl/main/downloads.htm
  13. Intel IPP H.264 codec (Intel Corporation)
    Intel IPP Library containe now H.264 encoder and decoder. Higher quality codecs are promised in 5.0 version (released now)
    http://www.intel.com/cd/software/pro…/ipp/index.htm
  14. PowerEncoder MPEG-4 AVC (CyberLink Corp.) NEW!!!
    Available in online shop.
    http://www.cyberlink.com/multi/produ…in_43_ENU.html
  15. ATI H.264 (ATI Technologies Inc.)
    No download. Software only and +HW support. Very fast codec by our tests.
    http://www.ati.com/technology/h264.html
  16. Mpegable AVC Codec (dicas digital image coding GmbH)
    No download, VfW
    http://www.mpegable.com/show/mpegableavc.html
    Old version from free-codecs:
    http://www.codec-download.com/module…=getit&lid=436

  17. Expert H.264 (PixelTools Corporation)
    Download on request
    http://www.pixeltools.com/experth264.html
  18. Softstream H.264/MPEG-4 (Media Excel)
    Audio & Video encoders ane decoders. Evaluation copy on request
    http://www.mediaexcel.com/products.htm
  19. MPEG-2/HDV/H.264 software (KDDI R&D Labs. Inc.)
    No download. MPEG related products also with H.264 support
    http://avs.kddilabs.jp/mpeg/indexe.html
  20. Fraunhofer IIS H.264 Codec (Fraunhofer IIS)
    No download.
    http://www.iis.fraunhofer.de/amm/download/mpeg4/
  21. UBLive-264-C64 (UB Video Incorporated)
    Demo available on request.
    http://www.ubvideo.com/mainmenu.html
  22. Sorenson Squeeze 4 Compression Suite (Sorenson)
    No download. Converter.
    http://www.sorensonmedia.com/solutio…d/mpg4_win.php
  23. Sonic’s HD-Series AVC encoder (Sonic Solutions)
    No download. Only press release now.
    http://www.sonic.com/about/press/new…/hdseries.aspx
  24. Enchansed sklmp4 (Pascal Massimino)
    No download. Announce of 264 development.
    http://skal.planet-d.net/coding/mpeg4codec.html
  25. NEX VISION H.264 (NEX VISION)
    No download.
    http://www.nexvision.fr/
  26. Hughes Network Systems H.264 (Hughes Network Systems, LLC)
    No download. Own Win&Linux codec for internal usage
    http://www.hns.com/HNS/Doc/0/MGD6UC9…3-04_IPoS.html
  27. Imagicity H.264/AVC codec (Imagicity, UK) NEW!!!
    No download. Speed optimization claimed.
    http://www.imagicity.com/products/products.htm

    ———————————————————-
    OPEN SOURCE:
    ———————

  28. x264 (free, supported by VideoLAN)
    OPEN SOURCE. Good publically available high profile encoder. Developers declare "early development stage", but encode results are one of the best.
    http://www.videolan.org/x264.html
    http://x264.nl/
  29. JM 9.6 reference H.264 encodec (free, supported by Joint Video Team ISO+ITU-T)
    OPEN SOURCE. Can be used only for stream testing.
    http://bs.hhi.de/~suehring/tml/
  30. libavcodec H.264 Decoder (Project FFMPEG)
    OPEN SOURCE. Permanently updated decoder.
    http://ffmpeg.sourceforge.net/index.php
  31. Hdot264 Pre-Alpha (Project Hdot264)
    OPEN SOURCE.
    http://sourceforge.net/projects/hdot264/
  32. t264 (Project t264)
    OPEN SOURCE.
    http://sourceforge.net/projects/t264