阅读新闻阅读所有新闻

FLASH网游通过XMLSocket与VB后台通信教程 (3)

我们要先想好客户端和服务器端有什么资料要通讯的,定好通讯的格式。我是这样设计的:通讯的资料我就不加密了,格式是01u=aa&xxxx 。前两位是代表了是做什么。u=aa是用户aa 做的操作。xxxx是操作的内容。
00 由服务器提供给客户端(简称S2C,下同),返回当前在线的所有用户。如:00u=a&x=0&y=0&u=b&x=54&y=78
01 C2S 用户登陆 如:01u=a
   S2C 告诉其他在线用户有新用户登陆 如:01u=a

02 C2S 用户移动 如:02u=a&x=100&y=50
   S2C 告诉其他在线用户某个用户在移动 如:02u=a&x=100&y=50

03 C2S 用户下线 如:03u=a
   S2C 告诉其他在线用户某个用户下线了 如:03u=a

04 C2S 用户发言 如:04u=a&内容
   S2C 告诉其他在线用户某个用户的发言 如:04u=a&内容

这里要说一下用户下线,用户下线是由用户在客户端点击“下线”完成,也可以是点击关闭FLASH的窗口完成。如果是点“下线”,那就由FLASH发送03过来就可以了。如果是点击关闭窗口的话,那只能由服务器端判断。当收到客户端发送的数据长度为零时,就可以判断客户端下线了。opMsg函数如下:

 ’处理收到的数据
        Public Sub opMsg(ByVal so As StateObject)
            Dim username As String
            Dim sendmsg As String
            Dim keys As IDictionaryEnumerator
            ’如果发送消息长度为0,断开客户端
            If so.len < 1 Then
                keys = Me.allRoles.Values().GetEnumerator
                While keys.MoveNext
                    If keys.Current.Equals(so.workSocket) Then
                        username = CType(keys.Key, String)
                    End If
                End While
                so.workSocket.Close()
                sendmsg = "03u=" + username + Chr(0)
                keys.Reset()
                While keys.MoveNext
                    If Not keys.Current.Equals(so.workSocket) Then
                        Me.send(keys.Key, sendmsg)
                    End If
                End While
                Me.allRoles.Remove(username)
                Me.rolesPosition.Remove(username)
                Exit Sub
            End If
            Dim msg As String = System.Text.Encoding.UTF8.GetString(so.buffer, 0, so.len - 1)
            Dim msgtype As String = Left(msg, 2)
            Select Case msgtype
                Case "01"   ’登陆
                    Dim newMsg As String = "00"
                    Dim isIn As Boolean = False
                    username = Right(msg, msg.Length - 4)
                    keys = Me.allRoles.Keys().GetEnumerator
                    While keys.MoveNext
                        If keys.Key <> username Then
                            If newMsg <> "00" Then
                                newMsg += "&"
                            End If
                            newMsg += "u=" + keys.Key + Me.rolesPosition.Item(keys.Key)
                        Else
                            isIn = True
                        End If
                    End While
                    newMsg += Chr(0)    ’考虑到FLASH里接收SOCKET是用XMLSocket,每个 XML 消息都是一个完整的 XML 文档,以一个零 (0) 字节结束。所以以chr(0)结束。
                    If Not (isIn) Then
                        Me.allRoles.Add(username, so.workSocket)
                        Me.rolesPosition.Add(username, "&x=275&y=200") ’这里我给角色初位置是(275,200),正好是在FLASH场景的中心。
                        sendmsg = msgtype + "u=" + username + "&x=275&y=200" + Chr(0)
                        keys = Me.allRoles.Keys().GetEnumerator
                        While keys.MoveNext
                            If keys.Key = username Then
                                Me.send(keys.Current, newMsg)
                            Else
                                Me.send(keys.Current, sendmsg)
                            End If
                        End While
                    End If
                Case "02"   ’移动
                    username = Right(msg.Split("&")(0), msg.Split("&")(0).Length - 4)
                    If CType(Me.allRoles.Item(username), Socket).Equals(so.workSocket) Then
                        Dim xy As String = Right(msg, msg.Length - msg.Split("&")(0).Length)
                        Me.rolesPosition.Item(username) = xy
                        keys = Me.allRoles.Keys().GetEnumerator
                        While keys.MoveNext
                            If keys.Key <> username Then
                                Me.send(keys.Current, msg + Chr(0))
                            End If
                        End While
                    End If
                Case "03"   ’下线
                    username = Right(msg, msg.Length - 4)
                    If CType(Me.allRoles.Item(username), Socket).Equals(so.workSocket) Then
                        keys = Me.allRoles.Values().GetEnumerator
                        While keys.MoveNext
                            If Not keys.Current.Equals(so.workSocket) Then
                                Me.send(keys.Key, msg + Chr(0))
                            End If
                        End While
                        Me.allRoles.Remove(username)
                        Me.rolesPosition.Remove(username)
                        so.workSocket.Close()
                    End If
                Case "04"   ’聊天
                    username = Right(msg.Split("&")(0), msg.Split("&")(0).Length - 4)
                    If CType(Me.allRoles.Item(username), Socket).Equals(so.workSocket) Then
                        keys = Me.allRoles.Keys().GetEnumerator
                        While keys.MoveNext
                            Me.send(keys.Current, msg + Chr(0))
                        End While
                    End If
            End Select
        End Sub

