Windows socket之Select模型开发

合集下载

网络程序设计-05-IO模型-Select模型-课件v1.0.0演示教学

网络程序设计-05-IO模型-Select模型-课件v1.0.0演示教学

fd_set *writefds, //指向一个套接字集合,用来检查其可写性
fd_set *exceptfds,//指向一个套接字集合,用来检查错误
const struct timeval *timeout //指定此函数等待的最长时间,如果为NULL则为无限大
)
返回值:①调用成功,返回发生网络事件的所有套接字数量的总和;
11
WinSock I/O模型-Select模型 1. 传统编程模式分析 2. 阻塞问题的解决方法 3. WinSock I/O模型 4. Select模型 5. 动手实践
12
4.Select模型 4.1 概述 Select模型主要使用select()函数来管理I/O, 故名“Select模型”。 这个模型的设计源于Unix系统,目的是避免 套接字阻塞,使程序有能力管理多个套接字。
16
4.Select模型
4.4 网络事件
Select模型确定套接字状态的过程如下:
套接字集合 readfds
select函数等待...
有事件发生
有未决的连接请求 数据可读 连接关闭/重启/中断
writefds
连接成功(调用connect) 数据可写
exceptfds
连接失败(调用connect) OOB数据可读
以执行读写操作。
15
4.Select模型
4.4 网络事件 套接字上有新连接请求、数据读/写、连接成功/中
断等都是网络事件。网络编程其实就是发现网络事件,并 处理网络事件的过程。
如果想检测某套接字上有否网络事件,需要将它添 加到相应的集合中,并调用select函数来确定。
调用select函数完成后,如果该套接字仍在相应的 集合中,则说明该套接字上有网络事件发生。

ch3 Winsock套接字IO模型(1)

ch3 Winsock套接字IO模型(1)

