




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Win32应用程序编程接口(API)。1.3windows版本Windows Server 2003 定位于企业和服务器应用。1.7准备win64Win32和Win64的本质差异是指针变量的大小(win64是64位)以及虚拟地址空间的大小。2.1 windows文件系统Windows支持4种文件系统。1.NT文件系统(NTFS)。2.文件分配表(FAT&FAT32)。3.CD-ROM文件系统(CDFS)。4.通用磁盘格式(UDF)。只有NTFS支持安全性。2.2文件名目录和文件名不能包含任何ASCII字符在1-31之间的字符或者以下字符:*?”“ /目录和文件名称不区分大小写,但可以保留大小写。2.4.2main函数C的main函数及其参数列表(argv),应该被宏tmain所代替。2.11.2目录管理创建或者删除目录涉及到一对简单函数:BOOL CreateDirectory(LPCTSTR lpPathName,LPSECURITY_ATTRIBUTES lpSecurityAttributes)BOOL RemoveDirectory(LPCTSTR lpPathName)3.5文件属性和目录处理有可能在目录中查找满足指定命名方式的文件和目录,同时获取文件属性。查找操作需要函数FindFirstFile获取的查找句柄,使用FindNextFile来获取指定的文件,以及使用FileClose终止查找。3.5.2获取文件和目录属性的其他方式FindFirstFile和FindNextFile函数可以获取一下文件属性信息:属性标记、三个时间戳和文件大小。3.5.3临时文件名该名称可用于任何指定的目录,而且必须是唯一的。3.9文件处理策略C库提供了一些不同的优点,包括如下:1)代码可以移植到非windows平台。2)便捷的面向行和字符的函数,而windows中没有相对应的函数来化简字符串处理。3)C库函数通常比windows函数更易于使用。4)面向行和流字符的函数易于改变以进行普通调用,尽管失去了可移植性特定。5)C库可以在多线程环境下运行。C库也有一些限制。如下:1)C库不能管理或遍历目录,也不能获取或设置大多数文件属性。2)C库在fseek函数中使用32位的文件位置,所以在顺序读取巨大文件的同时,却不能根据需要定位巨大文件的任何地方。3)C库中没有高级特性,比如文件安全性、内存映射文件、文件锁、异步I/O和进程间通信。3.10文件锁定文件锁可以是只读(共享)或读写(专有)。最重要的是锁属于进程。最普遍的函数是LockFileEx,其次是LockFile。在使用文件锁是应考虑以下因素:1)解锁应该同前面锁定使用完全相同的范围。2)锁不能跟文件现有的锁有重叠,否则会产生冲突。3)锁可以超出文件的长度范围,该方法在进程或线程扩展文件时有用。4)锁不能被新建的进程继承。3.11注册表注册表是关于程序和系统配置信息的集中的分层的数据库。对注册表的访问是通过注册关键字来实现的,他跟文件系统目录相似,关键字可以包含其他关键字或名称/值对,他跟文件名称和内容是类似的。注册表名称/值对包含如下信息:1)操作系统版本号、编译号和注册用户。2)每个正确安装程序的相似信息。3)计算机处理器类型、处理器数量、系统内存等等信息。4)用户特定信息,比如主目录和程序选项。5)安全信息,比如用户账号。6)从文件扩展名刀可执行程序的映射。这些映射在用户点击文件名图标时通过用户界面shell使用。例如.doc扩展名映射到微软的word程序。7)映射网络地址到主机名。4.3错误和异常*错误可以被当做一个可知位置偶然发生的事件,例如系统调用错误应该能被代码段中的逻辑立即检测和汇报。这样,程序一般包含明确的测试逻辑以判断文件读取操作是否有误,第二章采用ReportError函数来诊断并响应错误。另一方面,异常可能会在任何地方发生,而要对异常进行测试是不可能或不现实的。例如除以零和内存访问违规就是实际例子。虽然如此,但是两者的区别有时是模糊的。Windows可以在内存分配过程中使用HeapAlloc函数产生异常,二档内存不足时使用HeapCreat函数。程序可以通过使用RaiseException函数的程序员定义的异常代码来引起异常。异常处理器提供了不使用goto或longjmp移交控制权,从而程序控制下的内部程序块或函数中推出的一个便利机制。当程序块访问资源,比如打开文件,内存或同步对像时,这种能力尤其重要,因为处理器可以释放他们,也有可能在异常处理器之后继续程序执行而不是终止程序,另外,当程序块中断退出时,程序可以恢复系统状态,比如浮点掩码。用户定义异常:RaiseException函数:VIOD RaiseException(DWORD dwExceptionCode,DWORD dwExceptionFlags,DWORD cArguments,CONST DWORD *lpArguments)4.5终止处理器终止处理器跟异常处理器的作用是相同的,但是程序当线程由于正常程序流程程序块离开以及异常发生时,他才会执行。另一方面,终止处理器不能诊断异常。在try-finally语句使用_finally关键字来构建中止处理器。4.8控制台控制处理器异常处理器可以对不同的事件做出响应,但是它们不能探测到诸如用户注销或者从键盘上输入Ctrl-c以停止程序等之类的情形。控制台控制处理器可用于探测此类事件。4.10矢量异常处理矢量异常处理(VEH)管理跟控制台控制处理器管理是相似的,尽管细节有所不同。可以使用AddVectoredExceptionHandler来增加或注册一个处理器。PVOID AddVectoredExceptionHandler(ULONG FirstHandler,PVECTORED_EXCEPTION_HANDLER VectoredHandler)5.2堆Windows以堆得方式来维护内存池。一个进程可以包含多个堆,可以从浙西堆中分配内存。对于不同的数据结构,使用不同堆来分配有时是很方便的,不同堆的有点包括:1)公平。没有哪个线程可以获得比分配给其堆得内存还要多的内存,特别是由于程序忘记释放不在需要的数据单元而引起的内存泄漏缺点,只影响进程中的某个进程。2)多线程性能。每个线程具有自己的堆,线程之间的抢夺会减少,这充分提高了性能。3)分配效率。在小堆内分配固定大小的数据单元比在巨大的堆内分配许多不同大小单元的效率更高。分段也减少了。而且,每个线程具有唯一的堆简化了同步,所以产生了更高的效率。4)解除分配效率。整个堆及其包含的所有数据结构可以用单个函数调用来释放。该调用同时也释放堆中任何泄漏的内存分配。5)引用局部化的效率。在一个小堆维护数据结构确保单元限制在相对少量的页面中,这无形中减少了数据结构单元处理时的页面错误。注意:堆没有安全属性,因为他在进程之外是不可以访问的。要销毁整个堆,使用HeapDestroy。这是CloseHandle函数移除不需要的句柄的规则例外。BOOL CloseHandle(HANDLE hHeap)5.3管理堆内存通过指定堆句柄、块大小和几个标记来从堆中获得内存块的函数:LPVOID HeapAlloc(HANDEL hHeap,DWORD dwFlags,SIZE_T dwBytes)返回值:正常时返回已分配内存块的指针,失败时返回NULL(除非预先指定异常处理方式)。解除堆内存分配的函数: BOOL HeapFree(HANDLE hHeap,DWORD dwFlags,LPVOID lpMen)内存块可以重新分配以改变其大小 函数如下:LPVOID HeapReAlloc(HANDLE hHeap,DWORD dwFlags,LPVOID lpMen,SIZE_T dwBytes)返回值:正常时返回重新分配内存块的指针,失败时返回NULL,或产生异常。通过堆句柄和块指针来调用HeapSize以决定分配块的大小。DWORD HeapSize(HANDLE hHeap,DWORD dwFlags,LPVOID lpMen)返回值:正常时返回分配内存块的大小,失败时返回零。5.3.4小结:堆管理使用堆得通常过程如下1)使用CreateHeap或者GetProcesSEHap来获取一个堆句柄。2)使用HeapAlloc在堆内分配块。3)可选的,使用HeapFree释放一些或所有的单个块。4)使用HeapDestroy删除堆并关闭句柄。5.5内存映射文件Windows内存映射文件功能也可以将虚拟内存空间直接映射到普通文件。这有几个优点:1)没有必要执行直接的文件I/O(读写)。2)在内存中创建的数据结构将会保存在文件中,以便以后被相同的或不同的程序使用。3)方便而有用的内存算法(排序、查找树、字符串处理等等)可以处理文件数据,即使该文件可能比可用的物理内存要大得多。如果文件比较大,那么性能挥手道页面调度行为的影响。4)文件处理性能在同样情况细也能充分提升。5)没有必要管理缓存及其所含文件数据。操作系统能有效而可靠的完成这一艰巨任务。6)多个进程可以共享内存,通过映射虚拟地址空间到相同的文件或到页面调度文件中(进程间内存共享是映射到页面调度文件的主要原因)。7)没有必要消耗页面调度空间。5.9.1静态和动态库DLL是文件映射最明显和重要的应用。创建进程常用函数,比如ReportError,可以放入一个库中以简化创建进程。这种单映像模式简单,但又几个缺点1)可执行映像可能很大,在运行时消耗硬盘空间和物理内存,并需要过多的精力来管理机交付给用户。2)每次程序更新需要编译整个程序,即使改变很小或局部的。3)系统中使用该函数的每个程序在其可执行映像中都具有该函数的一个副本,可能包含不同版本,这种安排增加了磁盘空间,或许更重要的是,当几个这样的程序同时运行时会增加物理内存的使用频率。4)使用不同技术的不同程序版本则要求在不同的环境下获取最佳性能。DLL(优点)巧妙大的解决了这些及其他问题1)库函数在创建程序时没有连接。相反,他们在程序装载时(隐式连接)或者运行时(显式链接)链接。结果,程序映像可以小很多,因为他不包含函数库。2)DLL可用于创建共享库。多个程序以DLL德形式共享单个库,而只有一个副本装载到内存中,所有程序映射到他们进程的地址空间到DLL代码中,尽管每个线程在堆栈中具有自己不共享的存储副本。3)新版本或替代实现可以通过提供一个新版DLL来实现,而所有使用该库函数的程序无需修改就可以使用该新版本。4)有了显式链接,程序也可以在运行时决定应该使用哪个版本的库。不同的库可能是同一函数的代替实现,也可能执行完全不同的任务,就像不同程序一样。同用程序一样,哭在同一进程和线程中运行。多个进程可以共享DLL代码,而且可以使用调用线程的堆栈。所以DLL具备线程安全性。5.11DLL入口点串口化是必须的,因为DllMain必须在没有中断的情况下执行完初始化。5.12DLL版本管理DLL的一个主要优点是多个程序可以共享单个实现。然而该能力导致了兼容复杂性,正如下所述:1)新函数会增加,是的隐式连接程序在链接.LIB文件时所假定的偏移量无效。而显式链接则避免了这个问题。2)新版本会改变行为,引发现有未更新的程序问题。3)依赖新DLL函数的程序有时链接着较老的DLL版本。DLL兼容性问题解决方案:1)使用DLL版本号作为.DLL和.LIB文件名的一个组成部分,通常是作为后缀。例如Utility_3_0.DLL和Utility_3_0.LIB就用于本书web站点和所有跟本书版号相关的项目范例。通过使用隐式或显式链接,程序可以确定版本需求并使用不同的名称来访问文件。改方案常用于UNIX程序。2)微软引入了并行DLL或者汇编和组件概念。该解决方案需要在程序中增加一个用XML编写的声明以定义DLL需求。3).NET架构提供了并行执行的附加支持。6.1windows进程和线程每个进程包含一个或多个线程,而windows线程是最基本的可执行单元。进程的每个线程共享代码、全局变量、环境字符串和资源。每个线程都独立进行调度,并包含如下要素:1)为过程调用、中断、异常处理器和自动存储建立的堆栈。2)线程本地存储(TLS)指针数组,让线程可以分配存储以创建自己特有的数据环境。3)堆栈参数,在创建线程时所产生的,对每个线程来说通常是唯一的。6.2进程创建Windows进程管理的基本函数是CreateProcess,该函数不会返回HANDLE。BOOL CreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpsaProcess, LPSECURITY_ATTRIBUTES lpsaThread,BOOL bInheritHandles,DWORD dwCreationFlags,LPCTSTR lpEnvironment,LPCTSTR lpCurDir,LPSTARTUPINFO lpStartupInfo,LPPROCESS_INFORMATION lpProcInfo)返回值:只有当进程和线程都成功创建是才返回TRUE。6.2.1指定可执行的映像和命令行lpApplicationName或lpCommandLine制定了可执行映像名,规则如下:1)lpApplicationName,如不是NULL,就是可执行映像名称。如果映像名称包括空壳,可以使用引号。2)否则,可执行映像将是lpCommandLine的首个后记。通常当lpApplicationName为NULL时,只指定lpCommandLine。尽管如此,lpApplicationName仍有许多详细规则:1)如果lpApplicationNamebushi NULL,它指定可执行模块。指定完整路径和文件名或使用部分名称和当前驱动器和路径,无需进一步查找。名称中包含文件扩展名如.EXE或.BAT。2)如果lpApplicationName字符串是NULL,lpCommandLine中第一个空格定界符的标记值是程序名。如果名称中没有完整的目录路径,查找顺序如下:1.当前进程映像的目录。2当前目录。3.windows系统目录,可以通过GetSystemDirectory来获取。4. windows目录,可以通过GetSystemDirectory来获取。5.在环境变量PATH中指定的目录。新进程可以通过常用的argv机制获取命令行,或用GetCommandLine以单个字符串形式来获取命令行。注意命令行不是一个常数字符串。这跟主程序的argv参数不是常量是一致的。程序可以修改参数,尽管建议在参数字符串副本中进行修改。新进程不必使用跟父进程同样的UNICODE定义。各种组合都是可能的。7.1线程概览线程是进程中独立的执行单元。多线程编程需要组织和协调线程执行,以简化程序并利用主机内在的并行处理能力。7.3线程管理线程就像其他windows对象一样具有句柄,而且有一个系统调用CreateThread可以在调用进程地址空间中创建一个可执行线程。就像进程一样,有时会说”父”和”子”线程,尽管操作系统并不如此加以区分,CreateThread具有几个独特的要求。1)指定线程在进程代码中的开始地址。2)指定堆栈大小,堆栈空间是从进程虚拟地址空间中分配的。缺省堆栈大小是父线程的虚拟内存堆栈大小(通常是1MB)。初始化有一个页面提交给堆栈。新的页面根据需要可以提交到堆栈达到最大化而且不能再增加了。3)指定线程参数指针。该参数几乎可以是任何值并被线程自身解释。4) CreateThread返回一个线程ID值及其句柄,一个NULL的句柄值表示一个失败。HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddr,LPVOID lpThreadParm, DWORD dwCreationFlags,LPDWORD lpThreadId)7.10进程和线程优先级和调度线程获取跟其进程优先级相关的优先级。通过CreateProcess可以初始设置的进程优先级有四类,而每类具有基本优先级。IDLE_PRIORITY_CLASS,基本优先级4。NORMAL_ PRIORITY_CLASS,基本优先级9或者7。HIGH_ PRIORITY_CLASS,基本优先级13。REALTIME_PRIORITY_CLASS,基本优先级24。线程优先级设置成跟进程基本优先级相关,而在线程创建时优先级被设成进程优先级。线程优先级在进程基本优先级的2范围内。所产生的五个线程优先级的符号名称如下:THREAD_ PRIORITY_LOWEST THREAD_ PRIORITY_BELOW_NORMALTHREAD_ PRIORITY_NORMAL THREAD_ PRIORITY_ ABOVE_NORMALTHREAD_ PRIORITY_HIGHEST这些值来设置或者读取线程的相关优先级。注意使用带符号的整数而不是DWORD。7.13计时等待最后的韩式Sleep允许线程放弃处理器,并从运行状态转为在指定时间段(单位为毫秒)处于等待状态。7.14纤程纤程是线程中可以被程序而不是被内核调度的执行单元。一个线程可以创建多个纤程,而纤程自身决定了下一个需要执行的线程纤程。纤程具有独立的堆栈,但是完全在线程的环境中运行,而且,纤程管理完全发生在内核玩的用户空间,纤程可以被当做一个轻量级的线程,尽管有许多差别。使用纤程的主要目的有:1)最重要的是,许多程序,尤其是为UNIX编写的程序使用了专有的线程实现,现在通常过时了,他们被编写成调度自身的线程。纤程使其可以更加容易移植到windows平台上。2)线程不必阻值对文件锁、互斥、命名管道输入或者其他资源的等待。而纤程却可以轮询资源,如果资源不可用,就切换到另一个特定的纤程。3)纤程在线程中运作,访问线程和进程资源。不像线程,纤程不是抢占调度的。Windows的执行程序实际上不知道纤程,纤程是完全在用户空间内的纤程DLL中管理的。4)纤程允许实现写作例程,这样程序可以再互相关联的任务间切换。线程不能允许这点。程序员不能直接控制下一个要执行的线程是哪个。5)主要的软件厂商使用纤程并宣扬其性能优点。由6个函数组成了纤程API,他们按下列顺序使用:线程首先必须通过调用CreateThreadToFiber来启动纤程操作。线程包含一个独立的纤程,该纤程被称作主纤程。该调用给纤程数提供了一个指针,他可以像线程参数被用来创建线程的独特数据一样的使用。1)主纤程或者其他纤程使用CreateFiber来创建另外的纤程。每个纤程有一个开始地址、一个堆栈大小和参数。每个新纤程是通过地址而不是句柄来标识的。2)一个单独的纤程可以通过调用GetFiberDatal来获取数据,正如CreateFiber中所获取的一样。3)同理,一个纤程可以通过GetCurrentFiber来获取标识。4)一个运行的纤程通过调用SwitchToFiber把控制权交给另一个纤程,指出另一纤程的地址。纤程必须明确指出线程内下一个要运行的纤程。5)DeleteFiber函数删除现有的纤程以及相关数据。纤程相互调度的两种方式:主辅调度。端到端调度。8.2线程同步对象这两种机制用于进程和线程相互同步。1)进程中线程可以用ExitProcess等待其他进程终止,使用WaiForSingleObject或者WaitForMultipleObject等待进程句柄。纤程可以用同样的方式等待其他线程终止(ExitThread或者return)。2)文件锁是专门针对同步文件访问的。8.3 CRITICAL_SECTION对象前面所述的关键代码就是同时只能有一个纤程可以执行的代码段。多线程并发执行关键代码段可以导致不可预测的错误结果。CRITICAL_SECTION(CS)对象可被初始化和删除,但是没有句柄且不能被其它进程共享。CRITICAL_SECTION具有非内核对象的优点,在用户空间中维护。这通可以提供性能提升,但并非是种如此。一旦引入内核同步对象将会讨论性能优点。8.4保护变量的CRITICAL_SECTION使用CRITICAL_SECTION是简单的,其常见用法是允许线程访问全局共享变量。8.6.2互斥、CRITICAL_SECTION与死锁避免死锁的一个方法是“尝试和后退”战略,借此线程调用WaiForSingleObject时存在有限的超时值,当检测到被拥有互斥时,通过让出处理器或者做短时间的休眠来“后退”以等待再次尝试。8.9回顾:互斥与CRITICAL_SECTION区别如下:1)互斥在被终止线程抛弃后悔获得信号,这样其他线程就不会永远受阻。2)互斥等待可以超时,然而只能探测CS。3)互斥可以命名并可被不同进程中的线程共享。4)可以把WaiForSingleObject用于互斥,这既是一个编程便利,同时如果使用得当也是避免死锁的方法。5)创建互斥的线程可以立即指定所有权。在CS中,几个线程可以抢占CS。6)CS通常弹不总是比互斥快很多。8.8事件事件使用5个函数:CreateEvent,OpenEvent,SetEvent,ResetEvent,PauleEvent.事件可以分为手动重置和自动重置,这一属性是通过CreateEvent调用来实现的。可用OpenEvent来打开一个可能来自于其他进程的命名事件。线程可以使用SetEvent向事件发送信号。PauleEvent释放所有当前等待手动重置事件的线程,但是随后事件就自动重置。在自动重置事件的情况下,PauleEvent释放单个等待线程。注意ResetEvent仅在手动重置事件被SetEvent设置成获得信号时才是有用的。10.1.1同时使用时间和互斥1)互斥和事件都是与消息块或者其他数据接口相关的。2)互斥定义了访问数据结构对象的关键代码段。3)事件用来通知有了新的消息。4)归纳的得出,互斥确保对象的不变性(或者安全属性),而事件则告知对象的状态发生改变(比如消息被添加或者从消息缓存中删除),也可能编程一种已知的状态(比如在消息缓存中至少有一个信息)。5)一个线程锁定数据结构,并通过创建新的消息改变对象状态,并设置或发送(pulse)与该新消息相关的事件。6)至少有一个其他线程等待对象到达所需状态的事件,等待必须发生在关键代码段之外,这样生产者线程就可以访问对象了。7)消费者线程也可以锁定互斥,测试对象状态,并且在对象已经处于所需状态的情况下避免事件等待。10.1.2条件变量模型现在这一切合并到单个代码段中就产生了所谓的条件变量模型(CV模型),他有两类,分别是信号和广播CV模型。11.3命名管道命名管道包含如下特征:1) 命名管道是面向消息的,所以读取的进程可以读取由写进程发送的不同长度的信息。2) 命名管道是双向的,所以两个进程可以通过同一个管道交互信息。3) 多个独立的管道实例使用一个名称来命名。4) 管道名称可由网络上的系统来访问。无论两个处理器是在同一个机器还是不同机器上,命名管道通信都是一样的。5) 几个简便的连接函数化简了命名管道请求/响应交互和客户端服务器连接。11.3.2创建命名管道HANDLE CreateNamePipe(LPCTSTR lpName, DWORD dwOpenMode,DWORD dwPipeMode, DWORDnMaxInsrances,DWORD nOutBufferSize, DWORD nInBufferSize,DWORD nDefaultTimeOut,LPSECURITY_ATTRIBUTES lpSecurityAttributes)11.7邮槽Windows邮槽就像命名管道一样具有一个名称,他可以使不相关的进程进行通信。邮槽具有一种基于数据报的广播机制,但是行为上不同于命名管道,这使得他们在一些重要但有限的情况下非常有用。下面是他的重要特征:1)邮槽是单向的。2)邮槽可以有多个写入和读取程序,但是它通常是哟中1-n的形式。3)一个写入程序(客户端)不能确认所有读取程序(服务器)实际已接收到消息。4)邮槽可以在网络域中。5)消息长度是有限的。使用邮槽需要以下操作1)每个服务器使用CreateMailslot创建一个邮槽句柄。2)服务器然后使用ReadFile调用等待接受邮槽信息。3)只写客户端应该使用CreateFile打开邮槽,并用WriteFile写入信息,如果没有等待的读取者,打开操作会失败(名称找不到)。12.1windows套接字WinsockAPI是Berkeley套接字API对windows环境的扩展,而Winsock可以由所有的windows系统所支持,winsock的优点如下:1)移植用Berkeley套接字编写代码非常简单。2)windows系统容易整合到TCP/IP网络中,无论是IPv4还是新出现的IPv6,IPv6允许更长的IP地址,这克服了IPv4的4字节地址限制。3)套接字可以和windows重叠I/O一起使用,当有大量激活客户端时它允许服务器扩展。4)套接字可以作为文件HANDLE和ReadFile、WriteFile一起使用,虽然有些限制,但是其他windows函数就像UNIX一样允许套接字用作文件描述符。该特性在需要使用异步I/O和I/O完成端口时非常方便。5)扩展的非可移植性扩充也可以。12.1.1Winsock初始化WinsockAPI由DLL(WS_32.DLL)支持,程序可以通过链接WS_32.LIB来访问它。WSAStartup和WSACleanup总会需要,也许是你所使用的唯一非标准函数。int WSAStartup(WORD wVersionRequired,LPWSADATA lpWSAData);12.1.2创建套接字一旦Winsock DLL完成初始化,就可以使用标准函数来创建套接字,并连接客户端/服务器或者端到端的通信。调用socket函数创建佳一个SOCKETSOCKET socket(int af, int type, int protocol)12.2.1绑定套接字int bind(SOCKET s, const struct sockaddr *saddr, int namelen)12.2.2将绑定套接字放入监听状态int listen (SOCKET s ,int nQueueSize);12.2.3接收客户端连接SOCKET accept(SOCKET s, LPSOCKADDR lpAddr, LPINT lpAddrLen);12.4对比命名管道和套接字两者是非常相似的,但区别如下:1) 命名管道可以使面向消息的,这可以简化程序设计。2) 命名管道使用ReadFile和WriteFile,而套接字也可以使用send和recv。3) 套接字不像命名管道那样灵活,所以用户可以选择和套接字一起使用协议,比如TCP或者UDP。用户也可以根据服务质量和其他因素来选择协议。4) 套接字是基于业界标准的,允许和非windows系统进行互操作。12.4.1对比命名管道和套接字服务器当使用套接字时,重复调用accept以连接多个客户端。每次调用反悔不同的连接套接字。注意以下和命名管道相关的区别1) 命名管道需要使用CreateNamedPipe来创建每个命名管道实例和HANDLE,而套接字实例是通过accept来创建。2) 套接字客户端数量没有上限(listen只限制了排队客户端的数量),但是命名管道实例数量却没有限制,由对CreateNamedPipe的第一次调用决定。3) 没有跟TransactNamedPipe相对应的套接字便捷函数。4) 命名管道没有明确的端口号,而是通过名称来区别的。命名管道服务器需要两个函数(CreateNamedPipe和ConnectNamedPipe)来获取可用的HANDLE,而套接字服务器需要四个函数调用(socket,bind,listen,accept)。12.12数据报数据报同邮槽相似,并用于相似的环境中。在发
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论