众所周知,回声服务器是一个从套接字读取数据并将该数据写入另一个套接字的服务器。
由于Windows I/O完成端口提供了不同的操作方式,我想知道实现回声服务器的最佳方式(最有效的方式)是什么。我确信能够找到测试我将在此处描述的方法的人,并能贡献他/她的经验。
我的类是“Stream”,它抽象了一个套接字、命名管道或其他内容,以及“IoRequest”,它抽象了“OVERLAPPED”结构和执行I/O的内存缓冲区(当然,适用于读取和写入)。通过这种方式,当我分配一个“IoRequest”时,我只需一次性为数据内存缓冲区和“OVERLAPPED”结构分配内存,因此我只调用一次“malloc()”。
除此之外,我还在“IoRequest”对象中实现了一些花哨而有用的东西,比如原子引用计数等。
说了那么多,让我们探索做最好的回声服务器的方法:
-------------------------------------------- 方法A. ------------------------------------------
1) "读取"套接字完成其读取,IOCP回调返回,你有一个刚完成的带内存缓冲区的"IoRequest"。
2) 让我们将刚收到的缓冲区与"读取"IoRequest"复制到"写入"IoRequest"中。(这将涉及一个“memcpy()”或其他方式)。
3) 让我们在“读取”中再次使用用于读取的相同“IoRequest”的“ReadFile()”进行新的读取。
4) 在“写入”中进行新的写入。
-------------------------------------------- 方法B. ------------------------------------------
1) "读取"套接字完成其读取,IOCP回调返回,你有一个刚完成的带内存缓冲区的"IoRequest"。
2) 而不是复制数据,将该“IoRequest”传递给“写入”进行写入,而无需使用“memcpy()”复制数据。
3) 现在,“读取”需要一个新的“IoRequest”来继续读取,可以分配一个新的,也可以传递之前已经分配的一个,可能是刚完成写入的一个。
所以,在第一种情况下,每个
我的问题是:
问题1)避免复制数据真的值得吗!? 使用
问题2)我猜当我对N个不同套接字使用
由于Windows I/O完成端口提供了不同的操作方式,我想知道实现回声服务器的最佳方式(最有效的方式)是什么。我确信能够找到测试我将在此处描述的方法的人,并能贡献他/她的经验。
我的类是“Stream”,它抽象了一个套接字、命名管道或其他内容,以及“IoRequest”,它抽象了“OVERLAPPED”结构和执行I/O的内存缓冲区(当然,适用于读取和写入)。通过这种方式,当我分配一个“IoRequest”时,我只需一次性为数据内存缓冲区和“OVERLAPPED”结构分配内存,因此我只调用一次“malloc()”。
除此之外,我还在“IoRequest”对象中实现了一些花哨而有用的东西,比如原子引用计数等。
说了那么多,让我们探索做最好的回声服务器的方法:
-------------------------------------------- 方法A. ------------------------------------------
1) "读取"套接字完成其读取,IOCP回调返回,你有一个刚完成的带内存缓冲区的"IoRequest"。
2) 让我们将刚收到的缓冲区与"读取"IoRequest"复制到"写入"IoRequest"中。(这将涉及一个“memcpy()”或其他方式)。
3) 让我们在“读取”中再次使用用于读取的相同“IoRequest”的“ReadFile()”进行新的读取。
4) 在“写入”中进行新的写入。
-------------------------------------------- 方法B. ------------------------------------------
1) "读取"套接字完成其读取,IOCP回调返回,你有一个刚完成的带内存缓冲区的"IoRequest"。
2) 而不是复制数据,将该“IoRequest”传递给“写入”进行写入,而无需使用“memcpy()”复制数据。
3) 现在,“读取”需要一个新的“IoRequest”来继续读取,可以分配一个新的,也可以传递之前已经分配的一个,可能是刚完成写入的一个。
所以,在第一种情况下,每个
Stream
对象都有其自己的IoRequest
,数据是使用memcpy()
或类似函数复制的,一切正常。
在第二种情况下,2个Stream
对象互相传递IoRequest
对象,而不复制数据,但它稍微复杂一些,您必须管理在两个Stream
对象之间“交换”IoRequest
对象,可能会出现同步问题(那些在不同线程中发生的完成呢?)我的问题是:
问题1)避免复制数据真的值得吗!? 使用
memcpy()
或类似函数复制2个缓冲区非常快,这也是因为CPU缓存被利用于此目的。
让我们考虑使用第一种方法,我有可能从“读取器”套接字回显到多个“写入器”套接字,但是用第二种方法却无法做到这一点,因为我应该为每个N写入者创建N个新的IoRequest
对象,因为每个WriteFile()
需要其自己的OVERLAPPED
结构。问题2)我猜当我对N个不同套接字使用
WriteFile()
触发新的N个写入时,我必须提供N个不同的OVERLAPPED
结构和N个不同的缓冲区来读取数据。
或者,我可以使用N个不同的OVERLAPPED
从相同的缓冲区为N个套接字触发N个WriteFile()
调用吗?