a11s.Net

年纪大了,脑子不好用了,需要记录写东西了

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
 

关键字: DirectPlay DPlay VB DirectX .net 网络 游戏 作者:董含君
转贴请注明来自 http://a11s.cnblogs.com


为了看
DPlay的最后一个例子---ClientServer 我做好了充分的思想准备(大不了重新学)以及睡眠准备(13小时以上),而且特意安排了周末的事件(比较长).打开VS.NET(两个工程C/S)…

 

结果有点大失所望.P2P几乎没有区别!!!!唯独的区别就是把Peer换成了Server以及Client

方法都类似,强烈怀疑是对Peer进行了封装!

 

本来还想跟DSound一样最后进行一个封装的,现在看来几乎没有必要了,已经简单的可以了…如果可能的话,下次对player以及lobby还有其他细节方面整理一下.

本着善始善终的态度,Server-Client模式的步骤进行总结.

1 new Directplay.server,同时准备好事件触发

2 设置appdesc.sessionname guid sessionflags=clientserver (这里就是变了一个flag而已)

3 设置address

4 server.host(appdesc,address)

 

客户端

5 new directplay.client

6 appdesc,address

7 client.findhost(…peer是一样的)

8 找到之后client.connect (参数跟peer也是一样的)

 

9 可以收发消息了(Peer相同)

这里有一点改变

只有Server可以Sendto某一个player或者allplayer,Client只能send.而且只有服务器才能接收到

估计这就是C/SP2P的最大区别了.而且没有了HOST迁移.整体操作也比P2P简单不少(个人认为) 效率方面我无法提供相关数据,一般说来应该是有过优化的,要相信微软的工程师不是白痴.所以还是不要自己封装Peer

