您的位置:首页 > 理论基础 > 计算机网络

用邮槽实现网络上两台机器之间的进程通信

2008-05-29 20:17 260 查看
邮槽是Windows用来实现两个进程之间通信的一种手段,而且不仅可在本机的两个进程间实现,还可以在网络上两台主机的两个进程间实现。自从Windows 95启用新的内存保护机制以来,进程间通信再也不像以前那么容易了,进程空间是各自独立分开的,而不像以前那样是统一地址。为了在这种情况下实现进程间通信,Windows增加了一些新的机制,邮槽便是其中的一种。
邮槽的创建是通过函数CreateMailslot,其声明格式如下:
Declare Function CreateMailslot Lib "kernel32" Alias "CreateMailslotA" (ByVal lpName As String, ByVal nMaxMessageSize As Long, ByVal lReadTimeout As Long, ByVal lpSecurityAttributes&) As Long
第一个参数(lpName)是指定一个邮槽的名字,其格式如下:
//./mailslot/name 在本机上创建一个新的以name命名的邮槽或获取一个本机上已创 建的且名字是name的邮槽;(即若本机上没有以name命名的邮槽则创建一个新的,若有则获取其句柄。)
//computername/mailslot/name 指定主机名远程邮槽;
//domainname/mailslot/name 指定域名的远程邮槽;
//*/mailslot/name 在自己主域上的邮槽;
第二个参数(nMaxMessageSize)指定一个消息的最大字节长度。设为0表示可以为任意大小。若邮槽是域上的则其消息的最大长度不能超过400,否则WriteFile写时GetLastError会返回ERROR_BAD_NETPATH。
第三个参数(lReadTimeOut)用于设定“读”超时的时限。0为立即操作返回。
第四个参数(lpSecurityAttributes)为一个安全属性,主要用于继承,这里用不着,就设为0。
邮槽的信息可以通过函数GetMailslotInfo(ByVal hMailslot As Long, lpMaxMessageSize As Long, lpNextSize As Long, lpMessageCount As Long, lpReadTimeout As Long) 来获得。第一个参数为函数CreateMailslot或OpenMailslot返回的有效的邮槽句柄;第二个参数为CreateMailslot的第二个参数;第三个参数为当前消息的大小;第四个参数为邮槽中消息的个数;第五个同CreateMailslot的第三个参数。
当邮槽中消息个数不为0时,可以循环读取,直到没有消息为止。
 
程序1(创建Mailslot):
Private Declare Function CreateMailslot Lib "kernel32" Alias "CreateMailslotA" (ByVal lpName As String, ByVal nMaxMessageSize As Long, ByVal lReadTimeout As Long, ByVal lpSecurityAttributes&) As Long
Private Declare Function GetMailslotInfo Lib "kernel32" (ByVal hMailslot As Long, lpMaxMessageSize As Long, lpNextSize As Long, lpMessageCount As Long, lpReadTimeout As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped&) As Long
 
Private Const MAILSLOT_WAIT_FOREVER = (-1)
Dim MailslotSize&, MsgCount&, ReadTimeout&, NextSize&, hMailslot&
 
Private Sub CreateMslot_Click()
hMailslot = CreateMailslot("//./MAILSLOT/xyMail", 0, MAILSLOT_WAIT_FOREVER, 0)
MsgBox hMailslot
End Sub
 
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
CloseHandle hMailslot
End Sub
 
Private Sub ReadFle_Click ()
Dim TempStr$, BytesReaded&
Do
GetMailslotInfo hMailslot, MailslotSize, NextSize, MsgCount, ReadTimeout
Debug.Print MsgCount
If MsgCount = 0 Then Exit Do
TempStr = Space (NextSize)
ReadFile hMailslot, ByVal TempStr, NextSize, BytesReaded, 0
MsgBox TempStr
Loop While MsgCount > 1
End Sub
 
程序2(获取刚才创建的Mialslot):
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes&, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped&) As Long
 
Private Const FILE_SHARE_READ = &H1
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const OPEN_EXISTING = 3
Private Const OPEN_ALWAYS = 4
Dim MailslotSize&, MsgCount&, ReadTimeout&, NextSize&, hMailslot&
 
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
CloseHandle hMailSlot
End Sub
 
Private Sub OpenMailslot_Click ()
hMailSlot = CreateFile("//Campaq/MAILSLOT/xyMail", GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)
MsgBox hMailSlot
End Sub
 
Private Sub WriteSlot_Click ()
Dim TempStr$, BytesWritted&
TempStr = InputBox ("Please Input a String:") '"1234567"
WriteFile hMailSlot, ByVal TempStr$, Len (TempStr), BytesWritted, 0
MsgBox BytesWritted
End Sub
程序1是在本机上创建一个Mailslot,本机名是Campaq;程序2是在和本机(Campaq)连网的的另一台机器上运行的,也可在本机上运行。Windows中实现进程间通信的方法很多,本机上的可以还通过广播消息、WM_COPYDATA、匿名管道、内存映射、Mutex、Semaphore、零界区等,网络间的还可以通过命名管道、Winsock等等很多种方法,有兴趣的读者可以查阅的相关Windows 32位编程资料。
邮槽是使用数据报来发送数据的,发送前并没有建立一个可靠的连接,数据在发送中可能会丢失,所以服务器不一定能收到客户机的发送来的数据,要想克服这一点,最好使用命名管道(NamePipe)。使用邮槽时需要注意的是邮槽是单向通道,客户端只能写,服务器端只能读;还有一点特别的便是一个已经创建的邮槽可以同时被多个机器打开,这样可以用一个邮槽连接多个机器。
使用邮槽的缺点是:当把邮槽的超时时限设置为一个大于0的值,那么一旦超过这个时间,ReadFile便返回False,经多次ReadFile函数调用之后,系统便会变得极不稳定,以后超时的ReadFile便会都返回True。因此,系统不能再执行其它MS-DOS程序。为避免这一点,应该将超时时限设置为0(MAILSLOT_WAIT_FOREVER );如果服务器用CreateMailslot打开一个邮槽,指定一个超时,然后用ReadFile接收数据,而这时没有数据可读,ReadFile便会失败,此时用GetLastError函数便会返回错误代码ERROR_ACCESS_DENIED;在Win95上创建的邮槽不能写大于4093个字节的数据;MSDN的CreateFile函数说明中说明了一种情况,就是如果服务器没有创建邮槽,用CreateFile在客户端打开一个不存在的远程邮槽,函数却能返回一个有效的句柄。
该程序在VB5.0、Win98下调试通过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: