有一周多没有更新博客了,这段时间项目验收结尾,冲刺的时间比较多。还记得Fusion Chart的Demo吗,我们一起分析了 Fusion Chart Free,但功能更强大的当然是商业版。现在正在整理其Demo,项目结束与大家分享,敬请期待啊。请您先看张截图吧。
对于这张图如果用过FC的人,应该很熟悉的吧。对了,您猜对了,就是它。因为公司要用到RDLC报表,回头打算把RDLC的使用也复习下吧。
好了,项目快要结束了,做一下简单的技术沉淀,(当然正规的也要做的)。下面我们一起看一些基本的MFC的知识(学习MFC一定要有基础的)。
一、_T()函数
_T("")是一个宏,他的作用是让你的程序支持Unicode编码
因为Windows使用两种字符集ANSI和UNICODE,
前者就是通常使用的单字节方式,
但这种方式处理象中文这样的双字节字符不方便,
容易出现半个汉字的情况。
而后者是双字节方式,方便处理双字节字符。
Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows 9x只支持ANSI方式。
如果你编译一个程序为ANSI方式,
_T实际不起任何作用。
而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。
LPSTR:32bit指针指向一个字符串,每个字符占1字节
LPCSTR:32-bit指针指向一个常字符串,每个字符占1字节
LPCTSTR:32-bit指针指向一个常字符串,每字符可能占1字节或2字节,取决于Unicode是否定义
LPTSTR:32-bit指针每字符可能占1字节或2字节,取决于Unicode是否定义
L是表示字符串资源为Unicode的。
比如
wchar_t Str[] = L"Hello World!";
这个就是双子节存储字符了。
_T是一个适配的宏~
当
#ifdef _UNICODE的时候
_T就是L
没有#ifdef _UNICODE的时候
_T就是ANSI的。
比如
LPTSTR lpStr = new TCHAR[32];
TCHAR* szBuf = _T("Hello");
以上两句使得无论是在UNICODE编译条件下都是正确编译的。
而且MS推荐你使用相匹配的字符串函数。
比如处理LPTSTR或者LPCTSTR 的时候,不要用strlen ,而是要用_tcslen
否则在UNICODE的编译条件下,strlen不能处理 wchar_t*的字符串。
T是非常有意思的一个符号(TCHAR、LPCTSTR、LPTSTR、_T()、_TEXT()...),它表示使用一种中间类型,既不明确表示使用 MBCS,也不明确表示使用 UNICODE。那到底使用哪种字符集?编译的时候才决定
将char字符串转换成Unicode字符串。
T是个宏,不是函数
在需要双字节的函数,或COM里需要双字节的串.
为了国际兼容。其实很简单。
Visual C++里边定义字符串的时候,用_T来保证兼容性,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。
如果将来你不打算升级到unicode,那么也不需要_T,
_t("hello world")
在ansi的环境下,它是ansi的,如果在unicode下,那么它将自动解释为双字节字符串,既unicode编码。
这样做的好处,不管是ansi环境,还是unicode环境,都适用。
2\请问在vc++中的字符串_T("ABC")和一个普通的字符串“ABC”有什么区别。
_T("ABC")
表示如果定义了unicode
它表示 L"ABC",每个字符为16位,宽字符字符串
---------------------------------------------------------
if not UNICODE
它就是ascii的"ABC",每个字符为8位
"ABC"就是指ascii字符串"ABC"
----------------------------------------------------------
相当于
#ifdef _UNICODE
#define _T("ABC") L"ABC"
#else
#define _T("ABC") "ABC"
#endif
----------------------------------------------------------
_T("ABC")中的一个字符和汉字一样,占两个字节,而在"ABC"中,英文字符占一个字节,汉字占两个字节
二、堆和栈
1、“堆”和“栈”在C++中主要是指存放数据或者说是变量、对象的在内存中的区域,如同现实中 美国和中国的区别,表面上是在内存中的位置不同,但是分配内存的方式却大不相同,如同美国和中国虽然表面上都是国家,但是社会制度、各种福利 各种机构都不同,一句话就是内存中的不同区域。
2、c++中“堆”:在一个程序中 堆是一片内存,不是有堆内存之说,一般都是程序员手动分配,在C++中则是一般用new操作符(如果不使用C的malloc系列,好像只能用new)分配的内存,同样也只能程序员手动释放,不然会有内存泄露。当然了给什么分配内存,那只能给变量、类对象分配,所以存放的也是类对象和变量。
c++中“栈”:是程序自动分配的内存,比如调用某个函数,传递参数时(值传递),那么这个参数的值是在“栈”内存上分配的,当这个函数退出后 占用的“栈”内存也就自己释放了。
三、Windows Socket
s Socket的实现方法:
Socket是连接应用程序与网络驱动程序的桥梁。它在应用程序中创建,通过绑定操作与驱动程序建立关系。此后,应用程序送给Socket数据,由Socket交给驱动程序,驱动程序再把数据向网络上发送出去。计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。网络应用程序就是这样运用Socket进行数据的发送与接收的。
ISO/OSI七层参考模型(ISO:国际标准化组织 OSI:Open System Interconnection):
物理层:提供二进制传输,确定在通信信道上如何传输比特流。
数据链路层:提供介质访问,加强物理层的传输功能,建立一条无差错的传输线路。
网络层:提供IP寻址和路由。因为在网络上数据可以经由多条线路到达目的地,网络层负责找出最佳的传输路线。
传输层:为源端主机到目的端主机提供可靠的数据传输服务,隔离网络的上下层协议,使得网络应用与下层协议无关。
会话层:在两个相互通信的应用进程之间建立、组织和协调其相互之间的通信。
表示层:处理被传送数据的表示问题,即信息的语法和语义。
对等层通信的实质:
对等层实体之间虚拟通信。
下层向上层提供服务,实际通信在最底层完成。
各层所使用的协议:
应用层:远程登录协议Telnet、文件传输协议FTP、超文本传输协议HTTP、域名服务DNS、简单邮件传输协议SMTP、邮局协议POP3。
传输层:传输控制协议TCP、用户数据报协议UDP。
网络层:网际协议IP、Internet互联网控制报文协议ICMP、Internet组管理协议IGMP。
TCP/IP模型:应用层、传输层、网络层、网络接口层。
TCP/IP模型与OSI模型对照如下
应用层:应用层、表示层、会话层。 传输层:传输层。 网络层:网络层。 网络接口层:数据链路层、物理层。
端口:一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。
套接字的类型:
(1)流式套接字(SOCK_STREAM),基于TCP协议实现。
(2)数据报套接字(SOCK_DGRAM),UDP协议实现。
(3)原始套接字(SOCK_RAW)
Windows Socket “TCP”网络编程实例
一些开发步骤:
“TCP”服务器端
1、加载套接字库。
2、创建套接字。
3、绑定地址信息。
4、绑定套接字。
5、监听套接字。
6、“Accept”等待用户请求。
7、“send”发送数据。
8、"recv"接收数据。
9、关闭“使用中的套接字”,继续循环等待。
“TCP”客户端
1、加载套接字库。
2、创建套接字。
3、绑定地址信息。
4、绑定套接字。
5、发出请求。
6、接收数据。
7、发送数据。
8、关闭套接字。
9、“WSACleanup”终止“套接字库”的使用。(服务器端一直循环运行,所有没有)。
对于UDP通信,不需要建立连接,直接进行收/发就可以了。
四、多线程
1、程序和进程
程序是计算机指令的集合,它以文件的形式存储在磁盘上。而进程是正在运行的程序的实例。比如,我们编译生成的“exe”文件是一个可执行程序,存储在磁盘上就是程序。点击运行后,就启动了该程序的一个实例,我们称之为进程。一个程序可以有多个进程,也就是一个程序可以产生多个实例。
2、进程和线程
进程从来不执行任何东西,它是线程的容器,真正完成代码执行的是线程。单个进程可能包含若干个线程,但至少包含一个主线程。
3、进程的地址空间
系统赋予每个进程独立的虚拟地址空间。对于32位操作系统,运行32位的进程,这个地址空间是4G。因为对于32位指针来说,它的寻址的范围是2的32次方,即4G。这就是为什么32位操作系统,内存条一般不超过4G的原因。
4、虚拟内存。
在磁盘上有一个“pagefile.sys”文件,它是页文件,页文件透明的为应用程序增加了内存,这一部分就是虚拟内存。
5、线程。
线程的内核对象:操作系统用来存放线程统计信息的小型的数据结构。
线程栈:它用于维护线程在执行代码是所需要的所有函数参数和局部变量。
同一个进程的不同线程运行在同一个进程环境下,它们共享资源,所以可以非常容易的实现相互之间的通信。
线程运行在操作系统为其分配的CPU时间片上,对于单核CPU,就要多个线程来回切换。多核CPU就可以实现多个线程的并发执行。
采用多线程而不是多进程,是因为线程只有一个内核对象和一个栈,占用内存少。而对于进程每一个都要分配4GB的虚拟地址空间,占用资源多。而且进程切换需要交换整个地址空间。线程之间的切换只是执行环境的改变。
这些都是些基本的知识,希望您也能复习下。