发明内容
本发明实施例提供了一种进程间通信方法、电子设备及可读存储介质,用于解决大量客户端在同一时刻高并发连接命名管道服务器容易连接失败的问题,从而提高命名管道服务器的性能。
第一方面,本发明提供了一种进程间通信方法,应用于服务器,包括:
创建服务线程,所述服务线程用于处理针对客户端的异步任务,所述异步任务包括处理客户端的连接请求、接收客户端发送的数据请求以及向客户端发送数据请求;
调用accept函数,通过所述accept函数调用CreateNamedPipe函数创建异步的命名管道句柄和通过所述accept函数创建重叠IO,将所述命名管道句柄传入所述重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务,调用GetLastError函数,获得所述命名管道句柄的当前连接状态;
在所述当前连接状态为ERROR_IO_PENDING时,将所述重叠IO存放至与所述异步任务对应的存储空间中,其中,所述服务器中设置有用于存储所述处理客户端的连接请求对应的重叠IO的第一存储空间、用于存储所述接收客户端发送的数据请求对应的重叠IO的第二存储空间以及用于存储所述向客户端发送数据请求对应的重叠IO的第三存储空间;
在所述当前连接状态为ERROR_PIPE_CONNECTED时,确定与所述命名管道句柄连接的第一客户端,处理与所述第一客户端对应的数据任务,在所述数据任务处理完成后,如果所述命名管道句柄的当前连接状态为ERROR_IO_PENDING,将所述重叠IO存放至与所述异步任务对应的存储空间中;
通过所述服务线程循环查看所述第一存储空间、所述第二存储空间以及所述第三存储空间中的重叠IO,如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO。
可选的,所述处理与所述第一客户端对应的数据任务,包括:
调用onAccepted函数,在所述onAccepted函数中创建目标会话对象,调用所述目标会话对象的asyncReadSome函数,读取所述第一客户端发送的数据。
可选的,通过所述accept函数调用CreateNamedPipe函数创建异步的命名管道句柄,包括:
通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄,其中,所述命名管道句柄通过所述预设安全访问属性指定访问等级,所述命名管道句柄指定的访问等级使得所述服务器以管理员权限或非管理员权限创建所述命名管道句柄情况下,所述客户端均能访问所述命名管道句柄。
可选的,在所述调用accept函数之前,所述方法还包括:
初始化安全描述符;
将所述安全描述符的安全访问级别设置为最低等级;
创建安全属性描述结构,将安全访问级别设置为最低等级的所述安全描述符传入所述安全属性描述结构的属性字段中;
将创建的所述安全属性描述结构传入所述CreateNamedPipe函数的安全属性参数中,以使得所述CreateNamedPipe函数的安全属性设置为所述预设安全访问属性。
可选的,在所述如果查看到当前重叠IO处理完成之后,所述方法还包括:
将所述当前重叠IO从对应的存储空间中删除。
可选的,所述如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO,包括:
如果所述当前重叠IO为所述第一存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定有客户端连接到所述服务器;
调用onAccepted函数,在所述onAccepted函数中创建第一会话对象,调用所述第一会话对象的asyncReadSome函数,读取所述客户端发送的数据;
继续处理下一个存储空间的重叠IO。
可选的,所述如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO,包括:
如果所述当前重叠IO为所述第二存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功接收到来自客户端发送的数据;
通过所述当前重叠IO中Pointer字段获取所述当前重叠IO对应的第二会话对象;
调用所述第二会话对象的onReadComplete函数处理接收到的数据;
调用所述第二会话对象的asyncReadSome函数,把下一个读取的重叠IO放入到所述第二存储空间;
继续处理下一个存储空间的重叠IO。
可选的,所述如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO,包括:
如果所述当前重叠IO为所述第三存储空间中的重叠IO,定位与所述当前重叠IO对应的第三会话对象;
调用所述第三会话对象的asyncWriteSome函数异步的发送数据至客户端;
调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功的将数据发送至客户端;
继续处理下一个存储空间的重叠IO。
第二方面,本发明实施例提供一种电子设备,应用于服务器,包括:
创建单元,用于创建服务线程,所述服务线程用于处理针对客户端的异步任务,所述异步任务包括处理客户端的连接请求、接收客户端发送的数据请求以及向客户端发送数据请求;
调用单元,用于调用accept函数,通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄和通过所述accept函数创建重叠IO,将所述命名管道句柄传入所述重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务;
第一处理单元,用于在所述当前连接状态为ERROR_IO_PENDING时,将所述重叠IO存放至与所述异步任务对应的存储空间中,其中,所述服务器中设置有用于存储所述处理客户端的连接请求对应的重叠IO的第一存储空间、用于存储所述接收客户端发送的数据请求对应的重叠IO的第二存储空间以及用于存储所述向客户端发送数据请求对应的重叠IO的第三存储空间;
第二处理单元,用于在所述当前连接状态为ERROR_PIPE_CONNECTED时,确定与所述命名管道句柄连接的第一客户端,处理与所述第一客户端对应的数据任务,在所述数据任务处理完成后,如果所述命名管道句柄的当前连接状态为ERROR_IO_PENDING,将所述重叠IO存放至与所述异步任务对应的存储空间中;
第三处理单元,用于通过所述服务线程循环查看所述第一存储空间、所述第二存储空间以及所述第三存储空间中的重叠IO,如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO。
可选的,所述第二处理单元具体用于:
调用onAccepted函数,在所述onAccepted函数中创建目标会话对象,调用所述目标会话对象的asyncReadSome函数,读取所述第一客户端发送的数据。
可选的,所述调用单元具体用于:
通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄,其中,所述命名管道句柄通过所述预设安全访问属性指定访问等级,所述命名管道句柄指定的访问等级使得所述服务器以管理员权限或非管理员权限创建所述命名管道句柄情况下,所述客户端均能访问所述命名管道句柄。
可选的,所述电子设备还包括安全属性设置单元,具体用于:
在所述调用accept函数之前,初始化安全描述符;
将所述安全描述符的安全访问级别设置为最低等级;
创建安全属性描述结构,将安全访问级别设置为最低等级的所述安全描述符传入所述安全属性描述结构的属性字段中;
将创建的所述安全属性描述结构传入所述CreateNamedPipe函数的安全属性参数中,以使得所述CreateNamedPipe函数的安全属性设置为所述预设安全访问属性。
可选的,所述第三处理单元还用于:
在所述如果查看到当前重叠IO处理完成之后,将所述当前重叠IO从对应的存储空间中删除。
可选的,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第一存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定有客户端连接到所述服务器;
调用onAccepted函数,在所述onAccepted函数中创建第一会话对象,调用所述第一会话对象的asyncReadSome函数,读取所述客户端发送的数据;
继续处理下一个存储空间的重叠IO。
可选的,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第二存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功接收到来自客户端发送的数据;
通过所述当前重叠IO中Pointer字段获取所述当前重叠IO对应的第二会话对象;
调用所述第二会话对象的onReadComplete函数处理接收到的数据;
调用所述第二会话对象的asyncReadSome函数,把下一个读取的重叠IO放入到所述第二存储空间;
继续处理下一个存储空间的重叠IO。
可选的,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第三存储空间中的重叠IO,定位与所述当前重叠IO对应的第三会话对象;
调用所述第三会话对象的asyncWriteSome函数异步的发送数据至客户端;
调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功的将数据发送至客户端;
继续处理下一个存储空间的重叠IO。
第三方面,本发明实施例提供一种电子设备,所述电子设备包括处理器,所述处理器用于执行存储器中存储的计算机程序时实现如前述第一方面实施例中所述的进程间通信方法的步骤。
第四方面,本发明实施例提供了一种可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现如前述第一方面实施例中所述的进程间通信方法的步骤。
本申请实施例中的上述一个或多个技术方案,至少具有如下一种或多种技术效果:
在本发明实施例的技术方案中,首先创建服务进程,用于与多个客户端的进程通信,处理客户端的异步任务。进而,再调用accept函数创建异步任务对应的异步的命名管道句柄和重叠IO,将异步的命名管道句柄传入重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务,在将重叠IO存放至与异步任务对应的存储空间中之前,需要调用GetLastError函数,获得命名管道句柄的当前连接状态,如果当前连接状态为ERROR_IO_PENDING,表明此时没有任何的客户端调用WaitNamedPipe方法去连接命名管道句柄,所以,可以将重叠IO存放至与异步任务对应的存储空间中,通过服务线程循环查看的存储空间,处理重叠IO,实现异步任务处理。而在当前连接状态为ERROR_PIPE_CONNECTED时,表明服务器端调用CreateNamedPipe创建一个命名管道句柄后,还没有来得及调用ConnectNamedPipe函数,恰好第一客户端调用了WaitNamedPipe去连接刚刚创建的命名管道句柄,如果此时将重叠IO存放至与异步任务对应的存储空间中,通过服务线程循环查看的存储空间,处理重叠IO,会导致大量客户端都连接不上命名管道句柄,即服务器无法调用服务线程去处理重叠IO,需要等待处理完与第一客户端间的数据任务后,待命名管道句柄与第一客户端间的连接断开后,才将重叠IO存放至与异步任务对应的存储空间中,再通过服务线程循环查看的存储空间,处理重叠IO,实现异步任务处理。这样,能有效提高客户端连接命名管道句柄的成功率。
实施例
请参考图1,本发明第一实施例提供一种进程间通信方法,应用于服务器,该进程间通信方法包括如下步骤:
S101:创建服务线程,所述服务线程用于处理针对客户端的异步任务,所述异步任务包括处理客户端的连接请求、接收客户端发送的数据请求以及向客户端发送数据请求;
S102:调用accept函数,通过所述accept函数调用CreateNamedPipe函数创建异步的命名管道句柄和通过所述accept函数创建重叠IO,将所述命名管道句柄传入所述重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务,调用GetLastError函数,获得所述命名管道句柄的当前连接状态;
S103:在所述当前连接状态为ERROR_IO_PENDING时,将所述重叠IO存放至与所述异步任务对应的存储空间中,其中,所述服务器中设置有用于存储所述处理客户端的连接请求对应的重叠IO的第一存储空间、用于存储所述接收客户端发送的数据请求对应的重叠IO的第二存储空间以及用于存储所述向客户端发送数据请求对应的重叠IO的第三存储空间
S104:在所述当前连接状态为ERROR_PIPE_CONNECTED时,确定与所述命名管道句柄连接的第一客户端,处理与所述第一客户端对应的数据任务,在所述数据任务处理完成后,如果所述命名管道句柄的当前连接状态为ERROR_IO_PENDING,将所述重叠IO存放至与所述异步任务对应的存储空间中;
S105:通过所述服务线程循环查看所述第一存储空间、所述第二存储空间以及所述第三存储空间中的重叠IO,如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO。
其中,在所述如果查看到当前重叠IO处理完成之后,将所述当前重叠IO从对应的存储空间中删除。
具体的,本实施例中的方法主要应用于服务器端,在服务器端,服务器进程调用CreateNamedPipe函数根据一个指定的名称pipename来创建一个有名称的命名管道,然后调用ConnectNamedPipe来等待客户端的连接请求,这个函数既可以支持同步方式,又可以支持异步方式,若果服务器进程以同步方式调用ConnectNamedPipe函数,那么如果没有得到客户端的连接请求,那么会一直等到客户端的连接请求,所以此时会阻塞调用该函数的线程,当该函数返回时,客户端便与服务器端建立了通信连接。如果服务器端以异步的方式调用ConnectNamedPipe函数来处理客户端的连接请求,那么该函数会立即返回,不会阻塞调用该函数的线程。但是在以异步方式调用该函数时,需要指定一个结构类型为OVERLAPPED的重叠IO参数,传递给该ConnectNamedPipe函数,然后在一个服务线程中定时的查看该重叠IO是否完成,如果该重叠IO完成,那么就代表有客户端的连接请求。
在客户端,客户端进程首先调用WaitNamedPipe函数,将同样的管道名称pipename传入到WaitNamedPipe函数中,如果WaitNamedPipe函数返回成功,则代表连接服务器成功,然后调用CreateFile函数打开服务器端的管道句柄,这样便可以与服务器端进行通信了。
上面简要的概述了利用Windows操作系统的命名管道API进行服务器端与客户端之间建立通信连接的简要过程,后面的步骤来详细的说明实现一个服务器进程与多个客户端进程之间进行异步通信的方法。
为了测试命名管道句柄服务器的压力,本实施例设计了一种测试实例,在该实例中同时创建了200个线程,并且在每一个线程中,创建一个命名管道客户端实例,然后去连接服务器中创建的命名管道句柄。发现在最终的连接结果中,只有极少数的客户端连上了服务器的命名管道句柄。当出现只有极少数的客户端连上了服务器的命名管道句柄的情况后,如果再启动一个客户端去连接命名管道句柄,该客户端可能永远连接不上服务器。
针对上述问题,首先需明白,命名管道句柄的连接机制,在服务器端应该是创建一个命名管道句柄,然后等待客户端连接;而在客户端,只要有相应的未处于连接的命名管道句柄,就可以连接上。对应到Windows系统API上,这个流程可以这样表达:
服务器端
1)调用CreateNamedPipe函数创建一个未处于连接的命名管道;
2)调用ConnectNamedPipe等待客户端的接入。
客户端
1)调用WaitNamedPipe连接服务器端;
2)调用CreateFile创建与服务器端进行通信的管道句柄。
其中,在服务器在调用ConnectNamedPipe函数时,分为同步阻塞方式,以及异步方式。当采用同步阻塞方式时,必须等到客户端连接成功后,该函数才会返回。而异步方式,会立即返回,并不等待客户端的连接。由于同步阻塞方式会阻塞线程,所以在本实施例中,采取异步方式。
本实施例中的方法,实现了通过一个NamedPipeServer的模块用来代表一个命名管道服务器,该模块实现了上述的与多个客户端之间进行异步连接以及异步数据通信的功能。
首先,通过步骤S101创建服务线程,因为本实施例中的方法采取的时异步的方式,所以,首先创建一个独立的线程来处理所有的异步任务,这些异步任务包括来自客户端的连接请求,接收来自客户端发送的数据以及向客户端发送数据。
然后,通过步骤S102准备客户端链接请求,在NamedPipeServer模块中调用accept函数,accept函数的主要功能是创建一个异步的命名管道句柄,然后创建一个重叠IO来异步的处理连接请求。accept函数中的主要逻辑如下:
首先,调用CreateNamedPipe函数创建一个命名管道句柄,在调用该函数时,将命名管道的名称传入到该函数的第一个参数中,然后将FILE_FLAG_OVERLAPPED传入到该函数的第二个参数中,表示要创建的是一个异步的命名管道。如果该函数的返回值不等于INVALID_HANDLE_VALUE则代表创建命名管道句柄成功。
而当采取异步方式时,调用ConnectNamedPipe后,应该调用系统的GetLastError方法,通过该方法的返回值,获得命名管道句柄的当前连接状态。具体的,GetLastError方法可能返回两种状态,一个是悬而未决状态(ERROR_IO_PENDING),此种状态表示该命名管道句柄还没有被客户端连接。一种是已连接状态(ERROR_PIPE_CONNECTED)。出现上述两种状态的情况,可以用下面的两种现象来解释:
在GetLastError方法返回的状态为ERROR_IO_PENDING,服务器的命名管道句柄创建好,并准备好等待客户端连接,但是迟迟没有客户端的接入请求。对应到API层次上,就是当调用完ConnectNamedPipe之后,此时没有任何的客户端调用WaitNamedPipe方法,去连接命名管道句柄。这种现象发生在所有客户端按照时间顺序,一个一个去串行连接服务器的时候。按照时序图应该是:CreateNamedPipe->ConnectNamedPipe->WaitNamedPipe。
在GetLastError方法返回的状态为ERROR_PIPE_CONNECTED,此种情况可能是有大量客户端同时并发的去连接服务器的命名管道句柄。该情况发生在服务器端调用CreateNamedPipe创建一个命名管道句柄后,并且还没有来得及调用ConnectNamedPipe时,恰好有一个客户端调用了WaitNamedPipe去连接刚刚创建的命名管道句柄。此时在服务器端调用ConnectNamedPipe后,就会出现ERROR_PIPE_CONNECTED的情况。按照时序图应该是下面这样的:CreateNamedPipe->WaitNamedPipe->ConnectNamedPipe。
所以针对上述机制的分析,本实施例为了解决客户端高并发连接命名管道句柄造成连接阻塞的问题,在调用ConnectNamedPipe函数,异步的等待来自客户端的连接请求后,调用GetLastError函数,获取命名管道句柄的当前连接状态,标记为connectStatus。
进一步,在NamedPipeServer中有三个存储空间,这三个存储空间中,存放的都是类型为OVERLAPPED的异步重叠IO,它们分别是m_pipePendingArray,用来代表所有的异步连接,存放在第一存储空间。m_readPendingArray用来代表所有正在异步接收的请求,存放在第二存储空间;m_writePendingArray用来代表所有异步发送的请求,存放在第三存储空间。
然后,针对获得的当前连接状态connectStatus进行判断,通过步骤S103,如果该值等于ERROR_IO_PENDING,将上步骤中创建的OVERLAPPED重叠IO放入到m_pipePendingArray中,在服务线程中循环的处理这三个存储空间,后面针对客户端的异步连接、异步接收以及异步发送都是分别对这三个存储空间的处理。
进一步,针对获得的当前连接状态connectStatus进行判断,通过步骤S103,如果connectStatus的值等于ERROR_PIPE_CONNECTED,此时该命名管道已经同第一客户端建立起了连接,此时绝对不能把异步任务对应的重叠IO放入到对应的存储空间中,否则就会出现前述问题,请求的客户端永远连接不上命名管道句柄,因为该命名管道句柄已经被第一客户端连接上,任何其他的客户端就再也不能跟该命名管道进行连接。此时因为该命名管道句柄已经与第一客户端建立了连接,所以,服务器可以调用onAccepted函数,在onAccepted函数中创建目标会话对象,调用目标会话对象的asyncReadSome函数,读取所述第一客户端发送的数据,处理与第一客户端间的数据任务。这样,能确保第一客户端能与服务器的命名管道句柄正常通信。进而,在服务器处理完与第一客户端间的数据任务后,可以在预设时间间隔调用GetLastError函数,获得命名管道句柄的当前连接状态,如果当前连接状态转变至ERROR_IO_PENDING状态时,则可将创建的OVERLAPPED重叠IO放入到对应的存储空间中,在服务线程中循环的处理这三个存储空间,后面针对客户端的异步连接、异步接收以及异步发送都是分别对这三个存储空间的处理。
进而,在确定OVERLAPPED重叠IO放入到对应存储空间中后,即可通过S105,循环的处理m_pipePendingArray、m_readPendingArray、m_writePendingArray这三个存储空间,后面针对客户端的异步连接、异步接收以及异步发送都是分别对这三个存储空间的处理。
具体的,CreateNamedPipe函数包括8个参数,第一个参数为LPCTSTRlpName,表示管道名称,最多可达256个字符的长度,而且不区分大小写。第二个参数为DWORDdwOpenMode,表示管道的打开方式。第三个参数为DWORDdwPipeMode。表示管道的模式。第四个参数为DWORDnMaxInstances,表示该管道所能够创建的最大实例数量,必须是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。第五个参数是DWORDnOutBufferSize,表示管道的输出缓冲区容量,为0表示使用默认大小。第六个参数为DWORDnInBufferSize,表示管道的输入缓冲区容量,为0表示使用默认大小。第七个参数为DWORDnDefaultTimeOut,表示管道的默认等待超时。第八个参数为LPSECURITY_ATTRIBUTESlpSecurityAttributes,是安全属性参数,表示管道的安全属性。
在现有技术中,通过NamedPipeServer在调用CreateNamedPipe函数,创建命名管道句柄时,将该函数的最后一个参数,即安全属性参数默认传入的是NULL空值,那么创建的命名管道句柄的安全访问等级将使用系统默认的安全访问等级。当命名管道句柄的服务程序启动时,将出现下面四种不同的情况:
第一种:服务器端与客户端均以管理员权限启动,当命名管道句柄的通信双方都采用管理员权限启动时,客户端能够连接上服务器,双方通信正常。
第二种:服务器端以管理员权限启动,客户端以非管理员权限启动。如果服务器端以管理员权限启动,那么客户端在调用CreateFile打开服务器端创建的命名管道句柄时,因为权限不够,将会导致失败,从而导致客户端连接不上服务器端,双方通信失败。
第三种:服务器端以非管理员权限启动,客户端以管理员权限启动。当服务器端以非管理员权限启动时,那么其创建的命名管道句柄句柄也不会拥有管理员权限,当客户端以管理员权限启动时,调用CreateFile打开命名管道句柄时,能够成功,从而双方能够正常的通信。
第四种:服务器端与客户端均以非管理员权限启动。当通信双方都以普通权限启动,而非管理员权限启动时,客户端能够连上服务器,双方通信正常。
从上面的4种情况来看,当服务器端以管理员权限启动,而客户端以非管理员权限启动时,客户端会出现连不上服务器。为了解决这种情况,在步骤S102中,NamedPipeServer在调用CreateNamedPipe系统API时,不能使用默认的系统权限去创建,而应该以设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄。这样,命名管道句柄通过预设安全访问属性指定访问等级,命名管道句柄指定的访问等级使得所述服务器以管理员权限或非管理员权限创建所述命名管道句柄情况下,客户端均能访问命名管道句柄。所以,本实施例中,在创建命名管道句柄之前,需要对CreateNamedPipe函数设置预设安全访问属性,可通过如下步骤实现:
初始化安全描述符;将所述安全描述符的安全访问级别设置为最低等级;创建安全属性描述结构,将安全访问级别设置为最低等级的所述安全描述符传入所述安全属性描述结构的属性字段中;将创建的所述安全属性描述结构传入所述CreateNamedPipe函数的最后一个参数,即安全属性参数中,以使得所述CreateNamedPipe函数的安全属性设置为所述预设安全访问属性。
具体的,在本实施例中,首先初始化一个安全描述符。具体的,调用系统的InitializeSecurityDescriptor函数,初始化一个SECURITY_DESCIRPTOR的安全描述符结构。
然后,将安全描述符的安全访问级别设置为最低等级,具体的,上述初始化了一个安全描述符后,需要设置它的安全访问级别,当把其安全访问级别设置成最低时,所有的访问请求都能够成功通过。所以,本实施例中的方法,将该安全描述符的安全访问级别设置成最低,这样创建出来的命名管道句柄,不管服务器端与客户端是否以管理员权限启动,双方都能够连接成功。
具体的,将安全描述符的安全访问级别设置为最低等级,在具体实现过程中,通过调用SetSecurityDescriptorDacl系统函数,将上述的安全描述符结构SECURITY_DESCRIPTOR传入到该SetSecurityDescriptorDacl系统函数的第一个参数中,第二个参数设置为TRUE,第三个参数设置为NULL(表示最低安全访问级别)。
最后,设置CreateNamedPipe函数的预设安全访问属性。具体的,创建一个类型为SECURITY_ATTRIBUTES的安全属性描述结构,并将前述的安全描述符结构SECURITY_DESCRIPTOR设置到SECURITY_ATTRIBUTES的属性字段lpSecurityDescriptor字段中,完成之后,将SECURITY_ATTRIBUTES结构传入到CreateNamedPipe函数的最后一个参数,即安全属性参数中。这样,完成了CreateNamedPipe函数的预设安全访问属性的设置,通过该CreateNamedPipe函数创建出来的命名管道句柄其安全访问级别是最低等级,所以,不管服务器端是否以管理员权限启动,客户端都能够连接上。
对于三种不同的异步任务,处理过程可分为以下三种:
第一种:处理异步连接。
如果所述当前重叠IO为所述第一存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定有客户端连接到所述服务器;
调用onAccepted函数,在所述onAccepted函数中创建第一会话对象,调用所述第一会话对象的asyncReadSome函数,读取所述客户端发送的数据;
继续处理下一个存储空间的重叠IO。
具体的,在本实施例中,继续沿用上述示例,在服务线程中,如果当前重叠IO为第一存储空间中的重叠IO,即对于m_pipePendingArray中的每一个类型为OVERLAPPED的重叠IO,调用HasOverlappedIoCompleted函数,如果该函数返回true,那么代表已有客户端连接到服务器中,ConnectNamedPipe的结果最终得到处理,然后调用NamedPipeServer的onAccepted函数,在onAccepted函数中,主要是创建一个NamedPipeSession会话对象用来代表服务器端与客户端的一个通信连接,然后调用NamedPipeSession的asyncReadSome函数,准备读取来着客户端发送的数据,最后在onAccepted函数中再次调用accpet函数。具体的过程如下:
首先,创建一个类型为NamedPipeSession的会话对象,然后将该OVERLAPPED对象中的Pointer字段赋值给NamedPipeSession的m_pipe字段,从而根据m_pipe管道句柄来与客户端进行数据通信,然后给该NamedPipeSession指定一个数字型的sessionID,用来区分不同的NamedPipeSession对象。
然后,调用NamedPipeSession对象的asyncReadSome函数,异步的读取来自客户端的数据。在asyncReadSome函数中,首先同样创建一个OVERLAPPED的重叠IO,并且将该NamedPipeSession的this指针值放入到重叠IO的Pointer字段中,然后调用操作系统的ReadFile函数去异步的读取数据,在调用ReadFile函数时,将OVERLAPPED重叠IO传入到该函数的最后一个参数中,表示以异步的方式去读区客户端的数据,否则,会以同步的方式去读区数据然后将该OVERLAPPED重叠IO存入到NamedPipeServer的m_readPendingArray中,去处理异步读取的结果。
接着,调用完asyncReadSome函数后,再次调用NamedPipeServer的accept函数,处理下一个客户端的连接请求,从而再次执行本实施例中上述S102的相关逻辑,重复这样的逻辑,从而实现了一个服务器可以连接多个客户端的逻辑。
最后,因为已成功处理完异步连接请求,所以在m_pipePendingArray中移除该重叠IO。
第二种:处理异步接收。
如果所述当前重叠IO为所述第二存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功接收到来自客户端发送的数据;
通过所述当前重叠IO中Pointer字段获取所述当前重叠IO对应的第二会话对象;
调用所述第二会话对象的onReadComplete函数处理接收到的数据;
调用所述第二会话对象的asyncReadSome函数,把下一个读取的重叠IO放入到所述第二存储空间;
继续处理下一个存储空间的重叠IO。
具体的,在本实施例中,在服务线程中,如果当前重叠IO为第二存储空间中的重叠IO,即对于m_readPendingArray中的每一个类型为OVERLAPPED的重叠IO,调用HasOverlappedIoCompleted函数,如果该函数返回true,那么代表成功接收到来自客户端发送的数据。从而根据OVERLAPPED结果中的Pointer字段来获取NamedPipeSession对象,然后调用该NamedPipeSession对象的onReadComplete函数,在NamedPipeSession对象的onReadComplete函数中,处理完接收到的数据后,再次调用NamedPipeSession对象的asyncReadSome函数,再次把下一个读取的异步重叠IO放入到m_readPendingArray中,从而实现了NamedPipeSession对象的异步循环读取数据。同样的道理,因为已成功处理完异步发送数据的请求,所以,可从m_readPendingArray中移除该重叠IO。
第三种:处理异步发送。
如果所述当前重叠IO为所述第三存储空间中的重叠IO,定位与所述当前重叠IO对应的第三会话对象;
调用所述第三会话对象的asyncWriteSome函数异步的发送数据至客户端;
调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功的将数据发送至客户端;
继续处理下一个存储空间的重叠IO。
具体的,在本实施例中,在服务线程中,如果当前重叠IO为第三存储空间中的重叠IO,即在服务线程中,对于m_writePendingArray中的每一个类型为OVERLAPPED的重叠IO,调用HasOverlappedIoCompleted函数,如果该函数返回true,那么代表成功的将数据发送到了客户端从而根据OVERLAPPED结果中的Pointer字段来获取NamedPipeSession对象,然后调用该对象的onWriteComplete函数,将该重叠IO从NamedPipeServer的m_writePendingArray中删除。
同时,当NamedPipeServer向相应的客户端发送数据时,需要将向客户端发送数据请求对应的重叠IO存储至第三存储空间。首先根据制定的会话id,即NamedPipeSession的sessionID找到相对应的会话对象NamedPipeSession,然后调用会话对象NamedPipeSession的asyncWriteSome函数异步的发送数据。在asyncWriteSome函数中,同样首先创建一个OVERLAPPED的重叠IO,同样将该NamedPipeSession的this指针,传入到重叠IO的Pointer字段中,然后调用操作系统的WriteFile函数,将重叠IO传入到WriteFile函数的最后一个参数中,表示以异步的方式发送数据。最后将该重叠IO放入到m_writePendingArray集合中。
请参见图2,本发明的第二实施例提供了一种电子设备,所述电子设备包括:
创建单元201,用于创建服务线程,所述服务线程用于处理针对客户端的异步任务,所述异步任务包括处理客户端的连接请求、接收客户端发送的数据请求以及向客户端发送数据请求;
调用单元202,用于调用accept函数,通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄和通过所述accept函数创建重叠IO,将所述命名管道句柄传入所述重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务;
第一处理单元203,用于在所述当前连接状态为ERROR_IO_PENDING时,将所述重叠IO存放至与所述异步任务对应的存储空间中,其中,所述服务器中设置有用于存储所述处理客户端的连接请求对应的重叠IO的第一存储空间、用于存储所述接收客户端发送的数据请求对应的重叠IO的第二存储空间以及用于存储所述向客户端发送数据请求对应的重叠IO的第三存储空间;
第二处理单元204,用于在所述当前连接状态为ERROR_PIPE_CONNECTED时,确定与所述命名管道句柄连接的第一客户端,处理与所述第一客户端对应的数据任务,在所述数据任务处理完成后,如果所述命名管道句柄的当前连接状态为ERROR_IO_PENDING,将所述重叠IO存放至与所述异步任务对应的存储空间中;
第三处理单元205,用于通过所述服务线程循环查看所述第一存储空间、所述第二存储空间以及所述第三存储空间中的重叠IO,如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO。
在一种可选的实施方式中,所述第二处理单元具体用于:
调用onAccepted函数,在所述onAccepted函数中创建目标会话对象,调用所述目标会话对象的asyncReadSome函数,读取所述第一客户端发送的数据。
在一种可选的实施方式中,所述调用单元具体用于:
通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄,其中,所述命名管道句柄通过所述预设安全访问属性指定访问等级,所述命名管道句柄指定的访问等级使得所述服务器以管理员权限或非管理员权限创建所述命名管道句柄情况下,所述客户端均能访问所述命名管道句柄。
在一种可选的实施方式中,所述电子设备还包括安全属性设置单元,具体用于:
在所述调用accept函数之前,初始化安全描述符;
将所述安全描述符的安全访问级别设置为最低等级;
创建安全属性描述结构,将安全访问级别设置为最低等级的所述安全描述符传入所述安全属性描述结构的属性字段中;
将创建的所述安全属性描述结构传入所述CreateNamedPipe函数的安全属性参数中,以使得所述CreateNamedPipe函数的安全属性设置为所述预设安全访问属性。
在一种可选的实施方式中,所述第三处理单元还用于:
在所述如果查看到当前重叠IO处理完成之后,将所述当前重叠IO从对应的存储空间中删除。
在一种可选的实施方式中,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第一存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定有客户端连接到所述服务器;
调用onAccepted函数,在所述onAccepted函数中创建第一会话对象,调用所述第一会话对象的asyncReadSome函数,读取所述客户端发送的数据;
继续处理下一个存储空间的重叠IO。
在一种可选的实施方式中,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第二存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功接收到来自客户端发送的数据;
通过所述当前重叠IO中Pointer字段获取所述当前重叠IO对应的第二会话对象;
调用所述第二会话对象的onReadComplete函数处理接收到的数据;
调用所述第二会话对象的asyncReadSome函数,把下一个读取的重叠IO放入到所述第二存储空间;
继续处理下一个存储空间的重叠IO。
在一种可选的实施方式中,所述第三处理单元具体用于:
如果所述当前重叠IO为所述第三存储空间中的重叠IO,定位与所述当前重叠IO对应的第三会话对象;
调用所述第三会话对象的asyncWriteSome函数异步的发送数据至客户端;
调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功的将数据发送至客户端;
继续处理下一个存储空间的重叠IO。
请参见图3,本发明的第三实施例提供了一种电子设备,该实施例的电子设备包括:处理器301、存储器302以及存储在所述存储器中并可在所述处理器上运行的计算机程序,例如第一实施例中进程间通信方法对应的程序。所述处理器执行所述计算机程序时实现上述第一实施例中各路径检测中的步骤。或者,所述处理器执行所述计算机程序时实现上述第二实施例的电子设备中各模块/单元的功能。
示例性的,所述计算机程序可以被分割成一个或多个模块/单元,所述一个或者多个模块/单元被存储在所述存储器中,并由所述处理器执行,以完成本发明。所述一个或多个模块/单元可以是能够完成特定功能的一系列计算机程序指令段,该指令段用于描述所述计算机程序在所述计算机装置中的执行过程。例如,所述计算机程序可以被分割成创建单元、调用单元、第一处理单元、第二处理单元、第三处理单元的功能,各单元具体功能如下:
创建单元,用于创建服务线程,所述服务线程用于处理针对客户端的异步任务,所述异步任务包括处理客户端的连接请求、接收客户端发送的数据请求以及向客户端发送数据请求;
调用单元,用于调用accept函数,通过所述accept函数调用CreateNamedPipe函数创建异步的命名管道句柄和通过所述accept函数创建重叠IO,将所述命名管道句柄传入所述重叠IO的Pointer字段中,调用ConnectNamedPipe函数,异步等待来自客户端的所述异步任务,调用GetLastError函数,获得所述命名管道句柄的当前连接状态;
第一处理单元,用于在所述当前连接状态为ERROR_IO_PENDING时,将所述重叠IO存放至与所述异步任务对应的存储空间中,其中,所述服务器中设置有用于存储所述处理客户端的连接请求对应的重叠IO的第一存储空间、用于存储所述接收客户端发送的数据请求对应的重叠IO的第二存储空间以及用于存储所述向客户端发送数据请求对应的重叠IO的第三存储空间;
第二处理单元,用于在所述当前连接状态为ERROR_PIPE_CONNECTED时,确定与所述命名管道句柄连接的第一客户端,处理与所述第一客户端对应的数据任务,在所述数据任务处理完成后,如果所述命名管道句柄的当前连接状态为ERROR_IO_PENDING,将所述重叠IO存放至与所述异步任务对应的存储空间中;
第三处理单元,用于通过所述服务线程循环查看所述第一存储空间、所述第二存储空间以及所述第三存储空间中的重叠IO,如果查看到当前重叠IO处理完成,继续处理下一个存储空间的重叠IO。
所述电子设备可包括,但不仅限于,处理器、存储器。本领域技术人员可以理解,所述示意图3仅仅是计算机装置的示例,并不构成对电子设备的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件,例如所述电子设备还可以包括输入输出设备、网络接入设备、总线等。
所称处理器301可以是中央处理单元(Central Processing Unit,CPU),还可以是其他通用处理器、数字信号处理器(Digital Signal Processor,DSP)、专用集成电路(Application Specific Integrated Circuit,ASIC)、现成可编程门阵列(Field-Programmable Gate Array,FPGA)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等,所述处理器是所述计算机装置的控制中心,利用各种接口和线路连接整个计算机装置的各个部分。
所述存储器302可用于存储所述计算机程序和/或模块,所述处理器通过运行或执行存储在所述存储器内的计算机程序和/或模块,以及调用存储在存储器内的数据,实现所述计算机装置的各种功能。所述存储器可主要包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序(比如声音播放功能、图像播放功能等)等;存储数据区可存储根据手机的使用所创建的数据(比如音频数据、视频数据等)等。此外,存储器可以包括高速随机存取存储器,还可以包括非易失性存储器,例如硬盘、内存、插接式硬盘,智能存储卡(Smart Media Card,SMC),安全数字(Secure Digital,SD)卡,闪存卡(Flash Card)、至少一个磁盘存储器件、闪存器件、或其他易失性固态存储器件。
进一步,该电子设备所包括的处理器301还具有以下功能:
调用onAccepted函数,在所述onAccepted函数中创建目标会话对象,调用所述目标会话对象的asyncReadSome函数,读取所述第一客户端发送的数据。
进一步,该电子设备所包括的处理器301还具有以下功能:
通过所述accept函数调用设置了预设安全访问属性的CreateNamedPipe函数创建异步的命名管道句柄,其中,所述命名管道句柄通过所述预设安全访问属性指定访问等级,所述命名管道句柄指定的访问等级使得所述服务器以管理员权限或非管理员权限创建所述命名管道句柄情况下,所述客户端均能访问所述命名管道句柄。
进一步,该电子设备所包括的处理器301还具有以下功能:
在所述调用accept函数之前,初始化安全描述符;
将所述安全描述符的安全访问级别设置为最低等级;
创建安全属性描述结构,将安全访问级别设置为最低等级的所述安全描述符传入所述安全属性描述结构的属性字段中;
将创建的所述安全属性描述结构传入所述CreateNamedPipe函数的最后一个参数,即安全属性参数中,以使得所述CreateNamedPipe函数的安全属性设置为所述预设安全访问属性。
进一步,该电子设备所包括的处理器301还具有以下功能:
在所述如果查看到当前重叠IO处理完成之后,将所述当前重叠IO从对应的存储空间中删除。
进一步,该电子设备所包括的处理器301还具有以下功能:
如果所述当前重叠IO为所述第一存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定有客户端连接到所述服务器;
调用onAccepted函数,在所述onAccepted函数中创建第一会话对象,调用所述第一会话对象的asyncReadSome函数,读取所述客户端发送的数据;
继续处理下一个存储空间的重叠IO。
进一步,该电子设备所包括的处理器301还具有以下功能:
如果所述当前重叠IO为所述第二存储空间中的重叠IO,调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功接收到来自客户端发送的数据;
通过所述当前重叠IO中Pointer字段获取所述当前重叠IO对应的第二会话对象;
调用所述第二会话对象的onReadComplete函数处理接收到的数据;
调用所述第二会话对象的asyncReadSome函数,把下一个读取的重叠IO放入到所述第二存储空间;
继续处理下一个存储空间的重叠IO。
进一步,该电子设备所包括的处理器301还具有以下功能:
如果所述当前重叠IO为所述第三存储空间中的重叠IO,定位与所述当前重叠IO对应的第三会话对象;
调用所述第三会话对象的asyncWriteSome函数异步的发送数据至客户端;
调用HasOverlappedIoCompleted函数查看所述当前重叠IO,如果所述HasOverlappedIoCompleted函数返回值为“true”,确定成功的将数据发送至客户端;
继续处理下一个存储空间的重叠IO。
本发明第四实施例提供了一种计算机可读存储介质,其上存储有计算机程序,本发明第二实施例中的所述电子设备集成的功能单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明实现上述第一实施例的进程间通信方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、U盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器(ROM,Read-Only Memory)、随机存取存储器(RAM,Random Access Memory)、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读介质不包括电载波信号和电信信号。
尽管已描述了本发明的优选实施例,但本领域内的技术人员一旦得知了基本创造性概念,则可对这些实施例作出另外的变更和修改。所以,所附权利要求意欲解释为包括优选实施例以及落入本发明范围的所有变更和修改。
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。