( search forums )
admin in vb
Soldat Forums - Soldat Talk - Developers Corner
mar77a
March 19, 2006, 2:37 am
so, im writting an admin in vb from scratch...so far it's working fine the only thing i cant work out is why i dont get anything back from teh server after sending REFRESH

this is what the code looks like:
[code]
Private Sub Timer2_Timer()
Winsock1.SendData "REFRESH" + vbCrLf
Dim refresh As String
Winsock1.GetData refresh, , 1096
MsgBox refresh
End Sub
[/code]

umm, the msgbox prompt appears empty.

btw, you can suggest features if you want.

Deleted User
March 19, 2006, 2:41 am
You cant put the GetData command in a timer, you need to put it in the Winsock1_DataArrival() event.

[code]
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim sData As String
Winsock1.GetData sData
MsgBox sData
End Sub
[/code]

mar77a
March 19, 2006, 3:06 am
The thing is, im getting nothing in return. Ill try reinstalling teh server.

Deleted User
March 19, 2006, 3:13 am
If all else fails, try just GetData without the "refresh, ,1096" part

bja888
March 19, 2006, 12:23 pm
You using VB.NET or VB6?

mar77a
March 19, 2006, 1:54 pm
vb6.

Enesce, i have a console where the buffer is dumped (DataArrival) and when i winscock1.sendata "REFRESH" + vbCrLf, i get nothing. (Just the REFRESH).

DeMo
March 22, 2006, 2:52 am
Have u tried that without the vbCrLf at the end?
As far as I know VB (or Winsock) itself appends the CrLf to the end of the data when sending it.

Deleted User
March 22, 2006, 7:12 am
That is false DeMo, it definately does not do that. Show us some of your code mar77a?

mar77a
March 22, 2006, 9:05 pm
here's the code:

[code]
Option Explicit

Private Sub Command1_Click()
Winsock1.SendData Text2.Text & vbCrLf
Text1.SelStart = Len(Text1.Text) 'coloca el cursor al final del contenido
Text2.Text = "/"


End Sub

Private Sub Command2_Click()
Winsock1.Close
Winsock1.RemoteHost = Text3.Text
Winsock1.RemotePort = Text4.Text
Winsock1.Connect
End Sub

Private Sub Command3_Click()
Winsock1.Close
If Winsock1.State = sckClosed Then
Text1.Text = Text1.Text & "Disconnected." & vbCrLf
Else
Text1.Text = Text1.Text & "Could not disconnect." & vbCrLf
End If
Text1.SelStart = Len(Text1.Text)


End Sub

Private Sub Form_Load()
Dim ips As String
Dim ports As String
ips = ReadINI("CONFIG", "IP", "admin.ini")
ports = ReadINI("CONFIG", "Port", "admin.ini")
If ReadINI("CONFIG", "Frq", "admin.ini") <> "" Then
Timer2.Interval = ReadINI("CONFIG", "Frq", "admin.ini")
Else
Timer2.Interval = 5500
End If
If ips <> "" And ports <> "" Then
Text3.Text = ips
Text4.Text = ports
End If
End Sub

Private Sub Form_Terminate()
Winsock1.Close
End Sub

Private Sub Form_Unload(Cancel As Integer)
Winsock1.Close
End Sub


Private Sub Text1_Click()
Dim ret As Integer
ret = MsgBox("Clear console?", vbYesNo + vbExclamation, "Confirm")
If ret = vbYes Then
Text1.Text = ""
End If
End Sub

Private Sub Text3_GotFocus()
If Winsock1.State = sckClosed Then
Text3.Text = ""
End If

End Sub


Private Sub Text4_GotFocus()
If Winsock1.State = sckClosed Then
Text4.Text = ""
End If
End Sub


Private Sub Text5_GotFocus()
If Winsock1.State = sckClosed Then
Text5.Text = ""
Text5.PasswordChar = "*"
End If
End Sub


Private Sub Timer1_Timer()
If Winsock1.State = sckClosed Then
Timer2.Enabled = False

