关键字: DirectPlay DPlay VB DirectX .net 网络 游戏 作者:董含君
转贴请注明来自 http://a11s.cnblogs.com
这个QQ群的问题很是难办…. 人数已经超了….包括分群也超了…..对不住大家了<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
或者跟dudu老大联系一下开一个托管的DirectX 俱乐部或者团队之类的,指望QQ是靠不住了….
身体还是比较虚弱.继续加营养….下次就是看大厅了lobby还有Server以及Client还有Voice,周末回家养病,不一定能完成多少.
今天看了关于HostMigration的演示.就是HOST迁移.这个….还是举例子吧(赵本山:”转移了!”)
星际争霸 魔兽争霸 帝国时代 红色警戒…. 之类的联机游戏
1 网络游戏的时候我们都是需要先选择连线方式(帝国时代1最经典,简直就是专门为DPlay做的DEMO!!不信你连连看,就是当年DX7的那些窗体) 这个对应我们address的ServiceProvider 比如tcpip ipx modem..
2 然后需要有一个人做HOST 创建游戏. Peer.host()
3 大家加入 Peer.connect()
4 游戏开始 Peer.sendto() 发送数据
5 玩家2挂了,退出了,去参与其他游戏了,但是剩下的7个人(假设原来一共8个)还在继续少一个人罢了
6 终于玩家1(创建游戏的人)挂了.剩下六个人,按理说不就是少了一个人嘛.但是游戏是他创建的..这样就…
实际上,星际或者魔兽的时候还是可以继续的.这一点不同于CS模式(客户端-服务器)如果哪天WOW服务器当机了估计有一大票人都得休息…
这个解决的办法就是HostMigration 玩家1挂了,甚至断线了.停电了.session并没有中止,剩余的玩家将会有人接替玩家1的任务. 最重要的是,这一切都非常简单!
(这一点不知道能不能用在服务器的故障转移上面.呵呵,我学DX的目的并不完全都是准备用来做游戏…毕竟还是服务器跟桌面程序才是老本行..如果有多台服务器负载均衡,使用IPX,然后有一台网管对外.这样数据处理挂掉一台自然可以平滑迁移,而且由于不见得要求IP地址,所以一般的黑客工具或者入侵方式可能会遇上点麻烦,当然仅仅是想法而已…没有认真考虑,可能有不现实的地方,以后再说了)
7 终于最后一个玩家退出游戏,整个session结束.
以上就是游戏(网络)的进行过程,同时给出了类,方法的对照
实现过程很简单,如果你一路看我的blog的话,这样的基础已经可以了.创建appdesc的时候有个flag添加上这个 AppDesc.Flags = AppDesc.Flags Or SessionFlags.MigrateHost 然后准备响应一个事件
AddHandler m_Peer.HostMigrated, AddressOf HostMigratedHandler 用自定义的方法HostMigratedHandler()来响应 peer.hostmigrated.无非就是判断一下自己是不是host(其实,不理睬他也是可以的,p2p是对等的嘛,谁当老大都一样,反正真正的老大已经没了,通过事件返回的HostMigratedEventArgs来找到目的HOST的信息) OK,就需要注意这两个地方.
代码就不全贴出来了,这次直接COPY 微软的.体会一下就可以了.或者等我找到空间之后给出源码下载地址.
主要就是看看HostMigratedHandler,其他的都像上一篇一样不便.自己改一下就可以了,如果你真的理解了的话以下仅供参考,不要直接复制.
Public Sub ReceiveHandler(ByVal sender As Object, ByVal args As ReceiveEventArgs)
If m_Form.ReceivedMessagesListBox.Enabled Then
' Read the incoming chat message. Since network data is always
' broken down into raw bytes for transfer, the sent object must
' be rebuilt. The NetworkPacket class contains methods to
' easily send and receive unicode strings, but this sample
' manually decodes the string for compatibility with the C++
' tutorials. The data is first read into a byte array, then Unicode
' decoded, and finally added to our list of received messages.
Dim packet As NetworkPacket = args.Message.ReceiveData
Dim data As Byte() = CType(packet.Read(GetType(Byte), packet.Length), Byte())
m_Form.ReceivedMessagesListBox.Items.Add(Encoding.Unicode.GetString(data))
End If
End Sub 'ReceiveHandler
'/ <summary>
'/ Handler for incoming DirectPlay HostMigrated events
'/ </summary>
Public Sub HostMigratedHandler(ByVal sender As Object, ByVal args As HostMigratedEventArgs)
Dim info As PlayerInformation = m_Peer.GetPeerInformation(args.Message.NewHostID)
' See if we are the new host
If info.Local Then
m_Connection = ConnectionType.Hosting
UpdateUI()
End If
End Sub 'HostMigratedHandler
'/ <summary>
'/ Handler for incoming DirectPlay SessionTerminated events
'/ </summary>
Public Sub SessionTerminatedHandler(ByVal sender As Object, ByVal args As SessionTerminatedEventArgs)
MessageBox.Show(m_Form, "Connect lost or host terminated session", "DirectPlay Tutorial")
m_Connection = ConnectionType.Disconnected
UpdateUI()
End Sub 'SessionTerminatedHandler
'/ <summary>
'/ Host a new DirectPlay session.
'/ </summary>
Public Sub HostSession()
' Get desired hosting options
Dim dialog As New HostDialog()
dialog.LocalPort = DefaultPort
If DialogResult.Cancel = dialog.ShowDialog() Then
Return
End If
' Update the UI
m_Form.SessionStatusLabel.Text = "Connecting..."
m_Form.Update()
' Store host dialog choices
m_SessionName = dialog.SessionName
' Add the port number
If dialog.LocalPort > 0 Then
m_LocalAddress.AddComponent("port", dialog.LocalPort)
End If
' Create an application description
Dim AppDesc As New ApplicationDescription()
AppDesc.GuidApplication = m_AppGuid
AppDesc.SessionName = m_SessionName
AppDesc.Flags = SessionFlags.NoDpnServer
If dialog.IsHostMigrationEnabled Then
AppDesc.Flags = AppDesc.Flags Or SessionFlags.MigrateHost
End If
Try
' Host a new session
m_Peer.Host(AppDesc, m_LocalAddress) ' Application description
' Local device address
m_Connection = ConnectionType.Hosting
Catch ex As Exception
m_Form.ShowException(ex, "Host", True)
m_Form.Dispose()
Return
End Try
End Sub 'HostSession
'/ <summary>
'/ Find all sessions at the given host address
'/ </summary>
'/ <param name="hostname">IP address or hostname to search</param>
'/ <param name="port">Remote port to search</param>
Public Sub EnumerateSessions(ByVal hostname As String, ByVal port As Integer)
' Set the desired search options
Dim HostAddress As New Address()
HostAddress.ServiceProvider = Address.ServiceProviderTcpIp
If hostname.Length > 0 Then
HostAddress.AddComponent("hostname", hostname)
End If
If port > 0 Then
HostAddress.AddComponent("port", port)
End If
Dim AppDesc As New ApplicationDescription()
AppDesc.GuidApplication = m_AppGuid
' Find all sessions hosted at the given address. When a session is
' found, DirectPlay calls our FindHostResponse delegate. Since we're
' passing in the "Sync" flag, Connect will block until the search
' timeout has expired.
Try
m_Peer.FindHosts(AppDesc, HostAddress, m_LocalAddress, Nothing, 0, 0, 0, FindHostsFlags.Sync) ' Application description
' Host address
' Local device address
' Enumeration data
' Enumeration count (using default)
' Retry interval (using default)
' Timeout (using default)
' Flags
Catch ex As Exception
m_Form.ShowException(ex, "FindHosts", True)
m_Form.Dispose()
Return
End Try
End Sub 'EnumerateSessions
'/ <summary>
'/ Connect to the currently selected session
'/ </summary>
Public Sub ConnectToSession()
' Display connection dialog
Dim dialog As New ConnectDialog(Me)
dialog.RemotePort = DefaultPort
If DialogResult.Cancel = dialog.ShowDialog() Then
Return
End If
' Update the UI
m_Form.SessionStatusLabel.Text = "Connecting..."
m_Form.Update()
' Store connection dialog choices
Dim SelectedHost As HostInfo = dialog.SelectedHost
If SelectedHost Is Nothing Then
Return
End If
' Create an application description object to hold the desired
' host's instance guid.
Dim appDesc As New ApplicationDescription()
appDesc.GuidInstance = SelectedHost.GuidInstance
' Attempt to connect to the selected DirectPlay session. Once we
' are connected to the session, we will receive DirectPlay messages
' about session events (like players joining/exiting and received game
' data). Since we're passing in the "Sync" flag, the Connect call will
' block until the session is connected or the timeout expires.
Try
m_Peer.Connect(appDesc, SelectedHost.HostAddress, m_LocalAddress, Nothing, ConnectFlags.Sync) ' Application description
' Host address
' Local device address
' User connection data (none)
' Flags
m_SessionName = SelectedHost.SessionName
m_Connection = ConnectionType.Connected
Catch ex As Exception
m_Form.ShowException(ex, "Connect", False)
Return
End Try
End Sub 'ConnectToSession
'/ <summary>
'/ Sends the current outgoing chat string to all connected peers
'/ </summary>
Public Sub SendData()
' Create a network packet object to which we can write our chat message.
' For compatibility with the current C++ tutorials, the unicode text
' will be encoded as a null-terminated string for network transfer, as
' opposed to the .NET convention of string length followed by characters;
' however, there are no limits on how the data can be formatted since
' all data is received as a raw byte array.
Dim packet As New NetworkPacket()
packet.Write(Encoding.Unicode.GetBytes(m_Form.SendTextBox.Text))
' Now that all the outgoing data has been encoded to a network
' packet, the DirectPlay send method can be called. Since in a
' peer-to-peer topology there is no server, you must inform
' DirectPlay which peer you wish to receive the data. For this
' sample, we'll deliver the message to all connected players
' (except the local player, which we exclude with the NoLoopback
' flag )
m_Peer.SendTo(CInt(PlayerID.AllPlayers), packet, 0, SendFlags.Sync Or SendFlags.NoLoopback) ' Send to session
' Outgoing data
' Timeout (default)
' Flags
m_Form.SendTextBox.Text = ""
End Sub 'SendData
'/ <summary>
'/ Terminate or disconnect from the session.
'/ </summary>
Public Sub Disconnect()
' Disconnect by closing the current peer and opening
' a new one.
InitDirectPlay()
UpdateUI()
End Sub 'Disconnect