[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Tym

10/17/2008 3:56:00 PM

After programming in VB.Net for a couple of years now, I'm taking my first
steps in TCP transfers

I have a device which reports back to me via GRPS and thanks to Google I've
managed to adapt a suitable port listener to I can grab the data.

My quesiton is, whct if I've got 1000 of these things reporting back all on
the same port number... how do I ensure that all the data gets captured from
all units?

Example code here:

'////////////////////////////////////////
Imports System.Net.Sockets
Imports System.Text

Class TCPSrv

Shared Sub Main()

' Must listen on correct port- must be same as port client wants to connect
on.

Do

Grabbit()

Loop

End Sub

Shared Sub Grabbit()

Const portNumber As Integer = 24601

Dim PortListener As New TcpListener(portNumber)

Dim sWORDS() As String

Dim I As Integer

Dim dblLAT As Double

Dim dblLONG As Double

Dim dblBEARING As Double



Try

PortListener.Start()

Console.WriteLine("Waiting for connection... " & Now)

'Accept the pending client connection and return a TcpClient initialized for
communication.

Dim tcpClient As TcpClient = PortListener.AcceptTcpClient()

Console.WriteLine("Connection accepted. " & Now)

' Get the stream

Dim networkStream As NetworkStream = tcpClient.GetStream()

' Read the stream into a byte array

Dim bytes(tcpClient.ReceiveBufferSize) As Byte

networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

' Return the data received from the client to the console.

Dim clientData As String = Encoding.ASCII.GetString(bytes)

sWORDS = Split(clientData, ",")

For I = 0 To UBound(sWORDS) '- 1

Debug.Print(I & " - " & sWORDS(I))

Next

Debug.Print(" " & vbCrLf)

Debug.Print("=====================================================")

Beep()

'Console.WriteLine(("Client sent: " + clientdata))

Dim responseString As String = "Connected to server. " & Now

'Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(responseString)

'Any communication with the remote client using the TcpClient can go here.

'Close TcpListener and TcpClient.

tcpClient.Close()

PortListener.Stop()

Debug.Print(clientData)

Debug.Print(vbCr)

Console.WriteLine("exit")

'Console.ReadLine()

Catch e As Exception

Debug.Print(e.ToString)

Console.WriteLine(e.ToString())

'Console.ReadLine()

End Try

End Sub

End Class

'////////////////////////////////////////

How do I make it work 1000 times at the same time??? :-)


9 Answers

Peter Duniho

10/17/2008 6:29:00 PM

0

On Fri, 17 Oct 2008 08:55:58 -0700, Tym <spamtrap@ictis.net> wrote:

> After programming in VB.Net for a couple of years now, I'm taking my
> first
> steps in TCP transfers
>
> I have a device which reports back to me via GRPS and thanks to Google
> I've
> managed to adapt a suitable port listener to I can grab the data.
>
> My quesiton is, whct if I've got 1000 of these things reporting back all
> on
> the same port number... how do I ensure that all the data gets captured
> from
> all units?

That depends on whether you want to handle 1000 at a time, or 1000 in
sequence one at a time.

If you just want to handle them one at a time, the main thing you need to
change is to loop back to the call to AcceptTcpClient() after you're done
reading from a client.

If you want to handle all of the clients at the same time, you need to
separate the client connection accepting logic from the client receiving
logic. In the code you posted, you accept and receive data in the same
method. To handle multiple clients at once, you need to have one part of
the code that only deals with accepting clients. In that code, for each
client you'll need to hand off the created client connection to another
part of the code, which will deal with the actual communications with the
client.

The part of the code that deals with the actual communications can be
written in a variety of ways, but the most appropriate approach in .NET
would be to use the asynchronous programming model. If you want to
continue using TcpClient, you can use the BeginRead() method on the stream
you get from the TcpClient. Alternatively, you can call AcceptSocket()
instead of AcceptTcpClient(), and on the Socket instance call
BeginReceive() or ReceiveAsync() (the latter has somewhat better
performance characteristics under certain conditions, but for only a 1000
clients, either is probably fine).

By using the asynchronous programming model, you allow the framework to
manage the i/o threads, and you only have to code the callbacks to handle
the completion of i/o. You can start arbitrarily many i/o operations, one
at a time after each call to Accept...() returns, and then go right back
to calling the Accept...() method again. A different thread will be used
when the i/o operation actually completes.

You can even handle the accept logic using the asynchronous programming
model, and in fact that would generally be my preference. But if you only
have the one server socket listening, that may be overkill.

Pete

Tym

10/19/2008 6:33:00 PM

0

I must admint - half of what you said went straight over my head! So I hit
google and still none the wiser - yet!

I've created a new app for this - a windows app rather than console as
before.

My main form is now:

Imports System.Net.Sockets

Imports System.Text

Public Class Form1

Public frmTCP As Form

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Const portNumber As Integer = 24601

Dim PortListener As New TcpListener(portNumber)

Dim tcpClient As New TcpClient

Me.Show()

'Call ReverseGEOData(53.1, -2.1)