代码帖出来大家比较一下吧.整体还是比较简单的. (很明显,一看就是照着C#的code改的,这个是MS的例子)

Server:

'----------------------------------------------------------------------------

' File: Server.cs

'

' Desc: This tutorial modifes the Send tutorial to be a client/server

'       topology instead of peer to peer. This file contains the server

'       code.

'

' Copyright (c) Microsoft Corp. All rights reserved.

'-----------------------------------------------------------------------------

Imports System

Imports System.IO

Imports System.Windows.Forms

Imports System.Text

Imports System.Collections

Imports Microsoft.DirectX

Imports Microsoft.DirectX.DirectPlay

 

Namespace Tut09_Server

    ' Possible connection states

    Public Enum ConnectionType

        Disconnected

        Hosting

    End Enum 'ConnectionType

 

    '/ <summary>

    '/ Application class.

    '/ </summary>

    Public Class ServerApp

        Implements IDisposable

        ' Application identifier

        ' This guid allows DirectPlay to find other instances of the same game on

        ' the network, so it must be unique for every game, and the same for

        ' every instance of that game. You can use the guidgen.exe program to

        ' generate a new guid.

        Private Shared m_AppGuid As New Guid("1AD4CA3B-AC68-4d9b-9522-BE59CD485276")

        Public Shared DefaultPort As Integer = 2609 ' Default port number

 

        ' DirectPlay

        Private m_Server As Microsoft.DirectX.DirectPlay.Server = Nothing ' DirectPlay Server object

        Private m_LocalAddress As New Address() ' Local address

        ' Application

        Private m_Form As ApplicationForm = Nothing ' Main application WinForm

        Private m_SessionName As String = "New Host" ' Hosted session name

        Private m_Connection As ConnectionType = ConnectionType.Disconnected ' Current connection state    

 

        Public ReadOnly Property Connection() As ConnectionType

            Get

                Return m_Connection

            End Get

        End Property

        '/ <summary>

        '/ Constructor

        '/ </summary>

        Public Sub New()

            ' Initialize the application's UI

            m_Form = New ApplicationForm(Me)

 

            ' Update the UI

            UpdateUI()

 

            ' Initialize DirectPlay and event handlers

            InitDirectPlay()

 

            ' Set the service provider for our local address to TCP/IP

            m_LocalAddress.ServiceProvider = Address.ServiceProviderTcpIp

 

            ' Verify the computer supports our chosen service provider

            If Not IsServiceProviderValid(m_LocalAddress.ServiceProvider) Then

                MessageBox.Show(m_Form, "You must have TCP/IP installed on your " + "computer to run this tutorial.", "DirectPlay Tutorial", MessageBoxButtons.OK, MessageBoxIcon.Error)

 

                m_Form.Dispose()

            End If

        End Sub 'New

 

        '/ <summary>

        '/ Initializes the DirectPlay Server object

        '/ </summary>

        Private Sub InitDirectPlay()

            ' Release any exising resources

            If Not (m_Server Is Nothing) Then

                m_Server.Dispose()

            End If

            ' Create a new DirectPlay Server object

            m_Server = New Microsoft.DirectX.DirectPlay.Server()

 

            ' Add handlers for DirectPlay events

            AddHandler m_Server.Receive, AddressOf ReceiveHandler

 

            m_Connection = ConnectionType.Disconnected

        End Sub 'InitDirectPlay

 

        '/ <summary>

        '/ Handler for incoming DirectPlay Receive events

        '/ </summary>

        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>

        '/ 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.ClientServer Or SessionFlags.NoDpnServer

 

            Try

                ' Host a new session

                m_Server.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>

        '/ Sends the current outgoing chat string to all connected clients

        '/ </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. You must tell

            ' DirectPlay which client 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_Server.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 server and opening

            ' a new one.

            InitDirectPlay()

            UpdateUI()

        End Sub 'Disconnect

 

        '/ <summary>

        '/ Verify the given service provider if found in the enumerated list

        '/ of installed providers on this computer.

        '/ </summary>

        '/ <param name="provider">Guid of the provider to search for</param>

        '/ <returns>true if the given provider is found</returns>

        Private Function IsServiceProviderValid(ByVal provider As Guid) As Boolean

            ' Ask DirectPlay for the service provider list

            Dim SPInfoArray As ServiceProviderInformation() = m_Server.GetServiceProviders(True)

 

            ' For each service provider in the returned list...

            Dim info As ServiceProviderInformation

            For Each info In SPInfoArray

                ' Compare the current provider against the passed provider

                If info.Guid.Equals(provider) Then

                    Return True

                End If

            Next info

            ' Not found

            Return False

        End Function 'IsServiceProviderValid

 

 

        '/ <summary>

        '/ Update visual elements according to current state

        '/ </summary>

        Public Sub UpdateUI()

            ' Flush the incoming/outgoing messages box

            m_Form.SendTextBox.Text = ""

            m_Form.ReceivedMessagesListBox.Items.Clear()

 

            ' Set UI elements based on current connection state

            Select Case m_Connection

                Case ConnectionType.Hosting

                    m_Form.SessionStatusLabel.Text = "Hosting session """ + m_SessionName + """"

                    m_Form.HostButton.Text = "&Disconnect"

 

                    m_Form.ReceivedMessagesListBox.Enabled = True

                    m_Form.SendTextBox.Enabled = True

                    m_Form.SendButton.Enabled = True

 

                Case ConnectionType.Disconnected

                    m_Form.SessionStatusLabel.Text = "Not connected to a session"

                    m_Form.HostButton.Text = "&Host..."

                    m_Form.ReceivedMessagesListBox.Items.Add("You must first connect to a session.")

 

                    m_Form.ReceivedMessagesListBox.Enabled = False

                    m_Form.SendTextBox.Enabled = False

                    m_Form.SendButton.Enabled = False

 

            End Select

        End Sub 'UpdateUI

 

 

        '/ <summary>

        '/ Handles program cleanup

        '/ </summary>

        Protected Overridable Overloads Sub Dispose() Implements IDisposable.Dispose

            If Not (m_Server Is Nothing) And Not m_Server.Disposed Then

                m_Server.Dispose()

            End If

        End Sub 'Dispose

 

        '/ <summary>

        '/ The main entry point for the application.

        '/ </summary>

        Public Shared Sub Main()

            ' Create the main application object

            Dim App As New ServerApp()

 

            ' Start the form's message loop

            If Not App.m_Form.IsDisposed Then

                Application.Run(App.m_Form)

            End If

            ' Release resources

            App.Dispose()

        End Sub 'Main

    End Class 'ServerApp

End Namespace 'Tut09_Server

 

Client:

'----------------------------------------------------------------------------

' File: Client.cs

'

' Desc: This tutorial modifes the Send tutorial to be a client/server

'       topology instead of peer to peer. This file contains the client

'       code.

'

' Copyright (c) Microsoft Corp. All rights reserved.

'-----------------------------------------------------------------------------

Imports System

Imports System.IO

Imports System.Windows.Forms

Imports System.Text

Imports System.Collections

Imports Microsoft.DirectX

Imports Microsoft.DirectX.DirectPlay

 

 

Namespace Tut09_Client

    ' Possible connection states

    Public Enum ConnectionType

        Disconnected

        Connected

    End Enum 'ConnectionType

 

    '/ <summary>

    '/ Application class.

    '/ </summary>

    Public Class ClientApp

        Implements IDisposable 'ToDo: Add Implements Clauses for implementation methods of these interface(s)

        ' Application identifier

        ' This guid allows DirectPlay to find other instances of the same game on

        ' the network, so it must be unique for every game, and the same for

        ' every instance of that game. You can use the guidgen.exe program to

        ' generate a new guid.

        Private Shared m_AppGuid As New Guid("1AD4CA3B-AC68-4d9b-9522-BE59CD485276")

        Public Shared DefaultPort As Integer = 2609 ' Default port number

 

        ' DirectPlay

        Private m_Client As Microsoft.DirectX.DirectPlay.Client = Nothing ' DirectPlay Client object

        Private m_LocalAddress As New Address() ' Local address

        ' Application

        Private m_Form As ApplicationForm = Nothing ' Main application WinForm

        Private m_SessionName As String = "New Host" ' Hosted session name

        Private m_FoundSessions As New ArrayList() ' Enumerated sessions

        Private m_Connection As ConnectionType = ConnectionType.Disconnected ' Current connection state    

 

 

        Public ReadOnly Property Connection() As ConnectionType

            Get

                Return m_Connection

            End Get

        End Property

 

        Public ReadOnly Property FoundSessions() As ArrayList

            Get

                Return m_FoundSessions

            End Get

        End Property

 

        '/ <summary>

        '/ Constructor

        '/ </summary>

        Public Sub New()

            ' Initialize the application's UI

            m_Form = New ApplicationForm(Me)

 

            ' Update the UI

            UpdateUI()

 

            ' Initialize DirectPlay and event handlers

            InitDirectPlay()

 

            ' Set the service provider for our local address to TCP/IP

            m_LocalAddress.ServiceProvider = Address.ServiceProviderTcpIp

 

            ' Verify the computer supports our chosen service provider

            If Not IsServiceProviderValid(m_LocalAddress.ServiceProvider) Then

                MessageBox.Show(m_Form, "You must have TCP/IP installed on your " + "computer to run this tutorial.", "DirectPlay Tutorial", MessageBoxButtons.OK, MessageBoxIcon.Error)

 

                m_Form.Dispose()

            End If

        End Sub 'New

 

        '/ <summary>

        '/ Initializes the DirectPlay Client object

        '/ </summary>

        Private Sub InitDirectPlay()

            ' Release any exising resources

            If Not (m_Client Is Nothing) Then

                m_Client.Dispose()

            End If

            ' Create a new DirectPlay Client object

            m_Client = New Microsoft.DirectX.DirectPlay.Client()

 

            ' Add handlers for DirectPlay events

            AddHandler m_Client.FindHostResponse, AddressOf FindHostResponseHandler

            AddHandler m_Client.Receive, AddressOf ReceiveHandler

            AddHandler m_Client.SessionTerminated, AddressOf SessionTerminatedHandler

 

            m_Connection = ConnectionType.Disconnected

        End Sub 'InitDirectPlay

 

        '/ <summary>

        '/ Event handler for the DirectPlay FindHostResponse message

        '/ </summary>

        Public Sub FindHostResponseHandler(ByVal sender As Object, ByVal args As FindHostResponseEventArgs)

            Dim Node As New HostInfo()

            Node.GuidInstance = args.Message.ApplicationDescription.GuidInstance

            Node.HostAddress = CType(args.Message.AddressSender.Clone(), Address)

            Node.SessionName = args.Message.ApplicationDescription.SessionName

 

            ' If he haven't already seen this host, add the detected session

            ' to the stored list

            If Not FoundSessions.Contains(Node) Then

                FoundSessions.Add(Node)

            End If

        End Sub 'FindHostResponseHandler

 

        '/ <summary>

        '/ Handler for incoming DirectPlay Receive events

        '/ </summary>

        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 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>

        '/ 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_Client.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_Client.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 players

        '/ </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

            ' client/server topology, all data is sent between server and

            ' clients, there is no need to specify a destination player.

            m_Client.Send(packet, 0, SendFlags.Sync Or SendFlags.NoLoopback)  ' 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 client and opening

            ' a new one.

            InitDirectPlay()

            UpdateUI()

        End Sub 'Disconnect

 

 

        '/ <summary>

        '/ Verify the given service provider if found in the enumerated list

        '/ of installed providers on this computer.

        '/ </summary>

        '/ <param name="provider">Guid of the provider to search for</param>

        '/ <returns>true if the given provider is found</returns>

        Private Function IsServiceProviderValid(ByVal provider As Guid) As Boolean

            ' Ask DirectPlay for the service provider list

            Dim SPInfoArray As ServiceProviderInformation() = m_Client.GetServiceProviders(True)

 

            ' For each service provider in the returned list...

            Dim info As ServiceProviderInformation

            For Each info In SPInfoArray

                ' Compare the current provider against the passed provider

                If info.Guid.Equals(provider) Then

                    Return True

                End If

            Next info

            ' Not found

            Return False

        End Function 'IsServiceProviderValid

 

 

        '/ <summary>

        '/ Update visual elements according to current state

        '/ </summary>

        Public Sub UpdateUI()

            ' Flush the incoming/outgoing messages box

            m_Form.SendTextBox.Text = ""

            m_Form.ReceivedMessagesListBox.Items.Clear()

 

            ' Set UI elements based on current connection state

            Select Case m_Connection

                Case ConnectionType.Connected

                    m_Form.SessionStatusLabel.Text = "Connected to session """ + m_SessionName + """"

                    m_Form.ConnectButton.Text = "&Disconnect"

 

                    m_Form.ReceivedMessagesListBox.Enabled = True

                    m_Form.SendTextBox.Enabled = True

                    m_Form.SendButton.Enabled = True

 

                Case ConnectionType.Disconnected

                    m_Form.SessionStatusLabel.Text = "Not connected to a session"

                    m_Form.ConnectButton.Text = "&Connect..."

 

                    m_Form.ReceivedMessagesListBox.Items.Add("You must first connect to a session.")

 

                    m_Form.ReceivedMessagesListBox.Enabled = False

                    m_Form.SendTextBox.Enabled = False

                    m_Form.SendButton.Enabled = False

 

            End Select

        End Sub 'UpdateUI

 

 

        '/ <summary>

        '/ Handles program cleanup

        '/ </summary>

        Protected Overridable Overloads Sub Dispose() Implements IDisposable.Dispose

            If Not (m_Client Is Nothing) And Not m_Client.Disposed Then

                m_Client.Dispose()

            End If

        End Sub 'Dispose

 

        '/ <summary>

        '/ The main entry point for the application.

        '/ </summary>

        Public Shared Sub Main()

            ' Create the main application object

            Dim App As New ClientApp()

 

            ' Start the form's message loop

            If Not App.m_Form.IsDisposed Then

                Application.Run(App.m_Form)

            End If

            ' Release resources

            App.Dispose()

        End Sub 'Main

    End Class 'ClientApp

End Namespace 'Tut09_Client

posted on 2005-11-07 10:20  a11s.net  阅读(1982)  评论(2编辑  收藏  举报