i am creating application for communicate with screwdriver controllers thru TCP protocol. Main form dynamically creating new forms (each form = one screwdriver controller) which working fine, also create new connection after new form is loaded working fine. Problem is with receiving data and i am not sure how to share defined _client for each new form. How to address created _client into ReceiveDogaData function.If _client is just public variable then all communication is rewrited to the last know connection.
thx for any help
Private Sub NewDogaClient_load(sender As Object, e As EventArgs)
Dim _client As TcpClient
Try
_client = New TcpClient(Ip_lbl.Text, Port_lbl.Text)
CheckForIllegalCrossThreadCalls = False
Threading.ThreadPool.QueueUserWorkItem(AddressOf ReceiveDogaData)
Catch ex As Exception
MsgBox(ex.Message)
End Try
end sub
Private Sub ReceiveDogaData(state As Object)
Try
While True
Dim ns As NetworkStream = _client.GetStream()
TextBox1.Text = ""
Dim toReceive(100000) As Byte
ns.Read(toReceive, 0, toReceive.Length)
Dim txt As String = Encoding.ASCII.GetString(toReceive)
Dim recieveData As String
For i = 0 To 36 Step 2
recieveData = Hex(toReceive(i)) & Hex(toReceive(i + 1))
Dim response = CInt("&H" & recieveData)
TextBox1.Text = TextBox1.Text & ";" & recieveData
TextBox2.Text = TextBox1.Text
Next
End While
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Related
Here is my code:
'for clicking the datagridview
Private Sub DataGridView1_CellContentClick_1(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
Try
MySqlConnection.ConnectionString = "Server=localhost; User=root;Password='';Database=lrbhams;"
MySqlConnection.Open()
Dim state3 As String = "select boarder_fname, boarder_contact, guardian, guardian_number from boarders_info"
Dim command As New MySqlCommand(state3, MySqlConnection)
'command.Connection.Open()
command.ExecuteNonQuery()
MySqlConnection.Close()
If DataGridView1.Rows(e.RowIndex).Cells(2).Value Then
TextBox1.Text = DataGridView1.Rows(e.RowIndex).Cells(2).Value
ElseIf DataGridView1.Rows(e.RowIndex).Cells(4).Value Then
TextBox1.Text = DataGridView1.Rows(e.RowIndex).Cells(4).Value
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
''
End Sub
For sending message:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim message As String
'Dim reader As MySqlDataReader
message = RichTextBox1.Text
If send_sms.SerialPort.PortName = send_sms.portName Then
send_sms.SerialPort.Write("AT" & vbCrLf)
send_sms.SerialPort.Write("AT+CMGF=1" & vbCrLf)
send_sms.SerialPort.Write("AT+CMGS=" & Chr(34) & TextBox1.Text & Chr(34) & vbCrLf)
send_sms.SerialPort.Write(message & Chr(26))
MsgBox("Text Message Successfully Send !!!")
Try
Dim connectString As String
Dim conn As New MySqlConnection
Dim reader As MySqlDataReader
Dim command As MySqlCommand
'Dim mysqlQuery As String
connectString = "server=localhost;user=root;database=lrbhams"
conn = New MySqlConnection(connectString)
Dim query As String
conn.Open()
query = "INSERT into admin_log_attendance (action,contact_number, date) VALUES ('" & RichTextBox1.Text & "','" & TextBox1.Text & "', '" & Date.Today & "')"
command = New MySqlCommand(query, conn)
reader = Command.ExecuteReader
conn.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
MySqlConnection is a class in the MySql.Data.MySqlClient namespace. It is not a static class so it must be instantiated with the New keyword. You cannot set properties or call methods on the class itself. You must created an instance of the class. It is best practice to use `Using...End Using blocks for database objects. It will ensure that the database objects are closed and disposed even if there is an error.
A Select statement is not a NonQuery. Insert, Update and Delete statements can be run with command.ExecuteNonQuery but not Select. A Select query can be run with .ExecuteScalar if a single piece of data is expected or .ExecuteReader if several columns and/or rows are expected.
You can't just execute a Select command and expect something to happen. I suspect you want to display the data in your grid so let's fill a DataTable (an in memory representation of the records returned) with the .Load method then bind it to the DataGridView.
No need to close the connection because the Using block will close it.
If you call .ToString on a class that doesn't override the method you will just get the fully qualified name of the class. The Exception class provides a Property called Message which you can use.
The filling of the DataGridView will go in a separate method which you can call from Form.Load.
Now that there is data in the DataGridView you can click on it and the CellContentClick event will fire. I hope Cell(2) and Cell(4) Booleans because that is the only why your If statement will work. The necessity of the conversion code and .ToString will be obvious once you turn on Option Strict. (See my comment)
That's enough for now. With all this and Option Strict you should be able to fix the second part of your code.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
RetrieveRecordsForDataGridView()
End Sub
Private Sub RetrieveRecordsForDataGridView()
Dim dt As New DataTable
Try
Using cn As New MySqlConnection("Server=localhost; User=root;Password='';Database=lrbhams;")
Dim state3 As String = "select boarder_fname, boarder_contact, guardian, guardian_number from boarders_info"
Using command As New MySqlCommand(state3, cn)
cn.Open()
dt.Load(command.ExecuteReader())
End Using
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
If CBool(DataGridView1.Rows(e.RowIndex).Cells(2).Value) Then
TextBox1.Text = DataGridView1.Rows(e.RowIndex).Cells(2).Value.ToString
ElseIf CBool(DataGridView1.Rows(e.RowIndex).Cells(4).Value) Then
TextBox1.Text = DataGridView1.Rows(e.RowIndex).Cells(4).Value.ToString
End If
End Sub
I have created client and server application
i am trying to send the Arraylist from cilent to server
the Arraylist is transfer from client but how to use that Array list in server to get the information of ArrayList
while i am printing the message in server side it showing System.collection.ArrayList
below is my code
Client Code
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Try
Client = New TcpClient("192.168.0.226", 8080)
Dim Writer As New StreamWriter(Client.GetStream())
detailList.Add(txtname.Text)
detailList.Add(txtadd.Text)
For Each i As String In detailList
Console.WriteLine(i)
Next
Writer.Write(detailList)
' Writer.Write("</> " & txtaddress.Text & " <\>")
MsgBox("datas send ")
Writer.Flush()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Server Code
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
Dim message As String
Dim nStart As Integer
Dim nLast As Integer
If listener.Pending = True Then
message = ""
cline = listener.AcceptTcpClient()
Dim reder As New StreamReader(cline.GetStream)
While reder.Peek > -1
message &= Convert.ToChar(reder.Read()).ToString
End While
If message.Contains("</>") Then
nStart = InStr(message, "</>") + 10
nLast = InStr(message, "<\>")
message = Mid(message, nStart, nLast)
End If
Console.WriteLine(message)
txtname.Text = message
Label1.Text = message
' saveData()
End If
End Sub
Public Sub saveData()
Dim cmd As SqlCommand
sc.Open()
cmd = New SqlCommand("insert into demo values('" + txtname.Text + "')", sc)
cmd.ExecuteNonQuery()
msg = MsgBox("data save")
sc.Close()
End Sub
On this line in Button1_Click:
Writer.Write(detailList)
You're using the overloaded version of Write that takes an Object. In order to write out something meaningful for Objects, .NET has internally called detailList's ToString() method. The ToString() method here is what's returning the string "System.Collection.ArrayList".
So, you aren't sending an actual ArrayList implementation to your server, but simply its string representation (the result of calling ToString() on it).
In order to send objects over TCP, you will need to serialize it first, and then deserialize it on the server side. You could use any number of binary, XML, JSON, etc. formatters to do it, or write your own.
I am having a little issue with this socket chat, if I send little messages like "hello world" it works perfectly fine but if I try to send huge messages with about 10,000 characters it just crashes, i've been trying to fix this for the past 3 days with no luck, what should I be doing?
Server source:
Imports System.Text
Imports System.Net
Imports System.Net.Sockets
Enum Command
Login
'Log into the server
Logout
'Logout of the server
Message
'Send a text message to all the chat clients
List
'Get a list of users in the chat room from the server
Null
'No command
End Enum
Public Class Form1
'The ClientInfo structure holds the required information about every
'client connected to the server
Private Structure ClientInfo
Public socket As Socket
'Socket of the client
Public strName As String
'Name by which the user logged into the chat room
End Structure
'The collection of all clients logged into the room (an array of type ClientInfo)
Private clientList As ArrayList
'The main socket on which the server listens to the clients
Private serverSocket As Socket
Private byteData As Byte() = New Byte(1023) {}
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Try
clientList = New ArrayList()
'We are using TCP sockets
serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
'Assign the any IP of the machine and listen on port number 1000
Dim ipEndPoint As New IPEndPoint(IPAddress.Any, 2277)
'Bind and listen on the given address
serverSocket.Bind(ipEndPoint)
serverSocket.Listen(4)
'Accept the incoming clients
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
Catch ex As Exception
MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub
Private Sub OnAccept(ar As IAsyncResult)
Try
Dim clientSocket As Socket = serverSocket.EndAccept(ar)
'Start listening for more clients
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
'Once the client connects then start receiving the commands from her
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket)
Catch ex As Exception
MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub
Private Sub OnReceive(ar As IAsyncResult)
Try
Dim clientSocket As Socket = DirectCast(ar.AsyncState, Socket)
clientSocket.EndReceive(ar)
'Transform the array of bytes received from the user into an
'intelligent form of object Data
Dim msgReceived As New Data(byteData)
'We will send this object in response the users request
Dim msgToSend As New Data()
Dim message As Byte()
'If the message is to login, logout, or simple text message
'then when send to others the type of the message remains the same
msgToSend.cmdCommand = msgReceived.cmdCommand
msgToSend.strName = msgReceived.strName
Select Case msgReceived.cmdCommand
Case Command.Login
'When a user logs in to the server then we add her to our
'list of clients
Dim clientInfo As New ClientInfo()
clientInfo.socket = clientSocket
clientInfo.strName = msgReceived.strName
clientList.Add(clientInfo)
'Set the text of the message that we will broadcast to all users
msgToSend.strMessage = "<<<" & msgReceived.strName & " has joined the room>>>"
Exit Select
Case Command.Logout
'When a user wants to log out of the server then we search for her
'in the list of clients and close the corresponding connection
Dim nIndex As Integer = 0
For Each client As ClientInfo In clientList
If client.socket Is clientSocket Then
clientList.RemoveAt(nIndex)
Exit For
End If
nIndex += 1
Next
clientSocket.Close()
msgToSend.strMessage = "<<<" & msgReceived.strName & " has left the room>>>"
Exit Select
Case Command.Message
'Set the text of the message that we will broadcast to all users
msgToSend.strMessage = msgReceived.strName & ": " & msgReceived.strMessage
Exit Select
Case Command.List
'Send the names of all users in the chat room to the new user
msgToSend.cmdCommand = Command.List
msgToSend.strName = Nothing
msgToSend.strMessage = Nothing
'Collect the names of the user in the chat room
For Each client As ClientInfo In clientList
'To keep things simple we use asterisk as the marker to separate the user names
msgToSend.strMessage += client.strName & "*"
Next
message = msgToSend.ToByte()
'Send the name of the users in the chat room
clientSocket.BeginSend(message, 0, message.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), clientSocket)
Exit Select
End Select
If msgToSend.cmdCommand <> Command.List Then
'List messages are not broadcasted
message = msgToSend.ToByte()
For Each clientInfo As ClientInfo In clientList
If clientInfo.socket IsNot clientSocket OrElse msgToSend.cmdCommand <> Command.Login Then
'Send the message to all users
clientInfo.socket.BeginSend(message, 0, message.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), clientInfo.socket)
End If
Next
Debug.Print(msgToSend.strMessage)
End If
'If the user is logging out then we need not listen from her
If msgReceived.cmdCommand <> Command.Logout Then
'Start listening to the message send by the user
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket)
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub
Public Sub OnSend(ar As IAsyncResult)
Try
Dim client As Socket = DirectCast(ar.AsyncState, Socket)
client.EndSend(ar)
Catch ex As Exception
MessageBox.Show(ex.Message, "SGSserverTCP", MessageBoxButtons.OK, MessageBoxIcon.[Error])
End Try
End Sub
End Class
'The data structure by which the server and the client interact with
'each other
Class Data
Public strName As String
'Name by which the client logs into the room
Public strMessage As String
'Message text
Public cmdCommand As Command
'Command type (login, logout, send message, etcetera)
'Default constructor
Public Sub New()
cmdCommand = Command.Null
strMessage = Nothing
strName = Nothing
End Sub
'Converts the bytes into an object of type Data
Public Sub New(data__1 As Byte())
'The first four bytes are for the Command
cmdCommand = CType(BitConverter.ToInt32(data__1, 0), Command)
'The next four store the length of the name
Dim nameLen As Integer = BitConverter.ToInt32(data__1, 4)
'The next four store the length of the message
Dim msgLen As Integer = BitConverter.ToInt32(data__1, 8)
'This check makes sure that strName has been passed in the array of bytes
If nameLen > 0 Then
Me.strName = Encoding.UTF8.GetString(data__1, 12, nameLen)
Else
Me.strName = Nothing
End If
'This checks for a null message field
If msgLen > 0 Then
Me.strMessage = Encoding.UTF8.GetString(data__1, 12 + nameLen, msgLen)
Else
Me.strMessage = Nothing
End If
End Sub
'Converts the Data structure into an array of bytes
Public Function ToByte() As Byte()
Dim result As New List(Of Byte)()
'First four are for the Command
result.AddRange(BitConverter.GetBytes(CInt(cmdCommand)))
'Add the length of the name
If strName IsNot Nothing Then
result.AddRange(BitConverter.GetBytes(strName.Length))
Else
result.AddRange(BitConverter.GetBytes(0))
End If
'Length of the message
If strMessage IsNot Nothing Then
result.AddRange(BitConverter.GetBytes(strMessage.Length))
Else
result.AddRange(BitConverter.GetBytes(0))
End If
'Add the name
If strName IsNot Nothing Then
result.AddRange(Encoding.UTF8.GetBytes(strName))
End If
'And, lastly we add the message text to our array of bytes
If strMessage IsNot Nothing Then
result.AddRange(Encoding.UTF8.GetBytes(strMessage))
End If
Return result.ToArray()
End Function
End Class
Client source:
Enum Command
Login '0 Log into the server
Logout '1 Logout of the server
Message '2 Send a text message to all the chat clients
List '3 Get a list of users in the chat room from the server
Null '4 No command
End Enum
Public Class frmMain
Public clientSocket As System.Net.Sockets.Socket
'The main client socket
Public strName As String
'Name by which the user logs into the room
Private byteData As Byte() = New Byte(1023) {}
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Call StartChat()
End Sub
Private Sub StartChat()
clientSocket = New System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp)
Dim ipAddress As System.Net.IPAddress = System.Net.IPAddress.Parse("127.0.0.1")
Dim ipEndPoint As New System.Net.IPEndPoint(ipAddress, 2277)
clientSocket.BeginConnect(ipEndPoint, New AsyncCallback(AddressOf OnLoginConnect), Nothing)
End Sub
Private Sub OnLoginConnect(ar As IAsyncResult)
clientSocket.EndConnect(ar)
'We are connected so we login into the server
Dim msgToSend As New Data()
msgToSend.cmdCommand = Command.Login
msgToSend.strName = txtUser.Text
msgToSend.strMessage = Nothing
Dim b As Byte() = msgToSend.ToByte()
'Send the message to the server
clientSocket.BeginSend(b, 0, b.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnLoginSend), Nothing)
End Sub
Private Sub OnLoginSend(ar As IAsyncResult)
clientSocket.EndSend(ar)
strName = txtUser.Text
Call LoggedIn()
End Sub
'***************
Private Sub LoggedIn()
'The user has logged into the system so we now request the server to send
'the names of all users who are in the chat room
Dim msgToSend As New Data()
msgToSend.cmdCommand = Command.List
msgToSend.strName = strName
msgToSend.strMessage = Nothing
byteData = msgToSend.ToByte()
clientSocket.BeginSend(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnSend), Nothing)
byteData = New Byte(1023) {}
'Start listening to the data asynchronously
clientSocket.BeginReceive(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing)
End Sub
'Broadcast the message typed by the user to everyone
Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
'Fill the info for the message to be send
Dim msgToSend As New Data()
'.ToString("M/d/yyyy h:mm:ss tt")
msgToSend.strName = "[" & Date.Now.ToString("h:mm:ss tt") & "] <" & strName & ">"
msgToSend.strMessage = txtMessage.Text
msgToSend.cmdCommand = Command.Message
Dim byteData As Byte() = msgToSend.ToByte()
'Send it to the server
clientSocket.BeginSend(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnSend), Nothing)
txtMessage.Text = Nothing
End Sub
Private Sub OnSend(ar As IAsyncResult)
clientSocket.EndSend(ar)
End Sub
Private Sub OnReceive(ar As IAsyncResult)
'clientSocket.EndReceive(ar)
Dim bytesReceived As Long = clientSocket.EndReceive(ar)
If (bytesReceived > 0) Then
Me.Invoke(New iThreadSafe(AddressOf iThreadSafeFinish), New Object() {byteData})
End If
byteData = New Byte(1023) {}
clientSocket.BeginReceive(byteData, 0, byteData.Length, System.Net.Sockets.SocketFlags.None, New AsyncCallback(AddressOf OnReceive), Nothing)
End Sub
Private Delegate Sub iThreadSafe(ByVal ibyteData As Byte())
Private Sub iThreadSafeFinish(ByVal ibyteData As Byte())
Dim msgReceived As New Data(ibyteData)
'Accordingly process the message received
Debug.Print(msgReceived.cmdCommand)
Select Case msgReceived.cmdCommand
Case 0 'login
lstChatters.Items.Add(msgReceived.strName)
Exit Select
Case 1 'log out
lstChatters.Items.Remove(msgReceived.strName)
Exit Select
Case 2 'msg
Exit Select
Case 3 'List
lstChatters.Items.AddRange(msgReceived.strMessage.Split("*"c))
lstChatters.Items.RemoveAt(lstChatters.Items.Count - 1)
txtChatBox.Text += "<<<" & strName & " has joined the room>>>" & vbCr & vbLf
Exit Select
End Select
If msgReceived.strMessage IsNot Nothing AndAlso msgReceived.cmdCommand <> Command.List Then
txtChatBox.Text += msgReceived.strMessage & vbCr & vbLf
End If
End Sub
Private Sub txtMessage_TextChanged(sender As Object, e As KeyEventArgs) Handles txtMessage.KeyDown
If e.KeyCode = Keys.Enter Then
btnSend_Click(sender, Nothing)
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
strName = txtUser.Text
End Sub
End Class
'The data structure by which the server and the client interact with
'each other
Class Data
Public strName As String
'Name by which the client logs into the room
Public strMessage As String
'Message text
Public cmdCommand As Command
'Command type (login, logout, send message, etcetera)
'Default constructor
Public Sub New()
cmdCommand = Command.Null
strMessage = Nothing
strName = Nothing
End Sub
'Converts the bytes into an object of type Data
Public Sub New(data__1 As Byte())
'The first four bytes are for the Command
cmdCommand = CType(BitConverter.ToInt32(data__1, 0), Command)
'The next four store the length of the name
Dim nameLen As Integer = BitConverter.ToInt32(data__1, 4)
'The next four store the length of the message
Dim msgLen As Integer = BitConverter.ToInt32(data__1, 8)
'This check makes sure that strName has been passed in the array of bytes
If nameLen > 0 Then
strName = System.Text.Encoding.UTF8.GetString(data__1, 12, nameLen)
Else
strName = Nothing
End If
'This checks for a null message field
If msgLen > 0 Then
strMessage = System.Text.Encoding.UTF8.GetString(data__1, 12 + nameLen, msgLen)
Else
strMessage = Nothing
End If
End Sub
'Converts the Data structure into an array of bytes
Public Function ToByte() As Byte()
Dim result As New List(Of Byte)()
'First four are for the Command
result.AddRange(BitConverter.GetBytes(CInt(cmdCommand)))
'Add the length of the name
If strName IsNot Nothing Then
result.AddRange(BitConverter.GetBytes(strName.Length))
Else
result.AddRange(BitConverter.GetBytes(0))
End If
'Length of the message
If strMessage IsNot Nothing Then
result.AddRange(BitConverter.GetBytes(strMessage.Length))
Else
result.AddRange(BitConverter.GetBytes(0))
End If
'Add the name
If strName IsNot Nothing Then
result.AddRange(System.Text.Encoding.UTF8.GetBytes(strName))
End If
'And, lastly we add the message text to our array of bytes
If strMessage IsNot Nothing Then
result.AddRange(System.Text.Encoding.UTF8.GetBytes(strMessage))
End If
Return result.ToArray()
End Function
End Class
You are assuming that you will receive an entire message at a time. TCP does not guarantee to preserve the chunks that you wrote. Use the return value bytesReceived to determine how many bytes are actually in the buffer.
Your code must be able to deal with the possibility of receiving all outstanding data one byte at a time.
So I've finally got this to almost work but now every few times I test the process the form and the progressbar freeze. I'm also sure there are much more efficient ways of doing this so any constructive criticism would be greatly appreciated.
This is the coding for one page of a program that allows the user to click one button to download and install one application and then press the next button to download and install a different application:
Imports System.Net.WebRequestMethods
Public Class Software
'Open link in external browser
Public Sub HandleRequestNavigate(ByVal sender As Object, ByVal e As RequestNavigateEventArgs)
Process.Start(New ProcessStartInfo(e.Uri.AbsoluteUri))
e.Handled = True
End Sub
'Declarations
Shared progressamc As New Progress
Shared progresscti As New ProgressCTI
WithEvents startcti As New Process
WithEvents startamc As New Process
WithEvents startsfstb As New Process
WithEvents amcworker As New ComponentModel.BackgroundWorker
WithEvents ctiworker As New ComponentModel.BackgroundWorker
Dim ProgressBarAMC As Object = Progress.ProgressBar1
Dim blprgrsAMC As Object = Progress.blprgrs
Dim ProgressBarCTI As Object = progresscti.ProgressBar1
Dim blprgrsCTI As Object = progresscti.blprgrs
'FTP Values
Const host As String = "ftp://10.167.16.80/"
Const username As String = "anonymous"
Const password As String = ""
'AMC File Put/Get
Const localfileamc As String = "C:\AMC.exe"
Const Remotefileamc As String = "Bin/AMC.exe"
'CTI File Put/Get
Const localfilecti As String = "C:\CTI.exe"
Const Remotefilecti As String = "Bin/CTI.exe"
'On Init
Public Sub New()
InitializeComponent()
amcworker.WorkerReportsProgress = True
amcworker.WorkerSupportsCancellation = True
ctiworker.WorkerReportsProgress = True
ctiworker.WorkerSupportsCancellation = True
End Sub
'Install AMC Button
Private Sub ButtonAMC(sender As Object, e As RoutedEventArgs)
Dim butt1 As Button = DirectCast(sender, Button)
butt1.IsEnabled = False
Dispatcher.BeginInvoke(New Action(AddressOf progressamc_Show))
AddHandler Progress.Cancel_Click, AddressOf myProcessamc_Exited
amcworker.RunWorkerAsync()
End Sub
'Open Dialog
Private Sub progressamc_Show()
Try
progressamc.ShowDialog()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
End Try
End Sub
'FTP - Download
Private Sub ftpseshamc_DoWork(ByVal sender As System.Object, ByVal e As ComponentModel.DoWorkEventArgs) Handles amcworker.DoWork
Dim URI As String = host & Remotefileamc
Dim FTP As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest)
'Set the credentials
FTP.Credentials = New System.Net.NetworkCredential(username, password)
'FTP Options
FTP.KeepAlive = False
FTP.UseBinary = True
'Define the action as Download
FTP.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
'Get the response to the Ftp request and the associated stream
Try
Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse)
Dim Length As Long = response.ContentLength
Dim StopWatch As New Stopwatch
Dim CurrentSpeed As Double = Nothing
Using responseStream As IO.Stream = response.GetResponseStream
'loop to read & write to file
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
StopWatch.Start()
amcworker.ReportProgress(CShort(count / Length * 100 + 0.5))
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
StopWatch.Stop()
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
myProcessamc_Exited()
End Try
Installamc()
End Sub
'Starts the installation
Sub Installamc()
startamc.StartInfo.FileName = "C:\AMC.exe"
startamc.EnableRaisingEvents = True
Try
startamc.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Dispatcher.Invoke(New Action(AddressOf Progressamc_Hide))
End Sub
'Hide Dialog during install
Private Sub Progressamc_Hide()
progressamc.Hide()
End Sub
'Report progress
Private Sub amcworker_ProgressChanged(ByVal sender As System.Object, ByVal e As ComponentModel.ProgressChangedEventArgs) Handles amcworker.ProgressChanged
ProgressBarAMC.value = e.ProgressPercentage
blprgrsAMC.Content = "Downloading: " & e.ProgressPercentage & "%"
End Sub
End Class
Again, any help would be greatly appreciated.
Edit: I've made the following edit to the code but I'm not entirely sure it's doing what I think it's doing. Basically what I intended is for the ReportProgress to only run once every 2047 bytes read.
'Get the response to the Ftp request and the associated stream
Try
Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse)
Dim Length As Long = response.ContentLength
Dim StopWatch As New Stopwatch
Dim CurrentSpeed As Double = Nothing
Using responseStream As IO.Stream = response.GetResponseStream
'loop to read & write to file
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
Dim chunk As Integer = Int(2047 / Length)
Dim cycle As Integer = chunk = count
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
StopWatch.Start()
If cycle = True Then
amcworker.ReportProgress(CShort(count / Length * 100 + 0.5))
Else
End
End If
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
StopWatch.Stop()
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
myProcessamc_Exited()
End Try
I didn't scrutinize the code carefully, but I don't see why you're using stopwatch, so I took out the references. I'm not sure what starting it multiple times inside the loop and ending it outside would do anyway.
The use of the word END in the second example will comletely end your app! Pretty sure that's what you want there.
Try this modification of your first code. The key is only updating if change is >= 5%:
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
dim LastPct as Short = -5
dim Pct as Short = 0
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
Pct = CShort(count / Length * 100 + 0.5)
if Pct>= (LastPct + 5)
amcworker.ReportProgress(Pct)
LastPCT= Pct
EndIf
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
amcworker.ReportProgress(100)
responseStream.Close()
fs.Flush()
fs.Close()
End Using
I am looking for help with writing a server application to serve an updating text stream to clients. My requirements are as follows:
I need to be able to have a client request information on server port 7878 and receive back an initial set of values, the changed values would then be reported every 5 seconds. The hanging point for me has been connecting another client. I need to be able to connect a 2nd (or 3rd or 4th) client while the first is still running. The second client would receive the initial values and then begin updating as well. I need the two streams to be completely independent of each other. Is this possible with VB.Net and TCP sockets?
Edit to add: I have pasted some of my code below of what I can share. WriteLog is a separate sub that isn't really relevant to my problem. This code will allow for a client to connect and then allow for another client to connect, but all transmissions to the 1st client stop on a new connection.
Public Class ServerApp
Dim serverSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim clientSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Private Sub ServerApp_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
WriteLog(String.Format("Start of form load.."))
Dim listener As New Thread(New ThreadStart(AddressOf ListenForRequests))
listener.IsBackground = True
listener.Start()
End Sub
Private Sub ListenForRequests()
Dim CONNECT_QUEUE_LENGTH As Integer = 4
serverSocket.Bind(New IPEndPoint(IPAddress.Any, 7878))
serverSocket.Listen(CONNECT_QUEUE_LENGTH)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
End Sub
Private Sub OnAccept(ByVal ar As IAsyncResult)
clientSocket = serverSocket.EndAccept(ar)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
WriteLog("just accepted new client")
Try
clientSocket.Send(Encoding.UTF8.GetBytes("first response on connect"), SocketFlags.None)
While True
clientSocket.Send(Encoding.UTF8.GetBytes("string of updates"), SocketFlags.None)
Thread.Sleep(5000)
End While
Catch ex As Exception
WriteLog(ex.Message)
WriteLog("Remote host has disconnected")
End Try
End Sub
End Class
I recommend trying out the UdpClient class, i find it easier to use and understand.
Now for some code...
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text
Imports System.Net
Public Class Form1
Private port As Integer = 7878
Private Const broadcastAddress As String = "255.255.255.255"
Private receivingClient As UdpClient
Private sendingClient As UdpClient
Private myTextStream As String = "Blah blah blah"
Private busy As Boolean = False
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
InitializeSender()
InitializeReceiver()
End Sub
Private Sub InitializeSender()
Try
sendingClient = New UdpClient(broadcastAddress, port)
sendingClient.EnableBroadcast = True
Catch ex As Exception
MsgBox("Error, unable to setup sender client on port " & port & "." & vbNewLine & vbNewLine & ex.ToString)
End Try
End Sub
Private Sub InitializeReceiver()
Try
receivingClient = New UdpClient(port)
ThreadPool.QueueUserWorkItem(AddressOf Receiver)
Catch ex As Exception
MsgBox("Error, unable to setup receiver on port " & port & "." & vbNewLine & vbNewLine & ex.ToString)
End
End Try
End Sub
Private Sub sendStream()
busy = True
Dim i% = 0
Do While i < 4
If myTextStream <> "" Then
Dim data() As Byte = Encoding.ASCII.GetBytes(myTextStream)
Try
sendingClient.Send(data, data.Length)
Catch ex As Exception
MsgBox("Error, unable to send stream." & vbNewLine & vbNewLine & ex.ToString)
End
End Try
End If
Thread.Sleep(5000)
i += 1
Loop
busy = False
End Sub
Private Sub Receiver()
Dim endPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, port)
While True
Dim data() As Byte
data = receivingClient.Receive(endPoint)
Dim incomingMessage As String = Encoding.ASCII.GetString(data)
If incomingMessage = "what ever the client is requesting, for example," & "GET_VALUES" Then
If busy = False Then Call sendStream()
End If
End While
End Sub
End Class
A few links that may help: Here,
here,
here and
here.