Application.DoEvents()

Try

PortListener.Start()

Catch ex As Exception

MsgBox(ex.ToString)

End Try

Do

Application.DoEvents()

txtCONNLog.Text &= "Waiting for connection: " & Now() & vbCrLf

Application.DoEvents()

tcpClient = PortListener.AcceptTcpClient()

Dim frmDATA As New frmPORTdata(tcpClient)

tcpClient = Nothing

Loop



End Sub

End Class



Which as you can see sends the tcpClient off to another form each time the
connection is made for the forn to deal with it.

My form2 routine works fine in taking the connection and getting te data
from it using more or less the same routine as before - just a basuic
question I guess, is this sufficient to handle things the way I want them
handled, with the possibility of being bombarded with connections all on the
same port?

Form2:
Public Sub New(ByVal newParameter As TcpClient)



' This call is required by the Windows Form Designer.

InitializeComponent()

' Add any initialization after the InitializeComponent() call.

tcpClient = newParameter

Dim sWORDS() As String

Dim sIMEI As String

Dim sMSG As String



Dim I As Integer

Dim dblLAT As Double

Dim dblLONG As Double

Dim dblBEARING As Double

Dim singSPEED As Single

Me.Show()

Application.DoEvents()

Try

' Get the stream

Dim networkStream As NetworkStream = tcpClient.GetStream()

' Read the stream into a byte array

Dim bytes(tcpClient.ReceiveBufferSize) As Byte

Debug.Print("Receive buffer size = " & tcpClient.ReceiveBufferSize)

networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))

' Return the data received from the client to the console.

Dim clientData As String = Encoding.ASCII.GetString(bytes)

AddToFile (MyFile,clientData)

Catch ex As Exception

Console.WriteLine(ex.ToString)

txtCONdata.Text &= ex.ToString & vbCrLf

End Try

Me.Dispose()

End Sub

Public Sub AddToFile(ByVal sFILENAME As String, ByVal sTEXT As String)

Using sw As StreamWriter = New StreamWriter(sFILENAME, True)

sw.WriteLine(sTEXT)

sw.Close()

End Using

End Sub

End Class



"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
news:op.ui6lm2jn8jd0ej@petes-computer.local...
> On Fri, 17 Oct 2008 08:55:58 -0700, Tym <spamtrap@ictis.net> wrote:
>
>> After programming in VB.Net for a couple of years now, I'm taking my
>> first
>> steps in TCP transfers
>>
>> I have a device which reports back to me via GRPS and thanks to Google
>> I've
>> managed to adapt a suitable port listener to I can grab the data.
>>
>> My quesiton is, whct if I've got 1000 of these things reporting back all
>> on
>> the same port number... how do I ensure that all the data gets captured
>> from
>> all units?
>
> That depends on whether you want to handle 1000 at a time, or 1000 in
> sequence one at a time.
>
> If you just want to handle them one at a time, the main thing you need to
> change is to loop back to the call to AcceptTcpClient() after you're done
> reading from a client.
>
> If you want to handle all of the clients at the same time, you need to
> separate the client connection accepting logic from the client receiving
> logic. In the code you posted, you accept and receive data in the same
> method. To handle multiple clients at once, you need to have one part of
> the code that only deals with accepting clients. In that code, for each
> client you'll need to hand off the created client connection to another
> part of the code, which will deal with the actual communications with the
> client.
>
> The part of the code that deals with the actual communications can be
> written in a variety of ways, but the most appropriate approach in .NET
> would be to use the asynchronous programming model. If you want to
> continue using TcpClient, you can use the BeginRead() method on the stream
> you get from the TcpClient. Alternatively, you can call AcceptSocket()
> instead of AcceptTcpClient(), and on the Socket instance call
> BeginReceive() or ReceiveAsync() (the latter has somewhat better
> performance characteristics under certain conditions, but for only a 1000
> clients, either is probably fine).
>
> By using the asynchronous programming model, you allow the framework to
> manage the i/o threads, and you only have to code the callbacks to handle
> the completion of i/o. You can start arbitrarily many i/o operations, one
> at a time after each call to Accept...() returns, and then go right back
> to calling the Accept...() method again. A different thread will be used
> when the i/o operation actually completes.
>
> You can even handle the accept logic using the asynchronous programming
> model, and in fact that would generally be my preference. But if you only
> have the one server socket listening, that may be overkill.
>
> Pete


Tym

10/19/2008 6:36:00 PM

0

Sorry for typos - I've had a tiring weekend...

"Tym" <spamtrap@ictis.net> wrote in message
news:2o-dnW7fkvLn4GbVnZ2dnUVZ8s_inZ2d@posted.plusnet...
>I must admint - half of what you said went straight over my head! So I hit
>google and still none the wiser - yet!
>
> I've created a new app for this - a windows app rather than console as
> before.
>
> My main form is now:
>
> Imports System.Net.Sockets
>
> Imports System.Text
>
> Public Class Form1
>
> Public frmTCP As Form
>
> Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles MyBase.Load
>
> Const portNumber As Integer = 24601
>
> Dim PortListener As New TcpListener(portNumber)
>
> Dim tcpClient As New TcpClient
>
> Me.Show()
>
> 'Call ReverseGEOData(53.1, -2.1)
>
> Application.DoEvents()
>
> Try
>
> PortListener.Start()
>
> Catch ex As Exception
>
> MsgBox(ex.ToString)
>
> End Try
>
> Do
>
> Application.DoEvents()
>
> txtCONNLog.Text &= "Waiting for connection: " & Now() & vbCrLf
>
> Application.DoEvents()
>
> tcpClient = PortListener.AcceptTcpClient()
>
> Dim frmDATA As New frmPORTdata(tcpClient)
>
> tcpClient = Nothing
>
> Loop
>
>
>
> End Sub
>
> End Class
>
>
>
> Which as you can see sends the tcpClient off to another form each time the
> connection is made for the forn to deal with it.
>
> My form2 routine works fine in taking the connection and getting te data
> from it using more or less the same routine as before - just a basuic
> question I guess, is this sufficient to handle things the way I want them
> handled, with the possibility of being bombarded with connections all on
> the same port?
>
> Form2:
> Public Sub New(ByVal newParameter As TcpClient)
>
>
>
> ' This call is required by the Windows Form Designer.
>
> InitializeComponent()
>
> ' Add any initialization after the InitializeComponent() call.
>
> tcpClient = newParameter
>
> Dim sWORDS() As String
>
> Dim sIMEI As String
>
> Dim sMSG As String
>
>
>
> Dim I As Integer
>
> Dim dblLAT As Double
>
> Dim dblLONG As Double
>
> Dim dblBEARING As Double
>
> Dim singSPEED As Single
>
> Me.Show()
>
> Application.DoEvents()
>
> Try
>
> ' Get the stream
>
> Dim networkStream As NetworkStream = tcpClient.GetStream()
>
> ' Read the stream into a byte array
>
> Dim bytes(tcpClient.ReceiveBufferSize) As Byte
>
> Debug.Print("Receive buffer size = " & tcpClient.ReceiveBufferSize)
>
> networkStream.Read(bytes, 0, CInt(tcpClient.ReceiveBufferSize))
>
> ' Return the data received from the client to the console.
>
> Dim clientData As String = Encoding.ASCII.GetString(bytes)
>
> AddToFile (MyFile,clientData)
>
> Catch ex As Exception
>
> Console.WriteLine(ex.ToString)
>
> txtCONdata.Text &= ex.ToString & vbCrLf
>
> End Try
>
> Me.Dispose()
>
> End Sub
>
> Public Sub AddToFile(ByVal sFILENAME As String, ByVal sTEXT As String)
>
> Using sw As StreamWriter = New StreamWriter(sFILENAME, True)
>
> sw.WriteLine(sTEXT)
>
> sw.Close()
>
> End Using
>
> End Sub
>
> End Class
>
>
>
> "Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
> news:op.ui6lm2jn8jd0ej@petes-computer.local...
>> On Fri, 17 Oct 2008 08:55:58 -0700, Tym <spamtrap@ictis.net> wrote:
>>
>>> After programming in VB.Net for a couple of years now, I'm taking my
>>> first
>>> steps in TCP transfers
>>>
>>> I have a device which reports back to me via GRPS and thanks to Google
>>> I've
>>> managed to adapt a suitable port listener to I can grab the data.
>>>
>>> My quesiton is, whct if I've got 1000 of these things reporting back all
>>> on
>>> the same port number... how do I ensure that all the data gets captured
>>> from
>>> all units?
>>
>> That depends on whether you want to handle 1000 at a time, or 1000 in
>> sequence one at a time.
>>
>> If you just want to handle them one at a time, the main thing you need to
>> change is to loop back to the call to AcceptTcpClient() after you're done
>> reading from a client.
>>
>> If you want to handle all of the clients at the same time, you need to
>> separate the client connection accepting logic from the client receiving
>> logic. In the code you posted, you accept and receive data in the same
>> method. To handle multiple clients at once, you need to have one part of
>> the code that only deals with accepting clients. In that code, for each
>> client you'll need to hand off the created client connection to another
>> part of the code, which will deal with the actual communications with the
>> client.
>>
>> The part of the code that deals with the actual communications can be
>> written in a variety of ways, but the most appropriate approach in .NET
>> would be to use the asynchronous programming model. If you want to
>> continue using TcpClient, you can use the BeginRead() method on the
>> stream you get from the TcpClient. Alternatively, you can call
>> AcceptSocket() instead of AcceptTcpClient(), and on the Socket instance
>> call BeginReceive() or ReceiveAsync() (the latter has somewhat better
>> performance characteristics under certain conditions, but for only a 1000
>> clients, either is probably fine).
>>
>> By using the asynchronous programming model, you allow the framework to
>> manage the i/o threads, and you only have to code the callbacks to handle
>> the completion of i/o. You can start arbitrarily many i/o operations,
>> one at a time after each call to Accept...() returns, and then go right
>> back to calling the Accept...() method again. A different thread will be
>> used when the i/o operation actually completes.
>>
>> You can even handle the accept logic using the asynchronous programming
>> model, and in fact that would generally be my preference. But if you
>> only have the one server socket listening, that may be overkill.
>>
>> Pete
>
>


Peter Duniho

10/19/2008 7:27:00 PM

0

On Sun, 19 Oct 2008 11:33:28 -0700, Tym <spamtrap@ictis.net> wrote:

> I must admint - half of what you said went straight over my head! So I
> hit
> google and still none the wiser - yet!

Maybe study some more? :) Try to take on a small bit at a time. Don't
try to process all the information all at once. Look for one specific
statement or concept that doesn't make sense to you, and research that one
thing until it does make sense.

Network programming isn't itself fundamentally complicated, but there are
lots of little details that need to be right, and that's made even more
complicated if (as you've done here) you want to include network
programming with a GUI. Network i/o has a fundamental latency involved in
it, and GUI programming is not at all tolerant of latencies. Getting the
two to work together is non-trivial and you need to understand both very
well in order to make that blend work.

So my first advice would be: learn network i/o and GUI programming
independently of each other, and make sure you feel you've got at least a
good solid foundation in both before you try to do both together.

Note that part of getting a good foundation in network i/o is to learn how
to handle more than one connection at a time. Windows offers a number of
strategies for this, but in .NET the big three are: a new thread for each
connection; using the Socket.Select() method to monitor multiple Socket
instances in a single thread; or using the asynchronous programming model
(e.g. Socket.BeginReceive() or Stream.BeginRead()).

I strongly recommend the last of those three, the asynchronous programming
model. It is basically a multi-threaded solution, just as the first
approach is, so you will still need to get comfortable with the idea of
different code executing in different threads (GUI in one thread, network
i/o in others). But .NET will take care of managing the actual threads
for you, which not only simplifies things a bit, it allows for .NET to do
the network i/o in a more efficient way than if you were explicitly
creating a whole new thread for each connection.

So, part of learning the GUI fundamentals is to make sure you are
comfortable with the idea of using threads in conjunction with the GUI.

You can try to learn the fundamentals as you go along if you like, but I
think you're going to find it more frustrating.

As it happens, I've been trying to work on a sort of tutorial for this
kind of thing in my spare time. Unfortunately, spare time hasn't been
readily available recently and I've gotten side-tracked. I haven't yet
gotten to the part of the tutorial that would more directly address the
issues you're specifically asking about. However, there is at least what
I think is a good introduction that might at least fill in some of the
early gaps here. You might consider reading through it and see if it
helps flesh out some of the basic concepts for you.

The first article, of three so far, is here:
http://msmvps.com/blogs/duniho/archive/2008/08/19/basic-network-programming-i...

I do hope to resume work on the series in the near future, but I can't
make any promises.

> [...]
> Which as you can see sends the tcpClient off to another form each time
> the
> connection is made for the forn to deal with it.
>
> My form2 routine works fine in taking the connection and getting te data
> from it using more or less the same routine as before - just a basuic
> question I guess, is this sufficient to handle things the way I want them
> handled, with the possibility of being bombarded with connections all on
> the
> same port?

I assume that in your code, "Form2" is the same as "frmPORTdata"?

Unfortunately, the code you posted is pretty much entirely the wrong
approach. You are mixing your GUI code with your network i/o code, which
is not a good idea. Ideally, the network i/o code should exist in its own
class, but even if you put it in your form classes, the execution of that
code should not be done as part of the execution of GUI-related code (e.g.
Load event handler, constructor, etc.)

Three major issues:

-- You are calling Application.DoEvents() all over the place. This is
_always_ a sign of bad design. All of your GUI code should be designed so
that each method does exactly one small thing and returns quickly. If you
have more complex tasks to perform, those should be moved into a different
thread.

-- In your "Form2" class, you are disposing the form instance from
within the constructor, as well as calling Show() from the constructor.
Calling Show() would be a bad idea in any case -- not only does it take
control over the visibility of the new form out of the hands of the code
that actually created the instance, it exposes an incompletely-constructed
form instance which is a very bad thing -- but you're basically putting
the entire lifetime of the form instance into the constructor. By the
time the caller gets the reference back, the instance is dead.

-- You are creating a new form instance for each client. If you want,
as you have said, to handle 1000 clients simultaneously, this is just not
going to work well. Ignoring for the moment that the code as written
can't handle more than one client at a time anyway, even if you fixed that
issue you'd wind up having 1000 form instances visible all at the same
time. That's just not a practical thing to expect Windows to deal with
gracefully.

So, that's what's specifically wrong with the code.

I hope that I described adequately above what I think would be the _right_
way to do it, at least in broad terms. If you use the asynchronous
programming model, then every network i/o call you make can be done using
a "Begin...()" method, which you can safely call from GUI code. The
completion will either occur immediately, or later on a different thread.
Either way, the GUI won't get blocked and you won't have to call
Application.DoEvents().

And of course, creating a new form instance for each new connection is
just incorrect, at least for a situation where you expect to have 1000
simultaneous connections. You should encapsulate your connection-related
code in a non-form class, assuming you have it separate from your main
form class at all (which I think would be good).

Pete

Tym

10/20/2008 10:05:00 AM

0

Thanks Peter

I only adopted the GUI approach to try to see what was going on better with
each connection; the original that I gleaned from the web is a console app
and it may be better, as you saym to keep it in there.

I found this:
http://www.eggheadcafe.com/software/aspnet/30874323/tcp-listen-port-with...
with your guidance to someone else, but as it's in C#, and I'm a VBer, i'm
strugling a little, but will look at it in more detail.

I tried comverting it to VB with an online converter, but it throws up an
error in the
server.BeginAcceptTcpClient(AcceptCallback, server)

lines as the AcceptCallback is expecting a parameter. Ditto with
ReadCallback.

Imports System.Net.Sockets

Imports System.Text

Imports System

Imports System.IO

Imports System.Net

Public Class Form1

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)

