vb的UDP广播

vb的UDP广播,第1张

方案:

所有的CLIEN的WINSOCK全用控件数组。

如:

CLIENT(0)

然后在要广播的时候

sub BroadCoast()

for I =0 to client.count-1

if client(i).state=7 then

client(i).senddata

end if

next

end sub

给你帖一个我的游戏服务器代码:

Private Sub Command1_Click()

Dim intI As Integer

For I = 0 To 最大人数

If Ws(I).State <>0 Then Ws(I).Close

Next

End

End Sub

Private Sub Command2_Click()

Dim TheIndex As Long

Dim Response

TheIndex = CLng(LsUser.ListIndex)

If TheIndex = -1 Then Exit Sub

Response = MsgBox("真的要把用户" &用户(CInt(TheIndex)).用户名 &"删除下线吗?" &TheIndex, vbOKCancel + vbQuestion)

If Response = vbOK Then

Dim KillReson As String

KillReson = InputBox("请输入踢用户下线的理由:", "踢用户下线", "")

If Len(KillReson) = 0 Then Exit Sub

FrmMain.Ws(TheIndex + 1).SendData Encrypt("444$" &KillReson, LngKeyE, LngKeyD, LngKeyN)

DoEvents

'Call KillUser(CInt(TheIndex))

Else

Exit Sub

End If

End Sub

Private Sub Command3_Click()

Dim I, K As Long

For I = 0 To LsUser.ListCount - 1

'If Trim(LsUser.Text) = 用户(I + 1).用户名 And 用户(I + 1).用户状态 = 0 Then

' LsUser.RemoveItem I + 1

' End If

For K = 1 To 最大人数

If Trim(LsUser.List(I)) = 用户(K).用户名 And 用户(K).用户状态 = 0 Then

LsUser.RemoveItem CInt(用户(K).在线列表号)

End If

Next

Next

Labonline.Caption = "当前在线:" &LsUser.ListCount &"人"

End Sub

Private Sub Form_Load()

Dim I As Long

最大人数 = 5

当前连接号 = 1

For I = 2 To 最大人数

Load Ws(I)

DoEvents

Next

WsListen.LocalPort = "1982"

WsListen.Listen

DeBugs ("服务器已经准备就绪" &vbCrLf &"共加载个" &最大人数 &"连接" &vbCrLf &"服务IP:" &WsListen.LocalIP &vbCrLf &"端口:" &WsListen.LocalPort)

Call ConnData

Me.Show

End Sub

Private Sub Form_Unload(Cancel As Integer)

For I = 1 To 最大人数

If Ws(I).State <>0 Then

Ws(I).Close

End If

Next

End Sub

Private Sub LsUser_Click()

Dim strTheU, Uindex() As String

strTheU = Trim(LsUser.Text)

strTheU = "用户名:" &用户(CLng(LsUser.ListIndex + 1)).用户名 &vbCrLf

strTheU = strTheU &"昵 称:" &用户(CLng(LsUser.ListIndex + 1)).昵称 &vbCrLf

strTheU = strTheU &"积分:" &用户(CLng(LsUser.ListIndex + 1)).积分 &vbCrLf

strTheU = strTheU &"胜:" &用户(CLng(LsUser.ListIndex + 1)).胜 &vbCrLf

strTheU = strTheU &"败:" &用户(CLng(LsUser.ListIndex + 1)).败 &vbCrLf

strTheU = strTheU &"团 队:" &用户(CLng(LsUser.ListIndex + 1)).团队名 &vbCrLf

strTheU = strTheU &"职 务:" &用户(CLng(LsUser.ListIndex + 1)).职务 &vbCrLf

strTheU = strTheU &"IP:" &用户(CLng(LsUser.ListIndex + 1)).IP &vbCrLf

strTheU = strTheU &"连接号:" &用户(CLng(LsUser.ListIndex + 1)).连接号 &vbCrLf

strTheU = strTheU &"用户状态:" &用户(CLng(LsUser.ListIndex + 1)).用户状态 &vbCrLf

Lu.Caption = strTheU

End Sub

Private Sub Ws_Close(Index As Integer)

Ws(Index).Close

用户(Index).用户状态 = 0

Call RemoteUser(CLng(Index))

DeBugs ("用户:" &用户(Index).用户名 &"离开了游戏")

End Sub

Private Sub Ws_DataArrival(Index As Integer, ByVal bytesTotal As Long)

Dim sData As String

Dim ClsData As New Data

If bytesTotal = 0 Then

MsgBox "收到的数据为空"

Ws(Index).Close: Exit Sub

End If

Ws(Index).GetData sData, vbString

