Author | Message | Time |
---|---|---|
Spilled[DW] | Ok, in my .Net bot im attemping to create im using a NetworkStream for sending//recieving data, but I'm not doing it the right way obviously because its not working and I was wondering if someone could give me some help or show me an example of how its done. Here I create the connection and a thread for the recieving. [code] Private Sub mnuConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuConnect.Click Dim port As Int32 = 6112 Dim Server As String = "asia.battle.net" AddChat(Color.Yellow, "Attemping to Connect.") Try wSock = New TcpClient(Server, port) Stream = wSock.GetStream() Dim pbyte(1) As Byte pbyte(0) = &H1 Stream.Write(pbyte, 0, 1) InsertDWORD(0) InsertNonNTString("68XI") InsertNonNTString(sClient) InsertDWORD(&HCD) InsertDWORD(0) InsertDWORD(0) InsertDWORD(0) InsertDWORD(0) InsertDWORD(0) InsertNTString("USA") InsertNTString("United States") SendBNCSPacket(&H50) Dim t As Thread t = New Thread(AddressOf Recieve) t.Start() Catch f As SocketException AddChat(Color.Red, f) End Try End Sub [/code] Here is the recieving loop that is not working... [code] Dim tempBuff2(299) As Byte, pLen As Long, TotalBytes As Long, used As Long While Stream.CanRead Do While Stream.DataAvailable used = 0 pLen = 0 TotalBytes = Stream.Read(tempBuff2, 0, tempBuff2.Length) Dim tempBuff(TotalBytes - 1) As Byte Array.Copy(tempBuff2, 0, tempBuff, 0, TotalBytes) While used <> TotalBytes pLen = tempBuff(used + 2) Dim p1(pLen - 1) As Byte Array.Copy(tempBuff, used, p1, 0, pLen) Parsep(p1) used = used + pLen End While Stream.Flush() Loop End While [/code] Any ideas guys? Also after every time I Write//Send bytes, should I be doing NetworkStream.Flush? | January 17, 2006, 9:01 AM |
indulgence | [quote author=MSDN]NetworkStream.Flush Method Flushes data from the stream. This method is reserved for future use. Remarks The Flush method implements the Stream.Flush method; however, because NetworkStream is not buffered, it has no affect on network streams. Calling the Flush method will not throw an exception.[/quote] [code] Function Receive() As String Dim Bytes(wSock.ReceiveBufferSize) As Byte Dim objSR As New System.IO.StreamReader(Stream, Encoding.ASCII) Receive = (objSR.ReadToEnd()) End Function[/code] Maybe loop calls to that looking for a terminator... not really into the "bot" thing | January 17, 2006, 6:56 PM |
Myndfyr | The first thing I'm having an issue with is that you're not providing any information about what's wrong. You're not giving us an error, you're not giving us a packet log, or any indication about what might be wrong. We're just supposed to sift through a mound of code and determine what the problem is for you. Here's one problem I see. It's probably not the cause of your problems, but it can be a problem down the line: [quote author=Spilled link=topic=13937.msg142136#msg142136 date=1137488503] [code] Private Sub mnuConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuConnect.Click Dim t As Thread t = New Thread(AddressOf Recieve) t.Start() End Sub [/code] [/quote] You're creating a thread in a local scope and not saving it to the global scope. While this won't terminate the thread when you exit scope, it will prevent you from ever terminating the thread outside of your loop (Thread.CurrentThread.Stop()), which is programmatically a questionable thing to do. [quote author=Spilled link=topic=13937.msg142136#msg142136 date=1137488503] Here is the recieving loop that is not working... [code] Dim tempBuff2(299) As Byte, pLen As Long, TotalBytes As Long, used As Long While Stream.CanRead Do While Stream.DataAvailable used = 0 pLen = 0 TotalBytes = Stream.Read(tempBuff2, 0, tempBuff2.Length) Dim tempBuff(TotalBytes - 1) As Byte Array.Copy(tempBuff2, 0, tempBuff, 0, TotalBytes) While used <> TotalBytes pLen = tempBuff(used + 2) Dim p1(pLen - 1) As Byte Array.Copy(tempBuff, used, p1, 0, pLen) Parsep(p1) used = used + pLen End While Stream.Flush() Loop End While [/code] [/quote] Where to begin? You have a lot more loops in there than is necessary. At most you need one loop, and that's the outer loop. I'm not sure if "While stream.CanRead" is appropriate. You might rather look at "stream.Socket.Connected" instead. The nice thing about a NetworkStream as opposed to using something like a raw Socket is that you get the ability to parse data with stream reading tools like the StreamReader and BinaryReader. Both of these classes work with streams. Realistically though, to parse a single packet, each receive loop (the actual loop iteration, not the code construct) should receive 4 bytes out of the socket, parse the header, and then receive packet-length more bytes out of the stream. Since the header is nice and tells you how long the packet is, you only need to read that much more data to get a complete packet, and wait until you're ready to parse the next packet. That's how MBNCSUtil does it: [code] /// <summary> /// Creates a new data reader with the specified stream as input. /// </summary> /// <param name="str">The stream from which to read.</param> public BncsReader(Stream str) : base(str) { if (str == null) Locales.ThrowNullArgExc(ResID.streamNull, ResID.param_str); using (BinaryReader br = new BinaryReader(str)) { byte[] header = new byte[4]; br.ReadByte(); m_id = br.ReadByte(); m_len = br.ReadUInt16(); if (m_len > 4) { int moreDataLen = m_len - 4; int curIncIndex = 0; m_data = new byte[moreDataLen]; while (moreDataLen > 0) { int tmpLen = br.Read(m_data, curIncIndex, moreDataLen); curIncIndex += tmpLen; moreDataLen -= tmpLen; } } } } [/code] Also, you might be getting the "Changes to the appearance of Windows controls must take place on the same thread as they were created" problem. For example, if you're setting text in a rich text box in the Parsep function, you're doing that on the child thread. That causes a Windows error and consequently a runtime .NET exception (sometimes; the RTB has a weird problem in that it doesn't always throw an exception, but freezes the program). [quote author=Spilled link=topic=13937.msg142136#msg142136 date=1137488503] Also after every time I Write//Send bytes, should I be doing NetworkStream.Flush? [/quote] See: [quote author=MSDN]Remarks The Flush method implements the Stream.Flush method; however, because NetworkStream is not buffered, it has no affect on network streams. Calling the Flush method will not throw an exception.[/quote] Indulgence, I suggest you take a look at that last sentence before you try to look cool. | January 17, 2006, 7:03 PM |
indulgence | [quote author=MyndFyre link=topic=13937.msg142168#msg142168 date=1137524639] See: [quote author=MSDN]Remarks The Flush method implements the Stream.Flush method; however, because NetworkStream is not buffered, it has no affect on network streams. Calling the Flush method will not throw an exception.[/quote] Indulgence, I suggest you take a look at that last sentence before you try to look cool. [/quote] Sheesh sorry I edited that part in if you would have noticed - only b/c I, obviously, misread. My initial statement was that the calls were un-neccessary... | January 17, 2006, 7:15 PM |
kamakazie | [quote author=MyndFyre link=topic=13937.msg142168#msg142168 date=1137524639] Realistically though, to parse a single packet, each receive loop (the actual loop iteration, not the code construct) should receive 4 bytes out of the socket, parse the header, and then receive packet-length more bytes out of the stream. Since the header is nice and tells you how long the packet is, you only need to read that much more data to get a complete packet, and wait until you're ready to parse the next packet. That's how MBNCSUtil does it: [code] byte[] header = new byte[4]; str.Read(header, 0, 4); m_id = header[1]; m_len = BitConverter.ToUInt16(header, 2); if (m_len > 4) { m_data = new byte[m_len - 4]; str.Read(m_data, 0, m_len - 4); } [/code] [/quote] You need to be careful with that call to [tt]Read[/tt] because it does not guarantee it will read 4-bytes. Checking the return value would be wise. | January 17, 2006, 9:18 PM |
Myndfyr | [quote author=dxoigmn link=topic=13937.msg142182#msg142182 date=1137532727] You need to be careful with that call to [tt]Read[/tt] because it does not guarantee it will read 4-bytes. Checking the return value would be wise. [/quote] Yeah that is old code, I've already switched it over to BinaryReader-based code. But it's the same idea: it should block until the specified data comes in. | January 17, 2006, 9:21 PM |
Spilled[DW] | Ok, ive switch my NetWorkStream receive sub to BinaryReader and all is fine until after i receive 0x25 and 0x50 Heres my code: [code] Public Sub Receive(ByVal str As NetworkStream) Dim br As New BinaryReader(str) Dim header(4) As Byte, m_Read As Long, m_ID As Byte, pLen As Short While Stream.CanRead br.ReadByte() m_ID = br.ReadByte() pLen = br.ReadInt16 If pLen > 4 Then Dim moreData As Short moreData = pLen - 4 Dim p1(pLen - 1) As Byte Dim curIndex As Integer = 4 p1(0) = &HFF p1(1) = m_ID Array.Copy(BitConverter.GetBytes(pLen), 0, p1, 2, 2) While moreData > 0 Dim tmpLen As Integer tmpLen = br.Read(p1, curIndex, moreData) curIndex += tmpLen moreData -= tmpLen End While Parsep(p1) End If End While AddChat(Color.Red, "Connection Lost..") [/code] Ok the error Occurs here: [code] br.ReadByte() [/code] I think its because it's trying to read a byte and there is no data, what would i put into the while statement to keep it from erroring but not exiting the loop? Thanks in advance guys! | January 20, 2006, 6:47 AM |
Myndfyr | NetworkStream.CanRead will always return true because it is a stream that supports reading. Please read the documentation to learn these kinds of things. | January 24, 2006, 4:13 PM |
Spilled[DW] | hrmm well when I do Stream.Socket.Connected there is no .Socket property, Could this have something to do with the .Net Framework? I'm using the 1.1 Framework currently. | January 24, 2006, 4:17 PM |
Myndfyr | [quote author=Spilled link=topic=13937.msg142954#msg142954 date=1138119440] hrmm well when I do Stream.Socket.Connected there is no .Socket property, Could this have something to do with the .Net Framework? I'm using the 1.1 Framework currently. [/quote] Nope, there *is* a Socket property on the networkstream class. I think it has to do with the fact that you're using a braindead case-insensitive language that doesn't know you're referring to the local identifier "stream" as opposed to the System.IO identifier "Stream". It doesn't help that your naming isn't preventing this collision, either. | January 24, 2006, 4:23 PM |
Spilled[DW] | hrmm, I never really thought of that. Well im at school right now so when I get home ill take a look, thanks again myndfyre and check back for my edit if your not too busy later. Edit: It's saying that the Socket propertie is Protected ReadOnly. Would I have to do some kind of Sub Classing? on top of that, im not using a socket im using a tcpClient. | January 24, 2006, 4:29 PM |