用于WSAAsyncSelect函数的网络事件类型
用法举例
要接收读写通知:
#define WM_SOCKET WM_USER + 101 int nResult = WSAAsyncSelect(s,hWnd,WM_SOCKET,FD_READ|FD_ WRITE); if(nResult==SOCKET_ERROR) { //错误处理 }
此函数用于检测一个或多个套接字的状态。套接 字的状态包括可读、可写、出错。 需要检测状态的套接字集合由一个fd_set结构指 示,分别为readfds,writefds,exceptfds(不能同 时为NULL)。 参数timeout指向timeval结构,用于指定select等 待I/O操作完成的时间。如timeout是一个空指针, I/O timeout select调用会无限期地,直到至少有一个套接字 满足条件。
readfds集合包括满足下述任何一个条件的套接字: 有数据可以读入。 连接已经关闭、重设或中止。 假如已调用了listen,而且一个连接正在建立,那么 accept函数调用会成功。 writefds集合包括满足下述任何一个条件的套接字: 有数据可以发出。 如果已完成了对一个非阻塞连接调用的处理,连接就 会成功。 exceptfds集合包括满足下述任何一个条件套接字: 假如已完成了对一个非阻塞连接调用的处理,连接尝 试就会失败。 有带外(Out-of-band,OOB)数据可供读取。
ioctlsocket( int ioctlsocket( SOCKET s, long cmd, u_long FAR *argp ); 用于设置和获取与套接字相关的操作参数。 参数 s:套接字描述符。 cmd:对套接字s的操作命令。 argp:指向cmd命令所带参数的指针。 成功返回0,否则,返回SOCKET_ERROR。

网络编程WSAasynselect模型(2)

网络编程WSAasynselect模型(2)

2.UDP程序2的源代码
//编程环境:VC 6.0 //程序说明:基于用户数据报协议UDP的程序实例程 序功能:在窗口里点击鼠标左键,则发送信息到 端口为8000的远程机上,并可以从端口为8000的 远程机接收数据
#include "stdafx.h" #include <Winsock.h> // 说明全局量 HINSTANCE hInst; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ////////////////////////////// int APIENTRY WinMain(HINSTANCE hI,HINSTANCE hP,LPSTR lp,int nC) { MSG msg; HWND hWnd; hInst = hI; //实例句柄存入全局量hInst WNDCLASS wc; memset(&wc,0,sizeof(WNDCLASS)); wc.lpfnWndProc= (WNDPROC)WndProc; wc.hInstance = hI;
wc.hIcon=LoadIcon(NULL, IDI_APPLICATION); wc.hbrBackground= (HBRUSH)COLOR_WINDOW; wc.lpszClassName= "W1"; RegisterClass(&wc); hWnd=CreateWindowEx(WS_EX_PALETTEWINDOW,"W1"," UDP程序2[端口:6000]", WS_OVERLAPPEDWINDOW, 400,200,200,100,NULL, NULL, hI, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nC); // 主消息循环 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }//end 函数WinMain

Winsock网络编程笔记:select()函数详解,select例子实现非阻塞TCPServer

Winsock网络编程笔记:select()函数详解,select例子实现非阻塞TCPServer

Winsock⽹络编程笔记:select()函数详解,select例⼦实现⾮阻塞TCPServerSelect I/O模型优缺点优点:能从单个线程的多个套接字上进⾏多重连接,避免多线程的资源消耗。

缺点:fd_set结构中的最⼤套接字数量通常为64。

套接字集合:fd_set(defined in winsock2.h)fd_set结构可以把多个套接字集合在⼀起,形成⼀个套接字集合。

select函数可以测试这个集合中哪些套接字有事件发⽣。

typedef struct fd_set{u_int fd_count; // how many are SETSOCKET fd_array[FD_SETSIZE]; // an array of SOCKETs} fd_set;该结构内置函数:nfd_count() //Numbers of sockets in the set.nfd_array[i] //Array of sockets that are in the set.Winsock定义的4个操作fd_set套接字集合的宏:FD_ZERO(*set) ----初始化set为空集合。

FD_CLR (s, *set) ----从set移除套接字s。

FD_ISSET (s, *set) ----检查s是否是set的成员,返回值是ture或false。

FD_SET (s, *set) ----添加套接字s到集合set。

select函数:1. ⽤途在编程的过程中,经常会遇到许多阻塞的函数,好像read和⽹络编程时使⽤的recv, recvfrom函数都是阻塞的函数,当函数不能成功执⾏的时候,程序就会⼀直阻塞在这⾥,⽆法执⾏下⾯的代码。

这时就需要⽤到⾮阻塞的编程⽅式,使⽤select函数就可以实现⾮阻塞编程。

select函数是⼀个轮循函数,循环询问⽂件节点,可设置超时时间,超时时间到了就跳过代码继续往下执⾏。

socket通信中select函数的使用和解释

socket通信中select函数的使用和解释

socket通信中select函数的使⽤和解释select函数的作⽤:select()在SOCKET编程中还是⽐较重要的,可是对于初学SOCKET的⼈来说都不太爱⽤select()写程序,他们只是习惯写诸如conncet()、accept()、recv()或recvfrom这样的阻塞程序(所谓阻塞⽅式block,顾名思义,就是进程或是线程执⾏到这些函数时必须等待某个事件发⽣,如果事件没有发⽣,进程或线程就被阻塞,函数不能⽴即返回)。

可是使⽤select()就可以完成⾮阻塞(所谓⾮阻塞⽅式non-block,就是进程或线程执⾏此函数时不必⾮要等待事件的发⽣,⼀旦执⾏肯定返回,以返回值的不同来反映函数的执⾏情况。

如果事件发⽣则与阻塞⽅式相同,若事件没有发⽣则返回⼀个代码来告知事件未发⽣,⽽进程或线程继续执⾏,所以效率⾼)⽅式⼯作的程序,它能够监视我们需要监视的⽂件描述符的变化情况——读写或是异常。

select函数格式:select()函数的格式(所说的是Unix系统下的Berkeley Socket编程,和Windows下的有区别,⼀会⼉说明):Unix系统下解释:int select(int maxfdp, fd_set* readfds, fd_set* writefds, fd_set* errorfds, struct timeval* timeout);先说明两个结构体:第⼀:struct fd_set可以理解为⼀个集合,这个集合中存放的是⽂件描述符(file descriptor),即⽂件句柄,这可以是我们所说的普通意义的⽂件,当然Unix下任何设备、管道、FIFO等都是⽂件形式,全部包括在内,所以,毫⽆疑问,⼀个socket就是⼀个⽂件,socket句柄就是⼀个⽂件描述符。

fd_set集合可以通过⼀些宏由⼈为来操作,⽐如清空集合:FD_ZERO(fd_set*),将⼀个给定的⽂件描述符加⼊集合之中FD_SET(int, fd_set*),将⼀个给定的⽂件描述符从集合中删除FD_CLR(int, fd_set*),检查集合中指定的⽂件描述符是否可以读写FD_ISSET(int, fd_set*)。

试验3SELECTIO模型服务端的程序实现

试验3SELECTIO模型服务端的程序实现

试验3 SELECT I / O模型服务端的程序实现通过这次试验,要掌握Winsock提供了两种套接字模式:锁定和非锁定,一个应用程序如何通过它们管理I / O,Winsock提供了一些I / O模型,s e l e c t模型有助于应用程序通过一种“异步”方式,一次对一个或多个套接字上进行的通信加以管理,防止应用程序在套接字处于锁定模式中时,在一次I / O绑定调用(如s e n d或r e c v)过程中,被迫进入“锁定”状态;同时防止在套接字处于非锁定模式中时,产生W S A E W O U L D B L O C K错误。

相关内容说明select模型s e l e c t(选择)模型是Wi n s o c k中最常见的I / O模型。

之所以称其为“ s e l e c t模型”,是由于它的“中心思想”便是利用s e l e c t函数,实现对I / O的管理!最初设计该模型时,主要面向的是某些使用U n i x操作系统的计算机,它们采用的是B e r k e l e y套接字方案。

s e l e c t模型已集成到Winsock 1.1中,它使那些想避免在套接字调用过程中被无辜“锁定”的应用程序,采取一种有序的方式,同时进行对多个套接字的管理。

由于Winsock 1.1向后兼容于B e r k e l e y套接字实施方案,所以假如有一个B e r k e l e y套接字应用使用了s e l e c t函数,毋需对其进行任何修改,便可正常运行。

利用s e l e c t函数,我们判断套接字上是否存在数据,或者能否向一个套接字写入数据。

之所以要设计这个函数,唯一的目的便是防止应用程序在套接字处于锁定模式中时,在一次I / O绑定调用(如s e n d或r e c v)过程中,被迫进入“锁定”状态;同时防止在套接字处于非锁定模式中时,产生W S A E W O U L D B L O C K错误。

socket select用法和粘包处理

一、介绍1. 什么是socket select2. 为什么需要使用socket select3. socket select的作用二、socket select的基本用法1. 创建socket2. 使用select函数进行多路复用3. 使用FD_ISSET宏进行套接字状态检测4. 使用FD_SET宏进行套接字状态设置5. 使用FD_CLR宏进行套接字状态清除6. 使用FD_ZERO宏进行套接字集合清空三、socket select的粘包处理1. 什么是粘包2. 如何使用socket select进行粘包处理3. 代码示例四、总结1. socket select的优点2. socket select的局限性3. 对于粘包问题的处理建议---一、介绍1. 什么是socket selectsocket select是一种用于I/O多路复用的机制,它可以同时监视多个socket,当某个或某些socket发生变化时,可以触发相应的操作。

2. 为什么需要使用socket select在网络编程中,往往需要同时处理多个客户端的请求,如果使用传统的阻塞式I/O,需要为每个客户端创建一个线程来处理其请求,这样会导致系统资源的浪费。

而socket select可以通过单线程监听多个socket,极大地提升了服务器的处理效率。

3. socket select的作用socket select主要用于I/O多路复用,它可以监视多个socket的状态,并在其中任何一个socket发生变化时通知用户程序,从而实现高效的并发网络编程。

二、socket select的基本用法1. 创建socket在使用socket select之前,首先需要创建一个socket,并进行绑定、监听等操作,以便服务器可以接受客户端的连接请求。

2. 使用select函数进行多路复用在程序中使用select函数时,需要将所有需要监听的socket添加到一个文件描述符集合中,通过调用select函数来监视这些socket的状态变化。

8.1 select 模型[共2页]

2108.1 select模型如前所述,在非阻塞模式下,WinSock函数无论如何都会立即返回,所以必须采取适当的步骤,让非阻塞套接字能够满足应用的要求。

select(选择)模型是WinSock中最常见的I/O模型。

Berkeley套接字方案已经设计了该模型,后来又集成到了WinSock1.1中。

它的中心思想是利用select函数,实现对多个套接字I/O的管理。

利用select函数,可以判断套接字上是否存在数据,或者能否向一个套接字写入数据。

只有在条件满足时,才对套接字进行I/O操作,从而避免无功而返的I/O函数调用,避免频繁产生WSAEWOULDBLOCK错误,使I/O变得有序。

1.select的函数select的函数原型如下,其中的fd_set数据类型,代表着一系列特定套接字的集合。

int select(int nfds,fd_set FAR * readfds,fd_set FAR * writefds,fd_set FAR * exceptfds,const struct timeval FAR * timeout);其中,参数nfds:是为了保持与早期的Berkeley套接字应用程序的兼容,一般忽略它。

参数readfds:用于检查可读性。

readfds集合包括想要检查是否符合下述任何一个条件的套接字。

◇有数据到达,可以读入。

◇连接已经关闭、重设或中止。

◇假如已调用了listen,而且一个连接正在建立,那么accept函数调用会成功。

参数writefds:用于检查可写性。

writefds集合包括想要检查是否符合下述任何一个条件的套接字。

◇发送缓冲区已空,可以发送数据。

◇如果已完成了对一个非锁定连接调用的处理,连接就会成功。

参数exceptfds:用于检查带外数据。

exceptfds集合包括想要检查是否符合下述任何一个条件的套接字。

◇假如已完成了对一个非锁定连接调用的处理,连接尝试就会失败。

WindowsSocket学习笔记

Windows Socket学习笔记Socket(套接字)◆先看定义:typedef unsigned int u_int;typedef u_int SOCKET;◆Socket相当于进行网络通信两端的插座,只要对方的Socket和自己的Socket有通信联接,双方就可以发送和接收数据了。

其定义类似于文件句柄的定义。

◆Socket有五种不同的类型:1、流式套接字(stream socket)定义:#define SOCK_STREAM 1流式套接字提供了双向、有序的、无重复的以及无记录边界的数据流服务,适合处理大量数据。

它是面向联结的,必须建立数据传输链路,同时还必须对传输的数据进行验证,确保数据的准确性。

因此,系统开销较大。

2、数据报套接字(datagram socket)定义:#define SOCK_DGRAM 2数据报套接字也支持双向的数据流,但不保证传输数据的准确性,但保留了记录边界。

由于数据报套接字是无联接的,例如广播时的联接,所以并不保证接收端是否正在侦听。

数据报套接字传输效率比较高。

3、原始套接字(raw-protocol interface)定义:#define SOCK_RAW 3原始套接字保存了数据包中的完整IP头,前面两种套接字只能收到用户数据。

因此可以通过原始套接字对数据进行分析。

其它两种套接字不常用,这里就不介绍了。

◆Socket开发所必须需要的文件(以WinSock V2.0为例):头文件:Winsock2.h库文件:WS2_32.LIB动态库:W32_32.DLL一些重要的定义1、数据类型的基本定义:这个大家一看就懂。

typedef unsigned char u_char;typedef unsigned short u_short;typedef unsigned int u_int;typedef unsigned long u_long;2、网络地址的数据结构,有一个老的和一个新的的,请大家留意,如果想知道为什么,请发邮件给Bill Gate。

Socket模型c++版本详解

Socket模型详解[转]Winsock 的I/O操作:1、两种I/O模式阻塞模式:执行I/O操作完成前会一直进行等待,不会将控制权交给程序。

套接字默认为阻塞模式。

可以通过多线程技术进行处理。

非阻塞模式:执行I/O操作时,Winsock函数会返回并交出控制权。

这种模式使用起来比较复杂,因为函数在没有运行完成就进行返回,会不断地返回 WSAEWOULDBLOCK错误。

但功能强大。

为了解决这个问题,提出了进行I/O操作的一些I/O模型,下面介绍最常见的三种:Windows Socket五种I/O模型——代码全攻略如果你想在Windows平台上构建服务器应用,那么I/O模型是你必须考虑的。

Windows操作系统提供了选择(Select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped I/O)和完成端口(Completion Port)共五种I/O模型。

每一种模型均适用于一种特定的应用场景。

程序员应该对自己的应用需求非常明确,而且综合考虑到程序的扩展性和可移植性等因素,作出自己的选择。

我会以一个回应反射式服务器(与《Windows网络编程》第八章一样)来介绍这五种I/O模型。

我们假设客户端的代码如下(为代码直观,省去所有错误检查,以下同):#include <WINSOCK2.H>#include <stdio.h>#define SERVER_ADDRESS "137.117.2.148"#define PORT 5150#define MSGSIZE 1024#pragma comment(lib, "ws2_32.lib")int main(){WSADATA wsaData;SOCKET sClient;SOCKADDR_IN server;char szMessage[MSGSIZE];int ret;// Initialize Windows socket libraryWSAStartup(0x0202, &wsaData);// Create client socketsClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// Connect to servermemset(&server, 0, sizeof(SOCKADDR_IN));server.sin_family = AF_INET;server.sin_addr.S_un.S_addr = inet_addr(SERVER_ADDRESS);server.sin_port = htons(PORT);connect(sClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));while (TRUE){printf("Send:");gets(szMessage);// Send messagesend(sClient, szMessage, strlen(szMessage), 0);// Receive messageret = recv(sClient, szMessage, MSGSIZE, 0);szMessage[ret] = '\0';printf("Received [%d bytes]: '%s'\n", ret, szMessage);}// Clean upclosesocket(sClient);WSACleanup();return 0;}客户端所做的事情相当简单,创建套接字,连接服务器,然后不停的发送和接收数据。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

套接字select模型是一种比较常用的IO模型。利用该模型可以使Windows socket应用程
序可以同时管理多个套接字。

使用select模型,可以使当执行操作的套接字满足可读可写条件时,给应用程序发送
通知。收到这个通知后,应用程序再去调用相应的Windows socket API去执行函数调用。

Select模型的核心是select函数。调用select函数检查当前各个套接字的状态。根
据函数的返回值判断套接字的可读可写性。然后调用相应的Windows Sockets API完成数据
的发送、接收等。

阻塞模式和非阻塞模式的优点和不足:

阻塞模式套接字执行IO操作时,如果执行操作的条件未满足,线程就会阻塞在调用的
函数上。程序不得不处于等待状态,但是由于并不知道客户请求何时到来,因此函数在何时
返回不得而知。

非阻塞模式套接字执行IO操作时,在任何时候函数都会立即返回。但程序员必须为此
编写更多的代码。这增加了开发Windows socket应用程序的难度。另外由于不断的循环调
用导致程序效率很低。

Select模型是Windows sockets中最常见的IO模型。它利用select函数实现IO 管
理。通过对select函数的调用,应用程序可以判断套接字是否存在数据、能否向该套接字
写入数据。

如:在调用recv函数之前,先调用select函数,如果系统没有可读数据那么select
函数就会阻塞在这里。当系统存在可读或可写数据时,select函数返回,就可以调用recv
函数接收数据了。

可以看出使用select模型,需要两次调用函数。第一次调用select函数第二次socket
API。使用该模式的好处是:可以等待多个套接字。

select函数

[cpp]
int select (
Int nfds,//被忽略。传入0即可。
fd_set *readfds,//可读套接字集合。
fd_set *writefds,//可写套接字集合。
fd_set *exceptfds,//错误套接字集合。
const struct timeval*timeout);www.lunwen360.net//select函数等待时间。

该函数返回处于就绪态并且已经被包含在fd_set结构中的套接字总数。如果超时则返
回0。

第一个参数nfds被忽略。

第二个参数readfds,可读性套接字集合指针。

第三个参数writefds,可写性套接字集合指针。

第四个参数exceptfds,检查错误套接字集合指针。

第五个参数timeout,等待时间。

fd_set结构是一个结构体。

[cpp]
typedef struct fd_set
{
u_int fd_count;
socket fd_array[FD_SETSIZE];
}fd_set;

fd_cout表示该集合套接字数量。最大为64.

fd_array套接字数组。

select函数中需要三个fd_set结构:

一:准备接收数据的套接字集合,即可读性集合。

二:准备发送数据的套接字集合,即可写性集合。

在select函数返回时,会在fd_set结构中,填入相应的套接字。

readfds数组将包括满足以下条件的套接字:

1:有数据可读。此时在此套接字上调用recv,立即收到对方的数据。

2:连接已经关闭、重设或终止。

3:正在请求建立连接的套接字。此时调用accept函数会成功。

writefds数组包含满足下列条件的套接字:

1:有数据可以发出。此时在此套接字上调用send,可以向对方发送数据。

2:调用connect函数,并连接成功的套接字。

exceptfds数组将包括满足下列条件的套接字:

1:调用connection函数,但连接失败的套接字。

2:有带外(out of band)数据可读。

select函数的使用:

在调用select函数对套接字进行监视之前,必须将要监视的套接字分配给上述三个数
组中的一个。然后调用select函数,再次判断需要监视的套接字是否还在原来的集合中。
就可以知道该集合是否正在发生IO操作。

例如:应用程序想要判断某个套接字是否存在可读的数据,需要进行如下步骤:

1:将该套接字加入到readfds集合。

2:以readfds作为第二个参数调用select函数。

3:当select函数返回时,应用程序判断该套接字是否仍然存在于readfds集合。

4:如果该套接字存在与readfds集合,则表明该套接字可读。此时就可以调用recv
函数接收数据。否则,该套接字不可读。

在调用select函数时,readfds、writefds和exceptfds三个参数至少有一个为非空。
并且在该非空的参数中,必须至少包含一个套接字。否则select函数将没有任何套接字可
以等待。

timeval结构体用于定义select的等待时间。

[cpp]
structure timeval
{
long tv_sec;//秒。
long tv_usec;//毫秒。
};

当timeval为空指针时,select会一直等待,直到有符合条件的套接字时才返回。

当tv_sec和tv_usec之和为0时,无论是否有符合条件的套接字,select都会立即返
回。

当tv_sec和tv_usec之和为非0时,如果在等待的时间内有套接字满足条件,则该函
数将返回符合条件的套接字。如果在等待的时间内没有套接字满足设置的条件,则select
会在时间用完时返回,并且返回值为0。

为了方便使用,windows sockets提供了下列宏,用来对fd_set进行一系列操作。使
用以下宏可以使编程工作简化。

FD_CLR(s,*set);从set集合中删除s套接字。

FD_ISSET(s,*set);检查s是否为set集合的成员。

FD_SET(s,*set);将套接字加入到set集合中。

FD_ZERO(*set);将set集合初始化为空集合。

在开发Windows sockets应用程序时,通过下面的步骤,可以完成对套接字的可读写判
断:

1:使用FD_ZERO初始化套接字集合。如FD_ZERO(&readfds);

2:使用FD_SET将某套接字放到readfds内。如:

FD_SET(s,&readfds);

3:以readfds为第二个参数调用select函数。select在返回时会返回所有fd_set集
合中套接字的总个数,并对每个集合进行相应的更新。将满足条件的套接字放在相应的集合
中。

4:使用FD_ISSET判断s是否还在某个集合中。如:

FD_ISSET(s,&readfds);

5:调用相应的Windows socket api 对某套接字进行操作。

select返回后会修改每个fd_set结构。删除不存在的或没有完成IO操作的套接字。
这也正是在第四步中可以使用FD_ISSET来判断一个套接字是否仍在集合中的原因。

看例子,该例演示了一个服务器程序使用select模型管理套接字。

[cpp]
SOCKET listenSocket;
[cpp]
SOCKET acceptSocket;
FD_SET socketSet;
FD_SET writeSet;
FD_SET readSet;

FD_ZERO(&socketSet);
FD_SET(listenSocket,&socketSet);
while(true)
{
FD_ZERO(&readSet);
FD_ZERO(&writeSet);

相关文档
最新文档