|
|
函数的原形如下:
BOOL TransmitFile(
SOCKET hSocket,
HANDLE hFile,
DWORD nNumberOfBytesToWrite,
DWORD nNumberOfBytesPerSend,
LPOVERLAPPED lpOverlapped,
LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
DWORD dwFlags
);
TransmitPackets API比TransmitFile API更进一步,允许调用者一次指定多个文件句柄和内存缓冲区,并进行传输。原形如下:
BOOL TransmitPackets(
SOCKET hSocket,
LPTRANSMIT_PACKET_ELEMENT lpPacketArray,
DWORD nElementCount,
DWORD nSendSize,
LPOVERLAPPED lpOverlapped,
DWORD dwFlags
);
lpPacketArray包含结构体的数组。每个入口点指定一个需要被传输的文件句柄或内存缓冲,该结构的成员如下:
typedef struct _TRANSMIT_PACKETS_ELEMENT {
DWORD dwElFlags;
DWORD cLength;
union {
struct {
LARGE_INTEGER nFileOffset;
HANDLE hFile;
};
PVOID pBuffer;
};
} TRANSMIT_FILE_BUFFERS;
各成员的名字都是自解释的。dwEIFlags成员指明结构体里的元素是一个文件句柄(TF_ELEMENT_FILE)还是一个内存缓冲(TF_ELEMENT_MEMORY)。cLength成员表示要传输的字节数(对于文件句柄,0则表示文件内所有的数据)。一个未命名的联合体(union)包含内存缓冲指针或文件句柄(以及指定的偏移量)。
使用这两个函数的其他好处是,你可以通过指定TF_REUSE_SOCKET标志(必须同时指定TF_DISCONNECT标志)重用socket句柄。一旦API函数完成数据传输,连接就会在传输点的层次上断开,然后该socket就可以被AcceptEx重新使用。这样就可以减少反复创建socket和的次数,优化了效率。
使用这两个函数要注意的是,在WinNT Workstation版本或win2000 Professional版本上,并不能实现优化性能。必须在winNT,win2000 Server ,Win2000 Advanced Server 或Win2000 Data Center版本上才能实现。
来实现一个服务方案
在前几章里,我们介绍了一些有益于改善性能提高扩展性的APIs和方法,以及可能遇到的资源瓶颈。这对你有用吗?当然,首先取决于你的服务端和客户端的设计。在设计时,你对服务端和客户端的控制越得力,你就能更好的避免瓶颈
让我们来看一种简单的用例,在这个用例里我们设计一个服务器,这个服务器处理客户端的连接,然后客户端发送一次数据,并期待服务端的回应,然后客户端断开连接。
我们的设计是:服务器创建一个监听socket,并和一个完成端口相关联,然后创建和CPU同等数量的工作线程,以及一个专门用来进行AcceptEx调用的线程。既然我们知道客户端一旦连接马上就会发送数据 ,那么准备一个接受缓冲区会有利于工作的进行。当然,不要忘记经常的检查正在连接的socket的SO_CONNECT_TIME值,避免死连接。
本设计中重要的一项是决定需要显形调用多少个AcceptEx。因为每个AcceptEx操作都需要一个接收缓冲区,大量的页面将被锁定(还记得每个重叠操作都会消耗一些非分页内存,并且会将一些数据缓冲锁定到内存里吗)。没有公式和具体的准则指导如何确定究竟允许多少个AcceptEx操作。最好的方案就是使这个数目成为可调的,通过性能测试,寻找一个在典型的环境下最好的值
现在已经确定服务器是如何处理连接的了,下一步就是发送数据。影响发送数据的重要因素就是你期望服务器能够并发的处理连接数。一般来说,服务器应该限制并发的连接数量,以及显式的send调用。越多的连接数意味着越多的非分页内存的使用,并发的send调用也应该被限制,避免冲击系统的可分页内存锁定极限。连接数和并发的send调用限制也都应该是程序可调节的。
在本例的情况里,不必要去取消每个socket的接收缓冲,因为接收事件仅仅在AcceptEx调用中发生。保证每个socket都有一个接收缓冲不会造成什么危害。一旦客户端/服务器在最初的一次请求(由AcceptEx完成)之后进行交互,发送更多的数据,那么取消接收缓冲更是一个很不好的做法。除非你能保证这些数据都是在每个连接的重叠IO接收里完成的 。
结束语:
重复:开发一个可扩展的Winsock服务器并非十分困难的。仅仅是开始一个监听socket,接收连接,并且进行重叠发送和接收的IO操作。最大的挑战就是管理系统资源,限制重叠Io的数量,避免内存危机。遵循这几个原则,就能帮助你开发高性能,可扩展的服务程序。
--------------------------------------------------------------------------------
网友评论:(评论内容只代表网友观点,与本站立场无关!) |
阅读排行
|