Dim port As Int32 = 9007

Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")

Dim server As TcpListener = New TcpListener(localAddr, port)

server.Start()

' The above is pretty much what you had, cleaned up

' a bit. All you have to do at this point is start

' an accept operation:

server.BeginAcceptTcpClient(AcceptCallback, server) <== PROBLEM HERE

End Sub

Private Sub AcceptCallback(ByVal ar As IAsyncResult)

Dim server As TcpListener = CType(ar.AsyncState, TcpListener)

Dim state As ClientState = New ClientState()

' Once the accept operation completes, this callback will

' be called. In it, you can create a new TcpClient in much

' the same way you did it in the synchronous code you had:

state.client = server.EndAcceptTcpClient(ar)

' We're going to start reading from the client's stream, and

' we need a buffer for that:

state.buffer = New Byte(4096) {}

' Note that the TcpClient and the byte[] are both put into

' this "ClientState" object. We're going to need an easy

' way to get at those values in the callback for the read

' operation.

' Next, start a new accept operation so that we can process

' another client connection:

server.BeginAcceptTcpClient(AcceptCallback, server) <== PROBLEM HERE

' Finally, start a read operation on the client we just

' accepted. Note that you could do this before starting the

' accept operation; the order isn't really important.

state.client.GetStream().BeginRead(state.buffer, 0, state.buffer.Length,
ReadCallback, state) <== PROBLEM HERE

End Sub

Private Sub ReadCallback(ByVal ar As IAsyncResult)

Dim state As ClientState = CType(ar.AsyncState, ClientState)

Dim cbRead As Integer = state.client.GetStream().EndRead(ar)

If cbRead = 0 Then

' The client has closed the connection

Return

End If

' Your data is in state.buffer, and there are cbRead

' bytes to process in the buffer. This number may be

' anywhere from 1 up to the length of the buffer.

' The i/o completes when there is _any_ data to be read,

' not necessarily when the buffer is full.

' So, for example:

Dim strData As String = Encoding.ASCII.GetString(state.buffer, 0, cbRead)

' For ASCII you won't have to worry about partial characters

' but for pretty much any other common encoding you'll have to

' deal with that possibility, as there's no guarantee that an

' entire character will be transmitted in one piece.

' Of course, even with ASCII, you need to watch your string

' terminations. You'll have to either check the read buffer

' directly for a null terminator, or have some other means

' of detecting the actual end of a string. By the time the

' string goes through the decoding process, you'll have lost

' that information.

' As with the accept operation, we need to start a new read

' operation on this client, so that we can process the next

' bit of data that's sent:

state.client.GetStream().BeginRead(state.buffer, 0, state.buffer.Length,
ReadCallback, state) <== PROBLEM HERE

End Sub

'----------------------------------------------------------------

' Converted from C# to VB .NET using CSharpToVBConverter(1.2).

' Developed by: Kamal Patel (http://www.Kama...)

'----------------------------------------------------------------

End Class

As you say in the article - it may need a pinch of salt but i'd appreciate
guidance on where to sprinkle! :-)

I tried pasting it into a new VC# project and it threw even more problems at
me!


I'm happy to drop this back to a console app given your comments on latency.


Many thanks for your guidance so far, and I'm Googling on the
Stream.BeginRead()



Tym.