Command3.Enabled = False
command1.Enabled = False
Command2.Enabled = True
status.Caption = "Disconnected"
Text2.Enabled = False
Combo1.Enabled = False
Text1.Enabled = False
Text3.Enabled = True
Text4.Enabled = True
Text5.Enabled = True
ElseIf Winsock1.State = sckClosing Then
status.Caption = "Disconnecting..."
ElseIf Winsock1.State = sckConnecting Then
status.Caption = "Connecting..."
ElseIf Winsock1.State = sckResolvingHost Then
status.Caption = "Resolving host..."
ElseIf Winsock1.State = sckHostResolved Then
status.Caption = "Host resolved..."
ElseIf Winsock1.State = sckConnected Then
Timer2.Enabled = True
WriteINI Text3.Text, "CONFIG", "IP", "admin.ini"
WriteINI Text4.Text, "CONFIG", "Port", "admin.ini"
WriteINI Timer2.Interval, "CONFIG", "Frq", "admin.ini"
Command3.Enabled = True
command1.Enabled = True
status.Caption = "Connected"
Text2.Enabled = True
Combo1.Enabled = True
Text1.Enabled = True
Text3.Enabled = False
Text4.Enabled = False
Text5.Enabled = False
Command2.Enabled = False
End If

End Sub

Private Sub Timer2_Timer()
Winsock1.SendData "REFRESH" + vbCrLf
End Sub

Private Sub Winsock1_Close()
Winsock1.Close
Text1.SelStart = Len(Text1.Text)


End Sub

Private Sub Winsock1_Connect()
Winsock1.SendData Text5.Text + vbCrLf
Text1.SelStart = Len(Text1.Text)
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim Buffer As String 'variable para guardar los datos


'obtenemos los datos y los guardamos en una variable

Winsock1.GetData Buffer


'apuntamos al final del contenido del TextBox e

'insertamos los nuevos datos obtenidos

Text1.SelStart = Len(Text1.Text) 'coloca el cursor al final del contenido

Text1.Text = Text1.Text & Buffer
'mostramos los datos

Text1.SelStart = Len(Text1.Text) 'coloca el cursor al final del contenido


End Sub

Private Sub Winsock1_Error(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)
'cerramos la conexion

Winsock1.Close


'mostramos informacion sobre el error

MsgBox "Error numero " & Number & ": " & Description, vbCritical


End Sub
[/code]

chrisgbk
March 22, 2006, 11:37 pm
I don't know what your issue is, I just copied your code into a VB project and added the necesary controls and it works. If, like I think, you are wondering why the Refresh data apparantly doesn't show up in the console log, its this: there are null bytes in the reply (&h00) which is interpreted as the end of a string. You will have to parse the reply on a byte level, not a string level.

Deleted User
March 23, 2006, 12:01 am
Null gets converted into a space in a textbox. Have you got the textbox set to multiline? I cant test your code here, im at school.

chrisgbk
March 23, 2006, 12:35 am
through testing, found out something: the refresh packet is split into 2 pieces(in VB at least) I'll throw some code back on here to deal with that, and the case where the concatenation bug happpens (randomly, with high lag connections, 2 packets of data get combined into 1)

DeMo
March 24, 2006, 9:02 pm
Dude.. give some proper names to your controls!!
Your code is messy.. lots of Command1, Command2, Combo1, Text1, Text2, Text3, Text4, Text5.

You should name the controls in a way that makes it easier to understand what is what.
Like: txtHost, txtPort, cmdConnect.....

mar77a
March 24, 2006, 10:28 pm
yeah i know, but as one wise man once said...(n00bface)..."i name my variables in PHP with names like $michaeljackson"

bja888
March 25, 2006, 1:53 am
string alotherFuckingTemp = string.Empty;

is still better than
string temp3 = string.Empty;


:)

Deleted User
March 25, 2006, 2:58 am
haha I used to name all my vars whatever the first thing that came to my mind was, which was usually $omglol (im sure chrisgbk knows about my $omglol habits :p)

FliesLikeABrick
March 25, 2006, 3:21 am
bja888 this is your first warning. 2 more warnings and you get a ban. Don't avoid the swear filter

chrisgbk
March 25, 2006, 9:37 am
[code]
'Additions:

Private Type RefreshPacket
PlayerName(31) As String
Team(31) As Byte
Kills(31) As Long
Deaths(31) As Long
Ping(31) As Byte
Number(31) As Byte
IP(31, 3) As Byte
TeamScore(3) As Long
MapName As String
TimeLimit As Double
CurrentTime As Double
KillLimit As Long
GameStyle As Byte
End Type

