dcsimg
Results 1 to 4 of 4

Thread: How can I convert this console application to a windows forms application?

  1. #1

    Thread Starter
    New Member
    Join Date
    Aug 2018
    Posts
    3

    Question How can I convert this console application to a windows forms application?

    The following code is copied from the MSDN library. It is a socket example. My question is not a Network programming or socket question. Instead, I would like to transfer this example into a windows forms application. My interest is to create a user interface for it. My main problem is the listening loop. In a forms application, while loops can stop the application, so I would think to use Application.DoEvents, but I am not sure what the best way would be to do this. Since there is a Try/Catch in there also, I don't want to rewrite this and make it unstable. The overall goal would be to use a textbox for output. Is there a safe way to set this up. There is one more thing I have to consider. After I am able to set this up correctly, I would like to allow several clients to connect (A chat server), instead of just one. I want to make sure, that I can allow for this. So even thought that's not the question, please keep in mind that it is part of the goal (in case that makes a difference).

    Code:
    Imports System
    Imports System.IO
    Imports System.Net
    Imports System.Net.Sockets
    Imports System.Text
    Imports Microsoft.VisualBasic
    
    
    Class MyTcpListener
    
        Public Shared Sub Main()
    
        Dim server As TcpListener
        server=nothing
            Try
                ' Set the TcpListener on port 13000.
             Dim port As Int32 = 13000
             Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
    
             server = New TcpListener(localAddr, port)
    
             ' Start listening for client requests.
             server.Start()
    
             ' Buffer for reading data
                Dim bytes(1024) As Byte
                Dim data As String = Nothing
    
             ' Enter the listening loop.
             While True
                Console.Write("Waiting for a connection... ")
    
                ' Perform a blocking call to accept requests.
                ' You could also user server.AcceptSocket() here.
                Dim client As TcpClient = server.AcceptTcpClient()
                Console.WriteLine("Connected!")
    
                data = Nothing
    
                ' Get a stream object for reading and writing
                Dim stream As NetworkStream = client.GetStream()
    
                Dim i As Int32
    
                ' Loop to receive all the data sent by the client.
                i = stream.Read(bytes, 0, bytes.Length)
                While (i <> 0) 
                   ' Translate data bytes to a ASCII string.
                   data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
                        Console.WriteLine("Received: {0}", data)
    
                   ' Process the data sent by the client.
                   data = data.ToUpper()
                        Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
    
                   ' Send back a response.
                   stream.Write(msg, 0, msg.Length)
                        Console.WriteLine("Sent: {0}", data)
    
                   i = stream.Read(bytes, 0, bytes.Length)
    
                End While
    
                ' Shutdown and end connection
                client.Close()
             End While
          Catch e As SocketException
             Console.WriteLine("SocketException: {0}", e)
          Finally
             server.Stop()
          End Try
    
          Console.WriteLine(ControlChars.Cr + "Hit enter to continue....")
          Console.Read()
       End Sub 'Main
    
    End Class 'MyTcpListener 

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    4,636

    Re: How can I convert this console application to a windows forms application?

    Create a background thread and put the code there.
    I did a quick try with the following. I see it print out "Waiting for a connection... " in my Output window of the IDE.
    Didn't try to write a test case to connect and send something to it.
    If you don't see "Waiting for a connection..." print in the Output window of the IDE, check the Immediate Window.
    Code:
    Imports System.Threading
    Imports System.Net
    Imports System.Net.Sockets
    
    Public Class Form1
    
      Private tcpReceiverThread As New Thread(AddressOf tcpReceiver)
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        tcpReceiverThread.IsBackground = True
        tcpReceiverThread.Start()
      End Sub
    
      Private Sub tcpReceiver()
        Dim server As TcpListener
        server = Nothing
        Try
          ' Set the TcpListener on port 13000.
          Dim port As Int32 = 13000
          Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
    
          server = New TcpListener(localAddr, port)
    
          ' Start listening for client requests.
          server.Start()
    
          ' Buffer for reading data
          Dim bytes(1024) As Byte
          Dim data As String = Nothing
    
          ' Enter the listening loop.
          While True
            Console.Write("Waiting for a connection... ")
    
            ' Perform a blocking call to accept requests.
            ' You could also user server.AcceptSocket() here.
            Dim client As TcpClient = server.AcceptTcpClient()
            Console.WriteLine("Connected!")
    
            data = Nothing
    
            ' Get a stream object for reading and writing
            Dim stream As NetworkStream = client.GetStream()
    
            Dim i As Int32
    
            ' Loop to receive all the data sent by the client.
            i = stream.Read(bytes, 0, bytes.Length)
            While (i <> 0)
              ' Translate data bytes to a ASCII string.
              data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
              Console.WriteLine("Received: {0}", data)
    
              ' Process the data sent by the client.
              data = data.ToUpper()
              Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
    
              ' Send back a response.
              stream.Write(msg, 0, msg.Length)
              Console.WriteLine("Sent: {0}", data)
    
              i = stream.Read(bytes, 0, bytes.Length)
    
            End While
    
            ' Shutdown and end connection
            client.Close()
          End While
        Catch e As SocketException
          Console.WriteLine("SocketException: {0}", e)
        Finally
          server.Stop()
        End Try
    
      End Sub
    As for using a textbox, instead of Console.Write, you need to transfer the text from the background thread to the GUI thread, you can't write to the Textbox directly.
    But, they've made the indirect way fairly easy. You can use a concurrent queue to move text between the threads, but another simple alternative in this case would just to use a delegate. I'll make a quick change to the code to write to the textbox with a delegate, but it will still be untested until something is added to connect and send some data.

    The example may not be the best example, depending on how you want to communicate. All of my work with TCP has been a persistent connection between two devices, whereas the example is setup for a single connection, receive, response, and disconnect cycle. The sender would have to connect again after every transmission.
    But, my understanding is that is pretty much the way Web connections work. It is a continual series of connect, transfers, and disconnects.
    Last edited by passel; Aug 9th, 2018 at 10:47 AM.

  3. #3

    Thread Starter
    New Member
    Join Date
    Aug 2018
    Posts
    3

    Re: How can I convert this console application to a windows forms application?

    I looked into Threading and made this successfully. It is error prone though. If someone could perhaps help me clean it up so I dispose or close everything correctly. Or any other remarks are welcome

    This is the client
    Code:
    Imports System.Net
    Imports System.Net.Sockets
    
    
    Public Class Form1
        Dim myThread As System.Threading.Thread
    
    
        Dim server As String = "127.0.0.1"
        Dim Message As String = "This is a test sentence"
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            TextBox1.AppendText(vbCrLf & vbCrLf)
            myThread = New System.Threading.Thread(AddressOf Connecting)
            myThread.Start()
        End Sub
    
    
        Private Sub Connecting()
            Try
                ' Create a TcpClient.
                ' Note, for this client to work you need to have a TcpServer 
                ' connected to the same address as specified by the server, port
                ' combination.
                Dim port As Int32 = 13010
                Dim client As New TcpClient(server, port)
    
    
                ' Translate the passed message into ASCII and store it as a Byte array.
                Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(Message)
    
    
                ' Get a client stream for reading and writing.
                '  Stream stream = client.GetStream();
                Dim stream As NetworkStream = client.GetStream()
    
    
                ' Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length)
    
    
                TextBox1.AppendText("Sent: " & Message & vbCrLf)
    
    
                ' Receive the TcpServer.response.
                ' Buffer to store the response bytes.
                data = New [Byte](256) {}
    
    
                ' String to store the response ASCII representation.
                Dim responseData As [String] = [String].Empty
    
    
                ' Read the first batch of the TcpServer response bytes.
                Dim bytes As Int32 = stream.Read(data, 0, data.Length)
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
                TextBox1.AppendText("Received: " & responseData & vbCrLf)
    
    
                ' Close everything.
                stream.Close()
                client.Close()
            Catch e As ArgumentNullException
                TextBox1.AppendText("ArgumentNullException: " & e.Message)
            Catch e As SocketException
                TextBox1.AppendText("SocketException: " & e.Message)
            End Try
        End Sub 'Connect
    
    
        Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
    
    
        End Sub
    End Class
    This is the server

    Code:
    Imports System.Net
    Imports System.Net.Sockets
    
    
    Public Class Form1
        Dim myThread As New System.Threading.Thread(AddressOf Listening)
    
    
        Dim server As TcpListener
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
    
        End Sub
    
    
        Private Sub Listening()
    
    
            server = Nothing
            Try
                ' Set the TcpListener on port 13000.
                Dim port As Int32 = 13010
                Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
    
    
                server = New TcpListener(localAddr, port)
    
    
                ' Start listening for client requests.
                server.Start()
    
    
                ' Buffer for reading data
                Dim bytes(1024) As Byte
                Dim data As String = Nothing
    
    
                ' Enter the listening loop.
                While True
                    TextBox1.AppendText("Waiting for a connection... " & vbCrLf)
    
    
                    ' Perform a blocking call to accept requests.
                    ' You could also user server.AcceptSocket() here.
                    Dim client As TcpClient = server.AcceptTcpClient()
                    TextBox1.AppendText("Connected!" & vbCrLf)
    
    
                    data = Nothing
    
    
                    ' Get a stream object for reading and writing
                    Dim stream As NetworkStream = client.GetStream()
    
    
                    Dim i As Int32
    
    
                    ' Loop to receive all the data sent by the client.
                    i = stream.Read(bytes, 0, bytes.Length)
                    While (i <> 0)
                        ' Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
                        TextBox1.AppendText("Received: " & data & vbCrLf)
    
    
                        ' Process the data sent by the client.
                        data = data.ToUpper()
                        Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
    
    
                        ' Send back a response.
                        stream.Write(msg, 0, msg.Length)
                        TextBox1.AppendText("Sent: " & data & vbCrLf)
    
    
                        i = stream.Read(bytes, 0, bytes.Length)
    
    
                    End While
    
    
                    ' Shutdown and end connection
                    client.Close()
                End While
            Catch e As SocketException
                TextBox1.AppendText("SocketException: " & e.Message & vbCrLf)
            Finally
                server.Stop()
            End Try
        End Sub
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            myThread.Start()
        End Sub
    
    
        Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
            server.Stop()
        End Sub
    End Class

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    4,636

    Re: How can I convert this console application to a windows forms application?

    That code shouldn't work, as you are trying to access the textboxes from background threads. I edited my first response explaining that you need to use a method to move the text to the GUI thread in an indirect manner.

    I already modified the bit of code I posted in that response to use a delegate.
    I added a simple class, so that I could replace the Console.Write and Console.WriteLine with Write and WriteLine methods from the simple class. I only expect a string in the simple class, so had to wrap the formatted string parameters of the Console.Write calls in a String.Format function to convert the parameters to a string.

    I don't think I'll have time to play around with this any more right now, so I'll just post the updated example, which requires a multiLine enabled textbox. It prints the "Waiting for connection..." string in that textbox, so it looks like it should work (but I haven't tested it further).
    Code:
    Imports System.Threading
    Imports System.Net
    Imports System.Net.Sockets
    
    Public Class Form1
    
      Private tcpReceiverThread As New Thread(AddressOf tcpReceiver)
      Private txtOutput As TextOut
    
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        txtOutput = New TextOut(TextBox1)
    
        tcpReceiverThread.IsBackground = True
        tcpReceiverThread.Start()
      End Sub
    
      Private Sub tcpReceiver()
        Dim server As TcpListener
        server = Nothing
        Try
          ' Set the TcpListener on port 13000.
          Dim port As Int32 = 13000
          Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
    
          server = New TcpListener(localAddr, port)
    
          ' Start listening for client requests.
          server.Start()
    
          ' Buffer for reading data
          Dim bytes(1024) As Byte
          Dim data As String = Nothing
    
          ' Enter the listening loop.
          While True
            txtOutput.Write("Waiting for a connection... ")
    
            ' Perform a blocking call to accept requests.
            ' You could also user server.AcceptSocket() here.
            Dim client As TcpClient = server.AcceptTcpClient()
            txtOutput.WriteLine("Connected!")
    
            data = Nothing
    
            ' Get a stream object for reading and writing
            Dim stream As NetworkStream = client.GetStream()
    
            Dim i As Int32
    
            ' Loop to receive all the data sent by the client.
            i = stream.Read(bytes, 0, bytes.Length)
            While (i <> 0)
              ' Translate data bytes to a ASCII string.
              data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
              txtOutput.WriteLine(String.Format("Received: {0}", data))
    
              ' Process the data sent by the client.
              data = data.ToUpper()
              Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
    
              ' Send back a response.
              stream.Write(msg, 0, msg.Length)
              txtOutput.WriteLine(String.Format("Sent: {0}", data))
    
              i = stream.Read(bytes, 0, bytes.Length)
    
            End While
    
            ' Shutdown and end connection
            client.Close()
          End While
        Catch e As SocketException
          txtOutput.WriteLine(String.Format("SocketException: {0}", e))
        Finally
          server.Stop()
        End Try
    
      End Sub
    
      Private Class TextOut
        Private _txtBox As TextBox
    
        Public Sub New(txtBox As TextBox)
          _txtBox = txtBox
        End Sub
    
        Public Sub Write(s As String)
          _txtBox.Invoke(Sub() _txtBox.AppendText(s))
        End Sub
    
        Public Sub WriteLine(s As String)
          Write(s & vbNewLine)
        End Sub
      End Class

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width