"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
news:op.ujadmhpd8jd0ej@petes-computer.local...
> On Sun, 19 Oct 2008 11:33:28 -0700, Tym <spamtrap@ictis.net> wrote:
>
>> I must admint - half of what you said went straight over my head! So I
>> hit
>> google and still none the wiser - yet!
>
> Maybe study some more? :) Try to take on a small bit at a time. Don't
> try to process all the information all at once. Look for one specific
> statement or concept that doesn't make sense to you, and research that one
> thing until it does make sense.
>
> Network programming isn't itself fundamentally complicated, but there are
> lots of little details that need to be right, and that's made even more
> complicated if (as you've done here) you want to include network
> programming with a GUI. Network i/o has a fundamental latency involved in
> it, and GUI programming is not at all tolerant of latencies. Getting the
> two to work together is non-trivial and you need to understand both very
> well in order to make that blend work.
>
> So my first advice would be: learn network i/o and GUI programming
> independently of each other, and make sure you feel you've got at least a
> good solid foundation in both before you try to do both together.
>
> Note that part of getting a good foundation in network i/o is to learn how
> to handle more than one connection at a time. Windows offers a number of
> strategies for this, but in .NET the big three are: a new thread for each
> connection; using the Socket.Select() method to monitor multiple Socket
> instances in a single thread; or using the asynchronous programming model
> (e.g. Socket.BeginReceive() or Stream.BeginRead()).
>
> I strongly recommend the last of those three, the asynchronous programming
> model. It is basically a multi-threaded solution, just as the first
> approach is, so you will still need to get comfortable with the idea of
> different code executing in different threads (GUI in one thread, network
> i/o in others). But .NET will take care of managing the actual threads
> for you, which not only simplifies things a bit, it allows for .NET to do
> the network i/o in a more efficient way than if you were explicitly
> creating a whole new thread for each connection.
>
> So, part of learning the GUI fundamentals is to make sure you are
> comfortable with the idea of using threads in conjunction with the GUI.
>
> You can try to learn the fundamentals as you go along if you like, but I
> think you're going to find it more frustrating.
>
> As it happens, I've been trying to work on a sort of tutorial for this
> kind of thing in my spare time. Unfortunately, spare time hasn't been
> readily available recently and I've gotten side-tracked. I haven't yet
> gotten to the part of the tutorial that would more directly address the
> issues you're specifically asking about. However, there is at least what
> I think is a good introduction that might at least fill in some of the
> early gaps here. You might consider reading through it and see if it
> helps flesh out some of the basic concepts for you.
>
> The first article, of three so far, is here:
> http://msmvps.com/blogs/duniho/archive/2008/08/19/basic-network-programming-i...
>
> I do hope to resume work on the series in the near future, but I can't
> make any promises.
>
>> [...]
>> Which as you can see sends the tcpClient off to another form each time
>> the
>> connection is made for the forn to deal with it.
>>
>> My form2 routine works fine in taking the connection and getting te data
>> from it using more or less the same routine as before - just a basuic
>> question I guess, is this sufficient to handle things the way I want them
>> handled, with the possibility of being bombarded with connections all on
>> the
>> same port?
>
> I assume that in your code, "Form2" is the same as "frmPORTdata"?
>
> Unfortunately, the code you posted is pretty much entirely the wrong
> approach. You are mixing your GUI code with your network i/o code, which
> is not a good idea. Ideally, the network i/o code should exist in its own
> class, but even if you put it in your form classes, the execution of that
> code should not be done as part of the execution of GUI-related code (e.g.
> Load event handler, constructor, etc.)
>
> Three major issues:
>
> -- You are calling Application.DoEvents() all over the place. This is
> _always_ a sign of bad design. All of your GUI code should be designed so
> that each method does exactly one small thing and returns quickly. If you
> have more complex tasks to perform, those should be moved into a different
> thread.
>
> -- In your "Form2" class, you are disposing the form instance from
> within the constructor, as well as calling Show() from the constructor.
> Calling Show() would be a bad idea in any case -- not only does it take
> control over the visibility of the new form out of the hands of the code
> that actually created the instance, it exposes an incompletely-constructed
> form instance which is a very bad thing -- but you're basically putting
> the entire lifetime of the form instance into the constructor. By the
> time the caller gets the reference back, the instance is dead.
>
> -- You are creating a new form instance for each client. If you want,
> as you have said, to handle 1000 clients simultaneously, this is just not
> going to work well. Ignoring for the moment that the code as written
> can't handle more than one client at a time anyway, even if you fixed that
> issue you'd wind up having 1000 form instances visible all at the same
> time. That's just not a practical thing to expect Windows to deal with
> gracefully.
>
> So, that's what's specifically wrong with the code.
>
> I hope that I described adequately above what I think would be the _right_
> way to do it, at least in broad terms. If you use the asynchronous
> programming model, then every network i/o call you make can be done using
> a "Begin...()" method, which you can safely call from GUI code. The
> completion will either occur immediately, or later on a different thread.
> Either way, the GUI won't get blocked and you won't have to call
> Application.DoEvents().
>
> And of course, creating a new form instance for each new connection is
> just incorrect, at least for a situation where you expect to have 1000
> simultaneous connections. You should encapsulate your connection-related
> code in a non-form class, assuming you have it separate from your main
> form class at all (which I think would be good).
>
> Pete


Peter Duniho

10/20/2008 8:08:00 PM

0

On Mon, 20 Oct 2008 03:05:05 -0700, Tym <spamtrap@ictis.net> wrote:

> [...]
> I tried comverting it to VB with an online converter, but it throws up
> an error in the
> server.BeginAcceptTcpClient(AcceptCallback, server)
>
> lines as the AcceptCallback is expecting a parameter. Ditto with
> ReadCallback.
>
> [...]
> I tried pasting it into a new VC# project and it threw even more
> problems at
> me!

I don't know why the C# project would generate _more_ errors. But, there
are three basic issues with the code you posted:

-- in VB, you have to explicitly use "AddressOf" with method
(Sub/Function) names for delegate types
-- the code you posted is for use in context of a Forms application
(thus the Form1_Load() method)
-- the code you posted doesn't include the ClientState class that the
example I posted in that thread had

The latter two problems would exist in either the VB.NET or C# version.
They can be resolved easily though. For example, you could put the
initialization code in the Main() method of a VB.NET console application
(though, the main reason the Form1_Load() method is likely to be a problem
is that it uses the EventArgs type, which is not likely to be valid if you
don't have a reference to System.Windows.Forms). And you can go ahead and
add the ClientState class as required by the sample code.

The first issue is easily fixed by putting "AddressOf " in front of each
method name for the Begin...() method calls that are causing problems.

Now, that said: all of these errors are things that I would expect an
experienced programmer to be able to resolve on their own. If you are
using VB.NET and aren't familiar with the syntax for creating delegate
instances, then that doesn't bode well for any use of code involving
delegates, and especially not code involving multiple threads. The error
for the missing ClientState type should be obvious enough as far as
fixing. And you should be able to recognize a valid VB.NET console app
versus code that's intended for a Forms application, and reconcile the two.

At the very least, you should commit to not just expecting for basic
compilation and implementation errors to be solved by someone else, but
rather to really _learning_ these things and using errors and mistakes as
an opportunity to learn something new.

It will certainly be harder and take longer in the short run for you to
try to solve those problems on your own, and you definitely should still
ask questions if you have spent some significant time trying to figure
things out and still can't. But you'll wind up having a much better
understanding of how these things work if you can figure the basic
compiler errors out yourself; they are a classic "learning more from
mistakes than from successes" situation, and you should take advantage of
that. And in the long run, that will make things go much more smoothly.

Pete

Tym

10/21/2008 5:40:00 PM

0

Thank you for your "lecture" - if i may explain my position on this then
perhaps your comments might not be as critical, and maybe a little more
contructive.

My programming experience thus far is single user windows applicaiton
database front end using DAO on VB6 and ADO on vb.net 2006. I have never
used threading or network i/o before so am looking at all the various
resources to learn the subject "on the go" so to speak.

I took your C# code and used the converter to VB to *understand the
structure* of what you had written - not to rip code off that works and
paste it into the application. The best way I have found to learn a new
subject like this is the same way I have learned most things - find
something that works and take it apart to find out HOW it works. Then build
your own with the knowledge.

My early unsophisticated programming was in TurboBasic under DOS, and
actually started trying windows programming under vb4 - having to deal with
object etc... completely threw me at first when it used to just run through
and quit!!

I've Googled Stream.BeginRead() to try from there I respected and listened
to your previous advice, and it was in this seach that I came upon your C#
code.

I'm trying to understand two new approaches simultaneaously, which in
hindsight is probably not a good idea - I suppose I'd better deal with
threading first? and then the Stream.BeginRead() issues?

I'm not after a fast solution, just a fast way of learning! :-)

"Peter Duniho" <NpOeStPeAdM@nnowslpianmk.com> wrote in message
news:op.ujb97ur98jd0ej@petes-computer.local...
> On Mon, 20 Oct 2008 03:05:05 -0700, Tym <spamtrap@ictis.net> wrote:
>
>> [...]
>> I tried comverting it to VB with an online converter, but it throws up
>> an error in the
>> server.BeginAcceptTcpClient(AcceptCallback, server)
>>
>> lines as the AcceptCallback is expecting a parameter. Ditto with
>> ReadCallback.
>>
>> [...]
>> I tried pasting it into a new VC# project and it threw even more
>> problems at
>> me!
>
> I don't know why the C# project would generate _more_ errors. But, there
> are three basic issues with the code you posted:
>
> -- in VB, you have to explicitly use "AddressOf" with method
> (Sub/Function) names for delegate types
> -- the code you posted is for use in context of a Forms application
> (thus the Form1_Load() method)
> -- the code you posted doesn't include the ClientState class that the
> example I posted in that thread had
>
> The latter two problems would exist in either the VB.NET or C# version.
> They can be resolved easily though. For example, you could put the
> initialization code in the Main() method of a VB.NET console application
> (though, the main reason the Form1_Load() method is likely to be a problem
> is that it uses the EventArgs type, which is not likely to be valid if you
> don't have a reference to System.Windows.Forms). And you can go ahead and
> add the ClientState class as required by the sample code.
>
> The first issue is easily fixed by putting "AddressOf " in front of each
> method name for the Begin...() method calls that are causing problems.
>
> Now, that said: all of these errors are things that I would expect an
> experienced programmer to be able to resolve on their own. If you are
> using VB.NET and aren't familiar with the syntax for creating delegate
> instances, then that doesn't bode well for any use of code involving
> delegates, and especially not code involving multiple threads. The error
> for the missing ClientState type should be obvious enough as far as
> fixing. And you should be able to recognize a valid VB.NET console app
> versus code that's intended for a Forms application, and reconcile the
> two.
>
> At the very least, you should commit to not just expecting for basic
> compilation and implementation errors to be solved by someone else, but
> rather to really _learning_ these things and using errors and mistakes as
> an opportunity to learn something new.
>
> It will certainly be harder and take longer in the short run for you to
> try to solve those problems on your own, and you definitely should still
> ask questions if you have spent some significant time trying to figure
> things out and still can't. But you'll wind up having a much better
> understanding of how these things work if you can figure the basic
> compiler errors out yourself; they are a classic "learning more from
> mistakes than from successes" situation, and you should take advantage of
> that. And in the long run, that will make things go much more smoothly.
>
> Pete


Peter Duniho

10/21/2008 6:07:00 PM

0

On Tue, 21 Oct 2008 10:40:16 -0700, Tym <spamtrap@ictis.net> wrote:

> Thank you for your "lecture" - if i may explain my position on this then
> perhaps your comments might not be as critical, and maybe a little more
> contructive.

My comments were intended as nothing but helpful. Any criticism was
entirely in a constructive manner, and your defensiveness is inappropriate.

I already explained what you'd need to change in order to get the VB.NET
code you posted to work, so I have nothing new to add at this point. I
already wrote that even if you insist on trying to dive in at the deep end
rather than starting with the fundamentals, I'm happy to answer questions
as best I can. I'm just trying to save you some grief and difficulty.

If you have some specific question you'd like answered, please freel free
to post it. There's no need to waste space in the newsgroup being
defensive about matter-of-fact comments.

Pete

Naked Gonad

11/24/2008 2:43:00 PM

0

Eli Grubman wrote:
> On Mon, 24 Nov 2008 13:07:24 +0000, Naked Gonad
> <bodron57@tiscali.co.uk> wrote:
>
>> Eli Grubman wrote:
>>> On Mon, 24 Nov 2008 11:51:28 +0000, Naked Gonad
>>> <bodron57@tiscali.co.uk> wrote:
>>>
>>>> Eli Grubman wrote:
>>>>> On Mon, 24 Nov 2008 09:35:45 +0000, Naked Gonad
>>>>> <bodron57@tiscali.co.uk> wrote:
>>>>>
>>>>>> Eli Grubman wrote:
>>>>>>> On Tue, 18 Nov 2008 09:45:05 +0000, Naked Gonad
>>>>>>> <bodron57@tiscali.co.uk> wrote:
>>>>>>>
>>>>>>>> Eli Grubman wrote:
>>>>>>>>> On Mon, 17 Nov 2008 18:34:14 -0000, "Peter Hucker" <none@spam.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> On Tue, 11 Nov 2008 07:27:15 -0000, Eli Grubman <eli.grubman@googlemail.com> wrote:
>>>>>>>>>>
>>>>>>>>>>> On Mon, 10 Nov 2008 18:19:26 -0000, "Peter Hucker" <none@spam.com>
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> On Sun, 02 Nov 2008 02:26:52 -0000, Eli Grubman <eli.grubman@googlemail.com> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> On Sat, 01 Nov 2008 16:42:52 -0000, "Peter Hucker" <none@spam.com>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Sat, 25 Oct 2008 14:43:01 +0100, Naked Gonad <bodron57@tiscali.co.uk> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Eli Grubman wrote:
>>>>>>>>>>>>>>>> On Sat, 25 Oct 2008 10:32:10 +0100, Naked Gonad
>>>>>>>>>>>>>>>> <bodron57@tiscali.co.uk> wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Peter Hucker wrote:
>>>>>>>>>>>>>>>>> Yuk!
>>>>>>>>>>>>>>>> Bell's??? Isn't that a "budget" brand?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Well he is Scottish!
>>>>>>>>>>>>>> It was payment for removing a computer virus. I usually drink cider.
>>>>>>>>>>>>> That's disgusting! How can you?
>>>>>>>>>>>> It's apple juice plus alcohol.
>>>>>>>>>>> It's fermented, i.e. rotted, apple juice. Alcohol isn't actually
>>>>>>>>>>> added.
>>>>>>>>>> I never said it was ADDED, I said it had it.
>>>>>>>>> Plus means addition. Minus means subtraction.
>>>>>>>>>
>>>>>>>>>> There is a difference between fermenting and rotting.
>>>>>>>>> First you rot, then you ferment!
>>>>>>>>>
>>>>>>>> This sounds like a lot of rot to me.
>>>>>>> Hubble bubble toil 'n trubble.
>>>>>>>
>>>>>> Toilet trouble?
>>>>> Bogrot?
>>>>>
>>>> No! it's the truth!
>>> The troof? What's that?
>>>
>> I'd be lying if I told you.
>
> I'd be lying if I said I believed you.
>
You just can't trust a truthful liar these days!