DoEvents

Call ClsData.DataControl(sData, Index)

DeBugs ("收到包:" &sData)

End Sub

Private Sub Ws_Error(Index As Integer, ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)

DeBugs (Err.Description)

End Sub

Private Sub WsListen_ConnectionRequest(ByVal requestID As Long)

Dim I As Long

'//首先按顺序接收请求.

For I = 当前连接号 To 最大人数

If Ws(I).State = 0 Then

Ws(I).Accept requestID

DeBugs ("接收到远程用户的连接请求(" &Ws(I).RemoteHostIP &")")

当前连接号 = I

Exit For

End If

Next

'///如果按顺序没有空连接,则查看前面有没有退出的用户

If I = 最大人数 Then

For I = 1 To 当前连接号

If Ws(I).State = 0 Then

Ws(I).Accept requestID

Else

'WsBusy.Accept requestID

' If WsBusy.State = 7 Then

'WsBusy.SendData "服务已经满了...."

'WsBusy.Close

' End If

End If

Next

End If

End Sub

Sub DeBugs(Str)

txtDebug.Text = txtDebug.Text &Str &vbCrLf

End Sub

Public Function Login(Index As Integer, UserName As String, UserPass As String) As String

If UserName = "" Or UserPass = "" Then Login = Encrypt("999$用户名密码不能为空", "", "", "")

Dim strSql As String

Dim RsLogin As New ADODB.Recordset

strSql = "select sex,score,win,lose,groups,positions,pic,nick,lastlogintime from [user] where username='" &UserName &"' and userPass='" &UserPass &"'"

If RsLogin.State = 1 Then RsLogin.Close

RsLogin.Open strSql, Conn, 1, 3

If RsLogin.EOF Or RsLogin.BOF Then

Login = Encrypt("404$用户名或是密码错误", "", "", "")

Else

RsLogin("LastLoginTime") = Now

Dim K As Integer

Dim Plain() As String

'性别+积分+胜+输+团队+职务+头像+昵称

Ustr(Index) = ""

For K = 0 To RsLogin.Fields.Count - 1

Ustr(Index) = Ustr(Index) &RsLogin(K) &"$"

Next

Plain = Split("$" &Ustr(Index), "$")

With 用户(Index)

.连接号 = Index

.用户名 = UserName

.密码 = UserPass

.用户状态 = 1

.头像 = Plain(7)

.胜 = Plain(3)

.败 = Plain(4)

.昵称 = Plain(8)

.团队名 = Plain(5)

.职务 = Plain(6)

.积分 = Plain(2)

.性别 = Plain(1)

.IP = Ws(Index).RemoteHostIP

End With

LsUser.AddItem UserName

用户(Index).在线列表号 = LsUser.ListCount - 1

LsUser.Refresh

Labonline.Caption = "共有" &LsUser.ListCount &"人在线"

Login = "20$" &Ustr(Index) &"$" &用户(Index).连接号

End If

'If RsLogin.State = 1 Then RsLogin.Close

End Function

Public Sub KillUser(Index As Integer)

If Index <0 Then Exit Sub

Ws(Index + 1).Close

用户(Index + 1).用户状态 = 0

Call RemoteUser(Index + 1)

End Sub

Public Sub RemoteUser(Index As Integer)

' On Error Resume Next

If Index = -1 Then Exit Sub

Dim I As Long

For I = 0 To LsUser.ListCount - 1

If Trim(LsUser.List(I)) = Trim(用户(Index).用户名) Then

LsUser.RemoveItem I

LsUser.Refresh

Labonline.Caption = "共有" &LsUser.ListCount &"人在线"

'Exit For

End If

Next

End Sub

Public Function OnlineUser(Index As Integer, Hall As Integer)

Dim I As Long

Dim strOnUser As String

For I = 0 To 最大人数

If 用户(I).游戏ID = Hall And Len(用户(I).用户名) >0 And 用户(I).连接号 <>Index And 用户(I).用户状态 = 1 Then

OnUser = OnUser &"###" &用户(I).所在桌 &"$" &用户(I).所在座 &"$" &Ustr(I) &"$" &用户(I).用户名 &"$" &用户(I).连接号 &"$" &用户(I).IP

FrmMain.DeBugs ("user:" &I &"GameId:" &用户(I).游戏ID &"username:" &用户(I).用户名 &"Connectnum:" &用户(I).连接号 &"userstaus:" &用户(I).用户状态 &"---->send")

Else

FrmMain.DeBugs ("user:" &I &"GameId:" &用户(I).游戏ID &"username:" &用户(I).用户名 &"Connectnum:" &用户(I).连接号 &"userstaus:" &用户(I).用户状态 &"---->not send")

