Click here to Skip to main content
15,891,253 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Thanks so much for replying. I need to reformulate my question... The device that function as TCP server sends data in continuous manner, because is a closed device I cannot modify any TCP server parameters. I have to receive and storage this data somewhere continuosly in order to process it, in the meantime I need to keep receiving the server data because I cannot lose any part of the server messages.

Then I have two things to do: I must to receive and storage (in an array for example) a continuous data flow, at the same time I need to read the received data to process it. The server will never stop to send data and I have to catch all the sent data.

That´s the reason I asked if there´s a way to not depend of a byte buffer to recieve data in TCP client, if there´s a way to get all the data continuosly to storage it without losing any part of the data flow.

Thanks again!

----------------------------------------------------------

Hello:

I´m using TCP client socket in my app. In this case I need to receive data from a device (that is working as TCP server) that is continuosly sending messages without specifying the lenght of the sent data before sending it, it´s like a streaming of binary data. I need to read this data and process some specific parts of the message. The most common references I found about receiving TCP data is using the Stream Read method, but this method requires to define a buffer of defined size. Please read my code below:


VB
Imports System.IO
Imports System.Net.Sockets
Imports System.Threading
Imports System.Net
Imports System.Text

Public Class Write
    Public Event DataRecieved(ByVal data As String)
    Private Stm As Stream
    Private tcpThd As Thread


    Public Sub ConnectToServer()
        Try
            Dim tcpClnt As New TcpClient
            tcpClnt.Connect(IPAddress.Parse("192.168.1.50"), 2111)
            Stm = tcpClnt.GetStream()
            tcpThd = New Thread(AddressOf ReadSocket)
            tcpThd.Start()
        Catch ex As Exception
            MsgBox(ex.Message)
            Exit Sub
        End Try

    End Sub

#Region "Private Methods"
    Private Sub ReadSocket()
        Dim Buffer() As Byte
        While True
            <b>Buffer = New Byte(4000) {}</b>
            <b>Stm.Read(Buffer, 0, Buffer.Length)</b>
            DataRecieved(Encoding.ASCII.GetString(Buffer))
        End While
    End Sub
#End Region
End Class


You can figure that if I define a buffer of 4000 bytes, I read just 4000 bytes of data sent by the device, but the device keep sending data all the time and I need to keep reading data all the time too, not just 4000 bytes... Is there a way to read data all the time and process this data at the very moment it is received?

Thanks in advance.
Posted
Updated 26-Oct-11 4:00am
v2
Comments
Reiss 25-Oct-11 9:47am    
In your code you have a While True loop - may I suggest that you alter it so that you define a meaningful boolean variable instead, so you code becomes

Private Sub ReadSocket()
Dim loopForever as Boolean = True

While loopForever
'Do stuff
End While
End Sub

I find this more readable and more obvious when you come back to look at the code at a later date

>> I have to receive and storage this data somewhere continuosly in order to process it, in the meantime I need to keep receiving the server data because I cannot lose any part of the server messages.

The socket will buffer data for you until you read it, but if the buffer becomes full it'll start dropping messages. You need to make sure that you keep reading frequently enough so that the socket doesn't have to discard anything. In other words, you need to keep reading in a loop (as you're doing) and not allow processing the data to block reading the data from the socket. I think you realize this already, based on this statement:

>> if there´s a way to get all the data continuosly to storage it without losing any part of the data flow

To address this part:

>> if there´s a way to not depend of a byte buffer

no, sockets send and receive bytes. If you want to deal directly with sockets then byte[]s are what you have to deal with. That's not the problem with your code, though, it's the processing the data on the same thread as the read that looks dangerous. Depending on how long that takes data could be backing up waiting to be read and that's what you want to avoid. It may be the case that the server doesn't send data frequently and/or parsing it doesn't take very long in which case you'll be fine as is.

If that's not the case then one way or another I think you're going to have to do the data processing on another thread. Exactly how you do that depends on the specifics of your application. What you probably don't want to do is start a new thread for every message that's received; instead you most likely want one thread that handles every message. This will make it so that each message is handled one at a time and they're handled in the order that they're received. If those things don't matter then you could either start a thread for each message (still may not be optimal) or use the Thread Pool to handle the threads for you (probably better than manual threading).

With either approach, the
while 
{ 
    read; 
    process; 
}

loop will change to
while
{
    read;
    send data to another thread for processing;
}

That way the thread doing the reading won't spend any time on processing and can continue reading data from the socket. There are still some other things to consider:
* exception handling around the code that reads from the socket - currently there is none
* how do the threads doing the reading and parsing exit cleanly? The way that read thread is written there isn't a way.
* how are you going to get data from the read thread to the processing thread? You'll want to read up on thread safety, wait handles and other general threading topics (like this[^]). Or post another question asking for help on that.
* does each read you do give you one full message to parse, or might you need to combine the data received from multiple reads into one full message? Or will one read give you multiple messages to parse all at once?
* why is a class that reads data called Write?
 
Share this answer
 
Comments
comiteco 26-Oct-11 17:04pm    
Thanks for responding. It´s clear that I cannot read TCP sockets without depending of a buffer.

I´m using a thread in the wrong called "Write" class to read socket, then I raise an event that execute a subroutine in main form to process data.

The messages will be armed in mentioned main form subroutine, besides the buffer size, I have to send data to subroutine and arm every message.

Thanks again!
Even if you were using a buffer of billion bytes, it doesn't matter. In one receive you won't get exactly the whole buffer. If you are worried that 4000 bytes are not sufficient for the whole message to pass, you could write a 4-bytes packet that would represent the size of the expected buffer and declare it accordingly (and then iterate until you would get the whole buffer). You might find it useful also to track the progress within the buffer. You can (and must) know the number of read bytes in every iteration, the Read function returns it.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900