Private Function parseRefreshPacket(packet() As Byte, Optional offset As Byte = 0) As RefreshPacket
Dim i As Integer
Dim k As Integer
Dim j As Integer
Dim length As Byte
i = offset
With parseRefreshPacket
For k = 0 To 31
length = packet(i)
i = i + 1
For j = 0 To 23
.PlayerName(k) = .PlayerName(k) + Chr(packet(i))
i = i + 1
Next j
.PlayerName(k) = Left(.PlayerName(k), length)
Next k
For k = 0 To 31
.Team(k) = packet(i)
i = i + 1
Next k
For k = 0 To 31
.Kills(k) = packet(i) + (packet(i + 1) * 256&)
i = i + 2
Next k
For k = 0 To 31
.Deaths(k) = packet(i) + (packet(i + 1) * 256&)
i = i + 2
Next k
For k = 0 To 31
.Ping(k) = packet(i)
i = i + 1
Next k
For k = 0 To 31
.Number(k) = packet(i)
i = i + 1
Next k
For k = 0 To 31
For j = 0 To 3
.IP(k, j) = packet(i)
i = i + 1
Next j
Next k
For k = 0 To 3
.TeamScore(k) = packet(i) + (packet(i + 1) * 256&)
i = i + 2
Next k
length = packet(i)
i = i + 1
For k = 0 To 15
.MapName = .MapName + Chr(packet(i))
i = i + 1
Next k
.MapName = Left(.MapName, length)
For k = 0 To 3
.TimeLimit = .TimeLimit + (packet(i) * (256& ^ k))
i = i + 1
Next k
For k = 0 To 3
.CurrentTime = .CurrentTime + (packet(i) * (256& ^ k))
i = i + 1
Next k
.KillLimit = packet(i) + (packet(i + 1) * 256&)
i = i + 2
.GameStyle = packet(i)
End With
End Function


'Changes:

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Static refresh As Boolean
Dim tempstring As String
Dim Buffer() As Byte
dim packet as RefreshPacket
Winsock1.GetData Buffer
tempstring = StrConv(Buffer, vbUnicode)
If Left(tempstring, 7) = "REFRESH" Then
If Len(tempstring) = 9 Then
refresh = True
Else
packet = parseRefreshPacket(Buffer, 9)
End If
ElseIf refresh And UBound(Buffer) = 1187 Then
packet = parseRefreshPacket(Buffer)
refresh = False
Else
Text1.Text = Text1.Text & tempstring
End If

Text1.SelStart = Len(Text1.Text)
'todo: output the refresh packet data somewhere
End Sub
[/code]

You should also consider avoiding timers as much as possible. The ONLY place I would accept a timer in this code is for automatically sending the refresh packet at defined intervals; no where else.

As well, correctly naming variables based on their function and data type will make coding easier, especcially for someone debugging. I had to guess at what each textbox did, because with a name like "Text1" it isn't clear.

You may have noticed that the variable types I use don't exactly match the actual data sent by soldat: this is because VB doesn't support unsigned numbers, so I elected to up to the next largest datatype; 2 byte unisnged integer becomes a long (4 bytes), 4 byte unsigned integer becomes a double (8 byte floating point).

The time limit variables are expressed in ticks; divide by 60 to get seconds, and by another 60 to get minutes.

DeMo
March 25, 2006, 8:14 pm
Wow, you wrote the whole parse function by hand, good work!

That's the problem with VB6.. some stuff is very poor and lame. In other languages you can create a structure (Type) that is the same size and format as the refresh packet and then you just throw the data received by the socks into the structure and it gets automatically parsed.

One addition: The CurrentTime variable gets decremented over time, a more correct name would be TimeLeft. It starts with the same value as TimeLimit and then goes down to 0 (zero).

chrisgbk
March 26, 2006, 11:51 pm
Yeah, I used more or less the same variables as MM used in his soldat admin (copy/paste, find/replace makes converting delphi to VB easy)

you are right about the lameness, very limiting. It IS possible to create a structure that is the same size and format as the refresh packet and (almost) use it directly, but there are limitations: the structure cannot itself contain structures, only primitive types. and you have to use an auxillery structure, ie:
[CODE]
private type auxStruct
data(1187) as byte '1188 bytes
end type

private type refreshPacket
'1188 bytes worth of data using only primitives
end type

dim buffer as auxStruct
dim packet as refreshPacket
Winsock1.GetData Buffer.data
LSet packet = buffer
'LSet copies bytes from one struct to another without regard for underlying data type
[/CODE]


its not really practicle to use, but possible.