End If

DoEvents

Next

'///报头+1房间ID+2桌+3坐+4性别+5积分+6胜+7输+8团队+9职务+10头像+11上次LOGON时间+12昵称+13用户名+14连接号+15ip

OnlineUser = "4000$" &Hall &"$" &OnUser

End Function

星际争霸热键:

数字:按一下为控制已编好号的部队或建筑物,按两下为控制并跳到编好号的部队或建筑所在地。

P:巡逻。用“P”将部队点到别人基地,则在路上部队会自动攻击遇到的敌人。

鼠标右键:SCV点水晶为或天然气井为采矿,点损坏的建筑或机械部队维修理。部队点敌人为攻击,点自己人为跟随。

A:攻击。可用来强制攻击自己的建筑或部队。

F1 辅助说明

F10 游戏主选单

+ 增加游戏速度

- 减低游戏速度

Alt-M 游戏主选单

Alt-S 储存游戏进度

Alt-L 提取游戏进度

Alt-H 辅助说明

制作背景

游戏描述了26世纪初期,位于银河系中心的三个种族在克普鲁星际空间中争夺霸权的故事。三个种族分别是:地球人的后裔人族(Terran)、一种进化迅速的生物群体虫族(Zerg),以及一支高度文明并具有心灵力量的远古种族神族(Protoss)。游戏三个独特种族的创新设计得到了好评。

《星际争霸》提供了一个游戏战场,用以玩家之间进行对抗。这也是该游戏以及所有即时战略游戏的核心内容。在这个游戏战场中,玩家可以操纵任何一个种族,在特定的地图上采集资源,生产兵力,并摧毁对手的所有建筑取得胜利。

游戏同时为玩家提供了多人对战模式。在韩国这一项目尤为盛行,并发展出了职业的游戏比赛。大量选手在电视联赛上进行对抗,赢得了很高的知名度。

首先,游戏服务器与普通服务器相比较来说,游戏服务器需要能够保存更多的用户的状态。用户的等级等属性不用说,一般的IM服务也会有,还有一些时刻变化的数据,比如某个玩家的生命值,发技能前后的法力值等等,这些值区别于一般的属性值如名字,ID这些,这些数据会经常性的变化,还会参与到逻辑的计算中,比如你一个多少等级的玩家吃了什么东西之后战力值变化为多少,打在一个多少属性的玩家身上会不会被他闪避,会不会产生暴击…诸如此类的信息,在游戏服务器中都会一一保存。

其次,游戏服务器中每一个用户都是独立存在的,每一个用户的数据、请求等都是独立的,用户彼此间的数据并没有任何交互。这也是游戏服务器与普通服务器之间最大的区别。至于客户端之间会有交互这一点,举最简单的例子,一个人在一个场景里面说了一句话,那么“同一个屏幕”的玩家也需要能够看到他说的这句话。此时游戏服务器就需要判断,多远的距离以内的玩家,会认定为是"同屏幕"的玩家,需要向这些玩家广播这个玩家说的这句话。

这个广播就比较麻烦了。首先,需要计算哪些玩家属于"同屏幕",就是我们在第一点提到的玩家身上某些经常变化的属性需要做的运算,在这里需要根据玩家的坐标,找出来跟在同屏幕的玩家,用到的是AOI的概念。另外,找到了这些需要接收这个消息的玩家之后,将消息转发给它们又是一个IO密集的操作,假如场景中有10个人,那么一句话就需要同时广播给另外9个人,假如有100人,1000人呢,数据量就更大了,而且时间的延迟也不能太长,这对于游戏服务器的性能就要求很高了。所以同样的一个硬件配置的服务器,可能跑Nginx可以同时处理上万的链接,但是对于一个游戏服务器就只有1,2千了,就是因为游戏服务器是一个CPU密集而且IO密集的服务器类型。而且不仅需要这样的游戏服务器不仅要求性能比较高,还需要服务器具有极高的稳定性,总不能隔一会就宕机了,那大家还怎么玩。

此外,游戏服务器需要更好的数据承载能力和处理能力。而普通服务器则在各个方面都比较均衡。在寻找游戏服务器租用商的时候,一定要选择那种CPU性能非常出色的。

最后一点,游戏行业一直以来是网络攻击的重灾区,很多游戏刚上线没多久就频繁遭到攻击,导致玩家大量流失口碑下降,最后可能导致直接关服。所以游戏服务器一定要带高防流量包。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/792472.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-08-26
下一篇2023-08-26

发表评论

登录后才能评论

评论列表(0条)

    保存