由于某种原因,我开发的这段代码在使用无线网络时随机失败(我似乎无法在局域网上重现问题)。似乎是在即将传输新文件时,服务器不会发送任何字节。
客户端
Option Explicit Off
Imports System.Net.Sockets
Imports System.Net
Imports System.Threading
Imports System.IO
Imports NetFwTypeLib
Public Class UpdateReleaseForm
Public IP As String
Dim CheckNetworkThread As Thread
Dim SendItClient As TcpClient
Dim netStream As NetworkStream
Dim NumberOfBytes As ULong
Dim SumOfAllBytes As ULong = 0
Dim TotalNumberOfBytes As ULong
Dim NumberOfBytesInThisSecond As Integer = 0
Dim AllNew As Boolean
Dim DownloadFile As Boolean
Public UpgradeTo As String
Declare Sub Sleep Lib "Kernel32.dll" (ByVal ms As Short)
Dim netStreamn As NetworkStream
Dim writer As BinaryWriter
Dim SendItClientn As TcpClient
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles YesButton.Click
If YesButton.Text = "Yes" Or YesButton.Text = "Resume" Then
DownloadFile = True
Try
SendItClient = New TcpClient
SendItClient.Connect(IP, 8001)
netStream = SendItClient.GetStream
Catch ex As System.Net.Sockets.SocketException
MessageBox.Show("Could not establish a connection with server. Please try again later.", "Notification", MessageBoxButtons.OK)
Exit Sub
End Try
If Directory.Exists("C:\Results\") = False Then
Directory.CreateDirectory("C:\Results\")
End If
If Directory.Exists("C:\Results\Updates") = False Then
Directory.CreateDirectory("C:\Results\Updates\")
End If
If Directory.Exists("C:\Results\Updates\" & UpgradeTo) = False Then
Directory.CreateDirectory("C:\Results\Updates\" & UpgradeTo)
AllNew = True
Else
AllNew = False
End If
Dim ProcessIt As New Thread(AddressOf Process)
ProcessIt.IsBackground = True
ProcessIt.Start()
Dim BytesPerSecondThread As New Thread(AddressOf BytesPerSecond)
BytesPerSecondThread.IsBackground = True
BytesPerSecondThread.Start()
NoButton.Enabled = False
YesButton.Enabled = False
Else
DownloadFile = False
writer.Close()
netStreamn.Close()
SendItClientn.Close()
YesButton.Text = "Resume"
NoButton.Enabled = True
End If
End Sub
Private Sub Process()
Dim valid As Boolean = True
Dim number As Integer 'number of packet
Dim FilePath As String
Dim portN As ULong
Dim buff2(0) As Byte
Dim TimeItThread As New Thread(AddressOf TimeIt)
While valid = True
Dim buffer(65000 - 1) As Byte
Dim bytesRead As Integer = netStream.Read(buffer, 0, buffer.Length)
number = BitConverter.ToInt64(buffer, 0)
NumberOfBytes = number
TotalNumberOfBytes = BitConverter.ToUInt64(buffer, 8)
UpdateProgressBarMax(ProgressBar1, TotalNumberOfBytes)
portN = BitConverter.ToInt64(buffer, 16)
FilePath = System.Text.Encoding.ASCII.GetString(buffer, 25, buffer(24)) 'filename
If My.Computer.FileSystem.FileExists("C:\Results\Updates\" & UpgradeTo & FilePath) = False Then
Directory.CreateDirectory(Path.GetDirectoryName("C:\Results\Updates\" & UpgradeTo & FilePath))
End If
GetFile(FilePath, portN)
If DownloadFile = False Then
Exit Sub
End If
If TotalNumberOfBytes = SumOfAllBytes Then
Exit While
End If
End While
ChangeText(Label2, "Download Completed")
UpdateProgressBarValue(ProgressBar1, SumOfAllBytes)
'EnableControl(YesButton, True)
'EnableControl(NoButton, True)
Dim myProcess As New Process()
Try
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.FileName = "C:\Results\Updates\" & UpgradeTo & "\Setup.exe"
myProcess.StartInfo.CreateNoWindow = True
myProcess.Start()
Catch ex As Exception
MessageBox.Show("Error updating", "Warning")
CloseThisForm()
Exit Sub
End Try
Do While True
If myProcess.HasExited = True Then
CloseThisForm()
Exit Sub
End If
Sleep(50)
Loop
End Sub
Private Sub TimeIt()
Dim initial As DateTime
Dim PrevBytes As ULong
Dim bps As ULong
initial = Now
PrevBytes = 0
While TotalNumberOfBytes <> SumOfAllBytes
If DateDiff(DateInterval.Second, initial, Now) >= 0 Then
initial = Now
bps = SumOfAllBytes - PrevBytes
PrevBytes = SumOfAllBytes
ChangeText(Label3, bps)
End If
End While
End Sub
Private Sub GetFile(ByVal filep As String, ByVal PortNum As Integer)
' Dim Buffer(1026 - 1) As Byte
Dim Buffer(10024 - 1) As Byte
Dim count As Integer = 0
Dim buff2(0) As Byte
Dim bytesReadSum As ULong = 0
Dim NumberAlready As ULong
Dim holdit(0) As Byte
SendItClientn = New TcpClient
Try
SendItClientn.Connect(IP, PortNum)
Catch ex As Exception
'failure to connect when either server or network drops out
MessageBox.Show("Something went wrong there", "Warning")
DownloadFile = False
Exit Sub
End Try
netStreamn = SendItClientn.GetStream
If File.Exists("C:\Results\Updates\" & UpgradeTo & filep) Then
Dim fstm As Stream = New FileStream("C:\Results\Updates\" & UpgradeTo & filep, FileMode.Open, FileAccess.Read)
NumberAlready = fstm.Length()
fstm.Close()
writer = New BinaryWriter(System.IO.File.Open("C:\Results\Updates\" & UpgradeTo & filep, FileMode.Append))
Else
NumberAlready = 0
writer = New BinaryWriter(System.IO.File.Open("C:\Results\Updates\" & UpgradeTo & filep, FileMode.Create))
End If
Dim NumberAlreadyBytes() As Byte = BitConverter.GetBytes(NumberAlready)
netStream.Write(NumberAlreadyBytes, 0, NumberAlreadyBytes.Length)
bytesReadSum = NumberAlready
SumOfAllBytes += NumberAlready
If NumberOfBytes = NumberAlready Then
netStream.Write(buff2, 0, buff2.Length)
writer.Close()
Exit Sub
End If
Do While True
If DownloadFile = False Then
TotalNumberOfBytes = 0
SumOfAllBytes = 0
writer.Close()
SendItClient.Close()
netStreamn.Close()
Exit Sub
End If
Dim bytesRead As ULong
'ReDim Buffer(10024 - 1)
'Dim Buffer(10026 - 1)
'ReDim Buffer(1026 - 1)
ReDim Buffer(10024 - 1)
Try
bytesRead = netStreamn.Read(Buffer, 0, Buffer.Length)
Catch ex As Exception
MessageBox.Show("Something went wrong there. Software will now close.", "Warning")
End
End Try
bytesReadSum += bytesRead
SumOfAllBytes += bytesRead
NumberOfBytesInThisSecond = NumberOfBytesInThisSecond + bytesRead
UpdateProgressBarValue(ProgressBar1, SumOfAllBytes)
ChangeText(Label2, CInt(SumOfAllBytes / TotalNumberOfBytes * 100) & "% downloaded")
ReDim Preserve Buffer(bytesRead - 1)
Try
writer.Write(Buffer)
Catch ex As Exception
MessageBox.Show("Something went wrong there. Software will now close.", "Warning")
End
'Exit Sub
End Try
If bytesReadSum >= NumberOfBytes Then
Exit Do
End If
If bytesRead = 0 Then
MessageBox.Show("Something went wrong there. Software will now close.", "Warning")
End
End If
count += 1
Loop
netStream.Write(buff2, 0, buff2.Length)
buff2(0) = 1
writer.Close()
End Sub
Private Sub UpdateReleaseForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub Closing() Handles Me.FormClosing
Try
DownloadFile = False
netStreamn.Close()
SendItClient.Close()
Catch ex As Exception
End Try
End Sub
Delegate Sub UpdateProgressBarValueDelegate(ByVal progressB As ProgressBar, ByVal value As Integer)
Public Sub UpdateProgressBarValue(ByVal progressB As ProgressBar, ByVal value As Integer)
'If not on main thread then
If progressB.InvokeRequired Then
progressB.Invoke(New UpdateProgressBarValueDelegate(AddressOf UpdateProgressBarValue), New Object() {progressB, value})
Return
End If
progressB.Value = value
progressB.Update()
End Sub
Delegate Sub UpdateProgressBarMaxDelegate(ByVal progressB As ProgressBar, ByVal max As Integer)
Public Sub UpdateProgressBarMax(ByVal progressB As ProgressBar, ByVal max As Integer)
'If not on main thread then
If progressB.InvokeRequired Then
progressB.Invoke(New UpdateProgressBarMaxDelegate(AddressOf UpdateProgressBarMax), New Object() {progressB, max})
Return
End If
progressB.Maximum = max
progressB.Update()
End Sub
Delegate Sub CloseThisFormDelegate()
Public Sub CloseThisForm()
'If not on main thread then
If Me.InvokeRequired Then
Me.Invoke(New CloseThisFormDelegate(AddressOf CloseThisForm), New Object() {})
Return
End If
Me.Close()
End Sub
Private Sub BytesPerSecond()
While DownloadFile
NumberOfBytesInThisSecond = 0
Sleep(1000)
'ChangeText(Label3, NumberOfBytesInThisSecond / (1024 * 1024) & "MB/s")
If NumberOfBytesInThisSecond < 1024 Then
ChangeText(Label3, "Downloaded " & " @ " & NumberOfBytesInThisSecond & "B/s")
ElseIf NumberOfBytesInThisSecond < 1024 * 1024 Then
ChangeText(Label3, "Downloaded " & " @ " & Math.Round(NumberOfBytesInThisSecond / 1024, 2) & "KB/s")
Else
ChangeText(Label3, "Downloaded " & " @ " & Math.Round(NumberOfBytesInThisSecond / (1024 * 1024), 2) & "MB/s")
End If
' ChangeText(Label3, "Currently downloading")
End While
End Sub
Private Sub NoButton_Click(sender As Object, e As EventArgs) Handles NoButton.Click
Me.Close()
End Sub
End Class
服务器代码
Public Class ClientDownloadManage
Dim ClientToManage As TcpClient
Dim ClientManageThread As Thread
Dim NumberOfBytes As ULong = 0
Dim PortNumber As ULong
Dim NetStream As NetworkStream
Dim IntInd As Integer
Dim ContinueSend As Boolean = True
Public Sub New(ByVal ClientInst As TcpClient, ByVal IndPass As Integer)
ClientToManage = ClientInst
PortNumber = MyPorts.LicPorts.Ports(IndPass).PortNumber
IntInd = IndPass
ClientManageThread = New Thread(AddressOf Start_It)
ClientManageThread.Name = "Communicating"
ClientManageThread.IsBackground = True
NetStream = ClientToManage.GetStream
ClientManageThread.Start()
End Sub
Private Sub Start_It()
GetBytes("C:\HoldIt")
SendEachFileInDir("C:\HoldIt", "C:\HoldIt")
MyPorts.LicPorts.Ports(IntInd).Available = True
End Sub
Private Sub SendEachFileInDir(ByVal path As String, ByVal path1 As String)
Dim buff2(0) As Byte
For Each foundfile As String In My.Computer.FileSystem.GetFiles(path)
If ContinueSend = False Then
Exit Sub
End If
Dim fstm As Stream = New FileStream(foundfile, FileMode.Open, FileAccess.Read)
Dim buffer(65000 - 1) As Byte
Dim size As ULong 'number of bytes
size = fstm.Length
Dim ByteSize() As Byte = BitConverter.GetBytes(size)
Dim ByteTotalNumber() As Byte = BitConverter.GetBytes(NumberOfBytes)
Dim PortNumberBytes() As Byte = BitConverter.GetBytes(PortNumber)
Dim filenamebytes() As Byte = System.Text.Encoding.ASCII.GetBytes(Mid(foundfile, path1.Length + 1))
Dim SendBytes(UBound(ByteSize) + UBound(filenamebytes) + UBound(ByteTotalNumber) + UBound(PortNumberBytes) + 4) As Byte
Dim count As Integer = 0
For i = 0 To UBound(ByteSize)
SendBytes(count) = ByteSize(i)
count += 1
Next
For i = 0 To UBound(ByteTotalNumber)
SendBytes(count) = ByteTotalNumber(i)
count += 1
Next
For i = 0 To UBound(PortNumberBytes)
SendBytes(count) = PortNumberBytes(i)
count += 1
Next
SendBytes(count) = filenamebytes.Length
count += 1
For i = 0 To UBound(filenamebytes)
SendBytes(count) = filenamebytes(i)
count += 1
Next
SendFile(foundfile, fstm, PortNumber, NetStream, SendBytes)
fstm.Close()
Next
If ContinueSend = False Then
Exit Sub
End If
If My.Computer.FileSystem.GetDirectories(path).Count > 0 Then
For Each Dir As String In My.Computer.FileSystem.GetDirectories(path)
SendEachFileInDir(Dir, path1)
Next
End If
End Sub
Private Sub GetBytes(ByVal path As String)
For Each foundfile As String In My.Computer.FileSystem.GetFiles(path)
Dim pstm As Stream = New FileStream(foundfile, FileMode.Open, FileAccess.Read)
NumberOfBytes += pstm.Length
pstm.Close()
Next
If My.Computer.FileSystem.GetDirectories(path).Count > 0 Then
For Each Dir As String In My.Computer.FileSystem.GetDirectories(path)
GetBytes(Dir)
Next
End If
End Sub
Private Sub SendFile(ByVal foundfile As String, ByVal fstm As FileStream, ByVal PortNumber As Integer, ByVal NetStream As NetworkStream, ByVal SendBytes() As Byte)
Dim count As Integer = 0
'Dim SendFileClient As New TcpClient
'Dim netsStream As NetworkStream
Dim Buffer(10024 - 1) As Byte
Dim buff2(0) As Byte
Dim AlreadyReceivedBytes(7) As Byte
Dim AlreadyReceived As ULong
Dim bytesreadsum As ULong = 0
Dim workStream As NetworkStream
Dim ServerInst As TcpListener
Try
ServerInst = New TcpListener(PortNumber)
ServerInst.Start()
Dim ClientInst As TcpClient
NetStream.Write(SendBytes, 0, SendBytes.Length)
ClientInst = ServerInst.AcceptTcpClient
'MyPorts.LicPorts.Ports(IntInd).client = ClientInst
workStream = ClientInst.GetStream
NetStream.Read(AlreadyReceivedBytes, 0, 8)
AlreadyReceived = BitConverter.ToInt64(AlreadyReceivedBytes, 0)
If AlreadyReceived <> 0 Then
fstm.Position = AlreadyReceived
End If
Do While True
'ReDim Buffer(10024 - 1)
ReDim Buffer(1024 - 1)
Dim bytesRead As Integer = fstm.Read(Buffer, 0, Buffer.Length)
Dim CountIt As Integer = 0
If bytesRead = 0 Then
Exit Do
End If
bytesreadsum += bytesRead
ReDim Preserve Buffer(bytesRead - 1)
workStream.Write(Buffer, 0, Buffer.Length)
count += 1
Loop
NetStream.Read(buff2, 0, buff2.Length)
ServerInst.Stop()
Catch ex As System.IO.IOException
'client stopped downloading
ContinueSend = False
ServerInst.Stop()
MyPorts.LicPorts.Ports(IntInd).Available = True
Exit Sub
End Try
End Sub
End Class
Public Structure Port
Dim PortNumber As Integer
Dim Available As Boolean
End Structure
Public Structure Ports
Dim Ports() As Port
End Structure
Public Structure LicensePorts
Dim LicPorts As Ports
End Structure
Public Sub processForDownload()
Dim ServerInst As New TcpListener(8001)
Dim ClientInst As TcpClient
Dim count As Integer = 0
Dim PortNumber
ServerInst.Start()
While True
count += 1
ClientInst = ServerInst.AcceptTcpClient
PortNumber = FindValidPort()
If PortNumber >= 0 Then
MyPorts.LicPorts.Ports(PortNumber).Available = False
Dim Client_new As New ClientDownloadManage(ClientInst, PortNumber)
Else
ClientInst.Close()
End If
End While
End Sub