要注意的是,发送的消息要以chr(0)结尾,这样FLASH才知道这是消息的尾,否则FLASH会以为还没完,还在等后边不存在的数据传过来。因为我懒,所以不打算在这个教程里做与数据库相关联的例子,如果要加的话,就在这个函数里的case里加就可以了。正确的做法应该是把每个case里的代码整理成一个个的功能块,方便以后调用。我懒-_-
还要写一个从服务器发消息给客户端的函数:   

 ’向一个用户主动发信息
        Public Sub send(ByVal user As Object, ByVal msg As String)
            Dim sends As Socket
            sends = CType(allRoles.Item(user), Socket)
            Dim buffer() As Byte
            buffer = System.Text.Encoding.UTF8.GetBytes(msg)
            sends.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, AddressOf Me.Send_Callback, sends)
        End Sub
        Public Sub Send_Callback(ByVal result As IAsyncResult)
            CType(result.AsyncState, Socket).EndSend(result)
        End Sub

做好这个DLL文件了,做一个面板吧。其时这是在开始写server.vb的时候就应该做的事,刚才给忘了。现在加上。在右边的“解决方案资源管理器”里右击“解决方案”,选择“添加(D)”“添加新项目(N)...”“visual Basic 项目”“Windows 应用程序”,命名为rpg。如图5[5.gif]。在“解决方案资源管理器”里右击“rpg”,选择“项目依赖项”,在弹出窗口里勾选server(刚才做的那个文件的名字)。在“rpg”下一行的“引用”上右击,选择“添加引用”,“浏览”找到用server.vb(server文件夹下有个bin文件夹,如果里边没有,你就先按F5调试生成它)生成的server.dll文件,选中之。在rpg上右击,再选择“设为启动项目(A)”。在rpg的面板上添加一个按钮,加上以下程序:

Private isStarted As Boolean
    Private rpgServer As server.ibaiy.Server
    Private Sub ServerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.isStarted = False
    End Sub
    Private Sub Button_start_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_start.Click
        If Not Me.isStarted Then
            Me.rpgServer = New server.ibaiy.Server
            Me.rpgServer.startServer(9999)
            Me.isStarted = True
        End If
    End Sub

现在可以调试一下VB的程序了。我做了一个简单的FLASH来测试的。这个FLASH就不说明怎么做了。我在下边有提供。[socket.swf],有兴趣的朋友可以自己看看。使用方法:服务器启动后,点击socket.swf上边的connect按钮,成功或者失败都会在中间显示出来。如果成功,就可以在下边输入要传输入的文字,格式就是上边我们定义好的“01u=a”之类的,当收到服务器传过来的文字也会在中间显示出来。可以开几个看看效果。

图片附件: 5.gif



附件(swf):   socket.rar

添加时间2007-7-18 23:18:17 共被阅读:3971 次
类别索引