Client.vb 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407
  1. Imports System.Threading
  2. Imports System.Net
  3. Imports System.Net.Sockets
  4. Imports System.IO
  5. Imports System.Collections.Concurrent
  6. Imports System.Reflection
  7. Imports System.Runtime.InteropServices
  8. Imports System.Diagnostics
  9. Imports System.Collections.Generic
  10. Public Class Client
  11. Public errMsg As String
  12. ' Define the delegate type
  13. Public Delegate Sub ClientCallbackDelegate(ByVal bytes() As Byte, ByVal dataChannel As Byte)
  14. ' Create Delegate pointer
  15. Public ClientCallbackObject As ClientCallbackDelegate
  16. Private continue_running As Boolean = False
  17. Private bytes() As Byte
  18. Private blockSize As UInt16
  19. Private IP As System.Net.IPAddress
  20. Private Port As Integer
  21. Private localAddr As IPAddress
  22. Private Client As TcpClient
  23. Private Stream As NetworkStream
  24. Private fileWriter As AsyncUnbuffWriter
  25. Private fileReader As FileStream
  26. Private FileBeingSentPath As String
  27. Private weHaveThePuck As Boolean = False
  28. Private isRunning As Boolean = False
  29. Private UserBytesToBeSentAvailable As Boolean = False
  30. Private UserBytesToBeSent As New MemoryStream
  31. Private UserOutputChannel As Byte
  32. Private SystemBytesToBeSentAvailable As Boolean = False
  33. Private SystemBytesToBeSent() As Byte
  34. Private SystemOutputChannel As Byte
  35. Private SendingFile As Boolean = False
  36. Private ReceivingFile As Boolean = False
  37. Private IncomingFileName As String
  38. Private IncomingFileSize As Int64 = 0
  39. Private outgoingFileSize As UInt64 = 0
  40. Private outgoingFileName As String
  41. Private fileBytesRecieved As Int64 = 0
  42. Private filebytesSent As Int64 = 0
  43. Private bytesSentThisSecond As Int32 = 0
  44. Private bytesReceivedThisSecond As Int32 = 0
  45. Private mbpsOneSecondAverage() As Int32
  46. Private ReceivedFilesFolder As String = System.Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory) & "\ReceivedFiles"
  47. Private userName As String
  48. Private password As String
  49. Private machineId As String
  50. Private mbpsSyncObject As New AutoResetEvent(False)
  51. Private sendQueue As ConcurrentQueue(Of message)
  52. Private messageIn As MessageInQueue
  53. Private shuttingDown As Boolean
  54. Private reconnectMonitorDetails As New ReconnectData
  55. Private silentShutdown As Boolean = False
  56. Private connectionAccepted As Boolean = False
  57. Private connectionRejected = False
  58. Private disConnectComplete As Boolean
  59. Private Class ReconnectData
  60. Public ReconnectDuration As TimeSpan
  61. Public attemptTimeStamp As Date
  62. Public Reconnecting As Boolean
  63. Public ReconnectOnDisconnection
  64. Public ipAddress As String
  65. Public port As Int16
  66. Public machineId As String
  67. End Class
  68. Private Sub ReconnectMonitor()
  69. Dim reconnectDots As Int16 = 0
  70. Dim attemptMessage As String = "Attempting to reconnect"
  71. If continue_running = False then Exit Sub
  72. If Not connectionAccepted Then Exit Sub
  73. reconnectMonitorDetails.Reconnecting = True
  74. reconnectMonitorDetails.attemptTimeStamp = Now
  75. SystemMessage(attemptMessage)
  76. While Not Connect(reconnectMonitorDetails.ipAddress, reconnectMonitorDetails.port, reconnectMonitorDetails.machineId, "")
  77. If continue_running = False Then Exit While
  78. Thread.Sleep(1000)
  79. If Now > reconnectMonitorDetails.attemptTimeStamp.Add(reconnectMonitorDetails.ReconnectDuration) then Exit While
  80. If continue_running = False then Exit Sub
  81. attemptMessage += "."
  82. reconnectDots += 1
  83. If reconnectDots > 3 then
  84. reconnectDots = 0
  85. attemptMessage = "Attempting to reconnect"
  86. End If
  87. SystemMessage(attemptMessage)
  88. End While
  89. reconnectMonitorDetails.Reconnecting = False
  90. If isRunning = False then
  91. continue_running = False
  92. If Not silentShutdown Then SystemMessage("Disconnected.")
  93. End If
  94. End Sub
  95. Private Class message
  96. Public bytes() As Byte
  97. Public dataChannel As Byte
  98. End Class
  99. Private class MessageInQueue
  100. Public queue As New ConcurrentQueue(Of message)
  101. Private bgThread As New Threading.Thread(AddressOf Pump)
  102. Private running As Boolean
  103. Private callBack As ClientCallbackDelegate
  104. Public Sub New(ByRef _callBack As ClientCallbackDelegate)
  105. callBack = _callBack
  106. running = True
  107. bgThread.Start()
  108. End Sub
  109. Public Sub Close()
  110. running = False
  111. End Sub
  112. Private Sub Pump()
  113. Dim msg As message = Nothing
  114. While running
  115. If queue.Count > 0 then
  116. If queue.TryDequeue(msg) Then
  117. callBack(msg.bytes, msg.dataChannel)
  118. End If
  119. End If
  120. If queue.Count = 0 then Thread.Sleep(2)
  121. End While
  122. End Sub
  123. End Class
  124. Public Function isClientRunning() As Boolean
  125. Return isRunning
  126. End Function
  127. Public Sub SetReceivedFilesFolder(ByVal _path As String)
  128. ReceivedFilesFolder = _path
  129. End Sub
  130. Public Function GetIncomingFileName() As String
  131. Return IncomingFileName
  132. End Function
  133. Public Function GetOutgoingFileName() As String
  134. Return outgoingFileName
  135. End Function
  136. Public Function GetPercentOfFileReceived() As UInt16
  137. If ReceivingFile Then
  138. Return CUShort((fileBytesRecieved / IncomingFileSize) * 100)
  139. Else
  140. Return 0
  141. End If
  142. End Function
  143. Public Function GetPercentOfFileSent() As UInt16
  144. If SendingFile Then
  145. Return CUShort((filebytesSent / outgoingFileSize) * 100)
  146. Else
  147. Return 0
  148. End If
  149. End Function
  150. Public Function GetMbps() As String
  151. Dim currentMbps As Decimal = CalculateMbps(True)
  152. If currentMbps > 1000000 Then
  153. Return (currentMbps / 1000000).ToString("N2") & " Mbps"
  154. Else
  155. Return (currentMbps / 1000).ToString("N2") & " Kbps"
  156. End If
  157. End Function
  158. Public Function GetLocalIpAddress() As System.Net.IPAddress
  159. Dim strHostName As String
  160. Dim addresses() As System.Net.IPAddress
  161. strHostName = System.Net.Dns.GetHostName()
  162. addresses = System.Net.Dns.GetHostAddresses(strHostName)
  163. ' Find an IpV4 address
  164. For Each address As System.Net.IPAddress In addresses
  165. ' Return the first IpV4 IP Address we find in the list.
  166. If address.AddressFamily = AddressFamily.InterNetwork Then
  167. Return address
  168. End If
  169. Next
  170. ' No IpV4 address? Return the loopback address.
  171. Return System.Net.IPAddress.Loopback
  172. End Function
  173. Private Function GetIPFromHostname(ByVal hostname As String, Optional returnLoopbackOnFail As Boolean = True) As System.Net.IPAddress
  174. Dim addresses() As System.Net.IPAddress
  175. Try
  176. addresses = System.Net.Dns.GetHostAddresses(hostname)
  177. Catch ex As Exception
  178. If Not returnLoopbackOnFail Then Return Nothing
  179. Return System.Net.IPAddress.Loopback
  180. End Try
  181. ' Find an IpV4 address
  182. For Each address As System.Net.IPAddress In addresses
  183. ' Return the first IpV4 IP Address we find in the list.
  184. If address.AddressFamily = AddressFamily.InterNetwork Then
  185. Return address
  186. End If
  187. Next
  188. ' No IpV4 address? Return the loopback address.
  189. If returnLoopbackOnFail Then Return System.Net.IPAddress.Loopback
  190. Return Nothing
  191. End Function
  192. ''' <summary>
  193. ''' Starting a new client requires a callback sub, and optional reconnection cryteria.
  194. ''' </summary>
  195. ''' <param name="callbackMethod"></param>
  196. ''' <param name="ReconnectOnDisconnection">Clients started whith ReconnectOnDisconnection = True will continue to attempt to reconnect for the time specifyed in ReconnectionDurationSeconds.</param>
  197. ''' <param name="ReconnectionDurationSeconds">The number of seconds to attempt to reconnect to the server in the event that connection is lost.</param>
  198. ''' <remarks></remarks>
  199. Public Sub New(ByVal callbackMethod As ClientCallbackDelegate, Optional ByVal ReconnectOnDisconnection As Boolean = False, Optional ReconnectionDurationSeconds As Int32 = 15)
  200. blockSize = 10000
  201. ' Initialize the delegate variable to point to the user's callback method.
  202. ClientCallbackObject = callbackMethod
  203. ' Reconnect code here:
  204. reconnectMonitorDetails.ReconnectOnDisconnection = ReconnectOnDisconnection
  205. reconnectMonitorDetails.ReconnectDuration = New TimeSpan(0, 0, 0, ReconnectionDurationSeconds)
  206. End Sub
  207. Public Function Connect(ByVal IP_Address As String, ByVal prt As Integer, Optional newMachineID As String = "", _
  208. Optional ByRef errorMessage As String = "") As Boolean
  209. If isRunning then
  210. errorMessage = "The client is already connected.'
  211. Return False
  212. End If
  213. connectionAccepted = False
  214. connectionRejected = False
  215. disConnectComplete = False
  216. Try
  217. ' Attempt to get the ip address by parsing the IP_Address string:
  218. IP = System.Net.IPAddress.Parse(IP_Address)
  219. Catch ex As Exception
  220. ' We got an error - it's not an ip address.
  221. ' Maybe it's a hostname.
  222. IP = GetIPFromHostname(IP_Address, False)
  223. End Try
  224. If IP Is Nothing Then
  225. ' Handle invalid IP address passed here.
  226. errorMessage = "Could not connect to " & IP_Address & ". It is not a valid IP address or hostname on this network."
  227. Return False
  228. End If
  229. Port = prt
  230. continue_running = True
  231. errMsg = ""
  232. shuttingDown = False
  233. sendQueue = New ConcurrentQueue(Of message)
  234. messageIn = New MessageInQueue(ClientCallbackObject)
  235. Dim clientCommunicationThread As New Thread(AddressOf Run)
  236. clientCommunicationThread.Name = "ClientCommunication"
  237. clientCommunicationThread.Start()
  238. SetMachineID(newMachineID)
  239. ' Wait for connection...
  240. While isRunning = False And errMsg = ""
  241. Thread.Sleep(5)
  242. End While
  243. ' Are we connected?
  244. errorMessage = errMsg
  245. If isRunning = False Then
  246. messageIn.Close
  247. Return False
  248. Else
  249. While connectionAccepted = False
  250. Thread.Sleep(1)
  251. If connectionRejected = True then
  252. errorMessage = errMsg
  253. Return False
  254. End If
  255. If isRunning = False then
  256. errorMessage = errMsg
  257. messageIn.Close
  258. Return False
  259. End If
  260. End While
  261. End If
  262. Return True
  263. End Function
  264. ''' <summary>
  265. ''' Closes the TCP connection.
  266. ''' </summary>
  267. ''' <param name="shutDownSilently">Prevents all system messages from being passed to your callback
  268. ''' (including the disconnected notification) and retruns control quickly while the client shuts
  269. ''' down in the background.</param>
  270. ''' <remarks></remarks>
  271. Public Sub Close(Optional ByVal shutDownSilently As Boolean = False)
  272. silentShutdown = shutDownSilently
  273. shuttingDown = True
  274. ' If we're not running at all...
  275. If isRunning = False then
  276. continue_running = False
  277. If Not silentShutdown Then SystemMessage("Disconnected.")
  278. Exit Sub
  279. End If
  280. If messageIn isnot Nothing then messageIn.Close()
  281. If shutDownSilently = True then
  282. Dim bgClose As New Thread(AddressOf FinishClosing)
  283. bgClose.Start()
  284. Return
  285. End If
  286. FinishClosing()
  287. End Sub
  288. Private Sub FinishClosing()
  289. Dim timeout As Date = Now.AddSeconds(3)
  290. Try
  291. While (sendQueue.Count > 0) Or (UserBytesToBeSentAvailable = True)
  292. Thread.Sleep(5)
  293. If Now > timeout Then Exit While
  294. End While
  295. Catch ex As Exception
  296. ' sendQueue is nothing... not interested in this error.
  297. End Try
  298. continue_running = False
  299. While disConnectComplete = False
  300. Thread.Sleep(5)
  301. If Now > timeout then Exit While
  302. End While
  303. End Sub
  304. Private Sub DoInternalClose()
  305. Thread.Sleep(250)
  306. Close()
  307. End Sub
  308. Private Sub InternalClose()
  309. Dim bgClose As New Thread(AddressOf DoInternalClose)
  310. bgClose.Start()
  311. End Sub
  312. Public Function GetBlocksize() As UInt16
  313. Return blockSize
  314. End Function
  315. ''' <summary>
  316. ''' Returns the size of the sendqueue. Returns -1 if isRunning = False.
  317. ''' CAUTION: Calling this function too often will result in decreased performance, and failing to call it at all may result
  318. ''' in an out of memory error. You can continue to add messages to the send queue for as long as the connection is active
  319. ''' (isRunning = True), but that doesn't mean they are being sent as fast as you are adding them to the queue (or at all, for that matter).
  320. ''' </summary>
  321. ''' <returns>An Int32</returns>
  322. ''' <remarks></remarks>
  323. Public Function GetSendQueueSize() As Int32
  324. Dim sendQueueSize As Int32 = -1
  325. If isRunning then GetSendQueueSize = sendQueue.Count
  326. Return sendQueueSize
  327. End Function
  328. Public Sub GetFile(ByVal _path As String)
  329. sendQueue.Enqueue(New message With { _
  330. .bytes = Utilities.StrToByteArray("GFR:" & _path),
  331. .dataChannel = 254
  332. })
  333. End Sub
  334. Public Function SendFile(ByVal _path As String, Optional ByRef errMsg As String = "") As Boolean
  335. If shuttingDown then
  336. errMsg = "The client is shutting down. Outgoing files will not be sent."
  337. Return False
  338. End If
  339. sendQueue.Enqueue(New message With { _
  340. .bytes = Utilities.StrToByteArray("SFR:" & _path),
  341. .dataChannel = 254
  342. })
  343. Return True
  344. End Function
  345. Public Sub CancelIncomingFileTransfer()
  346. sendQueue.Enqueue(New message With { _
  347. .bytes = Utilities.StrToByteArray("Abort->"),
  348. .dataChannel = 254
  349. })
  350. FinishReceivingTheFile()
  351. Dim killFileThread As New System.Threading.Thread(AddressOf KillIncomingFile)
  352. killFileThread.Start(ReceivedFilesFolder & "\" & IncomingFileName)
  353. End Sub
  354. Private Sub KillIncomingFile(_path as Object)
  355. Dim filePath As String = CType(_path, String)
  356. Dim timeOut As New Stopwatch
  357. timeOut.Start()
  358. While timeOut.ElapsedMilliseconds < 1000
  359. Try
  360. If Not File.Exists(filePath) then Exit While
  361. File.Delete(filePath)
  362. Catch ex As Exception
  363. End Try
  364. End While
  365. End Sub
  366. Public Sub CancelOutgoingFileTransfer()
  367. sendQueue.Enqueue(New message With { _
  368. .bytes = Utilities.StrToByteArray("Abort<-"),
  369. .dataChannel = 254
  370. })
  371. StopSendingTheFile()
  372. End Sub
  373. Public Sub SetMachineID(ByVal id As String)
  374. machineId = id
  375. If id = "" then id = " "
  376. sendQueue.Enqueue(New message With { _
  377. .bytes = Utilities.StrToByteArray("MachineID:" & id),
  378. .dataChannel = 254
  379. })
  380. End Sub
  381. Public Function GetMachineID() As String
  382. Return machineId
  383. End Function
  384. Public Function GetErrorMessage() As String
  385. Return errMsg
  386. End Function
  387. Public Function SendBytes(ByVal bytes() As Byte, Optional ByVal channel As Byte = 1, Optional ByRef errMsg As String = "") As Boolean
  388. If shuttingDown then
  389. errMsg = "This client is shutting down. Bytes can not be sent."
  390. Return False
  391. End If
  392. If channel = 0 Or channel > 250 Then
  393. errMsg = "Data can not be sent using channel numbers less then 1 or greater then 250."
  394. Return False
  395. End If
  396. If bytes is Nothing or bytes.Length = 0 then
  397. errMsg = "bytes() must contain more then 0 bytes, and not be nothing."
  398. Return False
  399. End If
  400. If shuttingDown then
  401. errMsg = "The client is shutting down. Outgoing messages will not be accepted."
  402. Return False
  403. End If
  404. sendQueue.Enqueue(New message With { _
  405. .bytes = bytes,
  406. .dataChannel = channel
  407. })
  408. Return True
  409. End Function
  410. Public Function SendBytes(ByRef bytes() As Byte, ByVal offset As Int32, ByVal count As Int32, Optional ByVal channel As Byte = 1, Optional ByRef errMsg As String = "") As Boolean
  411. If shuttingDown then
  412. errMsg = "This client is shutting down. Bytes can not be sent."
  413. Return False
  414. End If
  415. If channel = 0 Or channel > 250 Then
  416. errMsg = "Data can not be sent using channel numbers less then 1 or greater then 250."
  417. Return False
  418. End If
  419. If bytes is Nothing or bytes.Length = 0 then
  420. errMsg = "bytes() must contain more then 0 bytes, and not be nothing."
  421. Return False
  422. End If
  423. If shuttingDown then
  424. errMsg = "The client is shutting down. Outgoing messages will not be accepted."
  425. Return False
  426. End If
  427. Dim msg As New message()
  428. ReDim msg.bytes(count - 1)
  429. Buffer.BlockCopy(bytes, offset, msg.bytes, 0, count)
  430. msg.dataChannel = channel
  431. sendQueue.Enqueue(msg)
  432. Return True
  433. End Function
  434. Public Function SendBytes(ByRef streamBytes As MemoryStream, Optional ByVal channel As Byte = 1, Optional ByRef errMsg As String = "") As Boolean
  435. If shuttingDown then
  436. errMsg = "This client is shutting down. Bytes can not be sent."
  437. Return False
  438. End If
  439. If channel = 0 Or channel > 250 Then
  440. errMsg = "Data can not be sent using channel numbers less then 1 or greater then 250."
  441. Return False
  442. End If
  443. If bytes is Nothing or bytes.Length = 0 then
  444. errMsg = "bytes() must contain more then 0 bytes, and not be nothing."
  445. Return False
  446. End If
  447. If shuttingDown then
  448. errMsg = "The client is shutting down. Outgoing messages will not be accepted."
  449. Return False
  450. End If
  451. Dim msg As New message()
  452. ReDim msg.bytes(streamBytes.Length - 1)
  453. streamBytes.Position = 0
  454. streamBytes.Read(msg.bytes, 0, msg.bytes.Length)
  455. msg.dataChannel = channel
  456. sendQueue.Enqueue(msg)
  457. Return True
  458. End Function
  459. ''' <summary>
  460. ''' This is a convienience function that handles the work of converting the text you would like to send to a byte array.
  461. ''' Passes back the return value and errMsg of SendBytes(). Returns True on success and False on falure. Check the errMsg
  462. ''' string for send failure explanations.
  463. ''' </summary>
  464. ''' <param name="textMessage"></param>
  465. ''' <param name="channel"></param>
  466. ''' <param name="errMsg"></param>
  467. ''' <returns></returns>
  468. ''' <remarks></remarks>
  469. Public Function SendText(ByVal textMessage As String, Optional ByVal channel As Byte = 1, _
  470. Optional ByRef errMsg As String = "") As Boolean
  471. If shuttingDown then
  472. errMsg = "This client is shutting down. Text can not be sent."
  473. Return False
  474. End If
  475. If textMessage = "" then
  476. errMsg = "Your text message must contain some text."
  477. Return False
  478. End If
  479. Return SendBytes(Utilities.StrToByteArray(textMessage), channel, errMsg)
  480. End Function
  481. Private Function RcvBytes(ByVal data() As Byte, Optional ByVal dataChannel As Byte = 1) As Boolean
  482. ' dataType: >0 = data channel, 251 and up = internal messages. 0 is an invalid channel number (it's the puck)
  483. If dataChannel < 1 Or Not continue_running Then Return False
  484. Try
  485. Dim passedData(data.Length - 1) As Byte
  486. Array.Copy(data, passedData, data.Length)
  487. messageIn.queue.Enqueue(New message With { _
  488. .bytes = passedData,
  489. .dataChannel = dataChannel
  490. })
  491. 'ClientCallbackObject(data, datachannel)
  492. Catch ex As Exception
  493. ' An unexpected error.
  494. Debug.WriteLine("Unexpected error in Client\RcvBytes: " & ex.Message)
  495. Return False
  496. End Try
  497. Return True
  498. End Function
  499. Private Function CreateFolders(ByVal _path As String) As Boolean
  500. CreateFolders = True
  501. Dim parts() As String
  502. Dim path As String = ""
  503. Dim count As Int32
  504. parts = Split(_path, "\")
  505. path = parts(0)
  506. For count = 1 To parts.Length - 2
  507. path += "\" & parts(count)
  508. Try
  509. If Not Directory.Exists(path) Then
  510. Directory.CreateDirectory(path)
  511. End If
  512. Catch ex As Exception
  513. End Try
  514. Next
  515. End Function
  516. Private Sub SendExternalSystemMessage(ByVal message As String)
  517. SystemBytesToBeSent = Utilities.StrToByteArray(message)
  518. SystemOutputChannel = 254 ' Text messages / commands on channel 254
  519. SystemBytesToBeSentAvailable = True
  520. End Sub
  521. Private Function BeginToReceiveAFile(ByVal _path As String) As Boolean
  522. Dim readBuffer As Int32 = 0
  523. ReceivingFile = True
  524. BeginToReceiveAFile = True
  525. fileBytesRecieved = 0
  526. Try
  527. CreateFolders(_path)
  528. fileWriter = New AsyncUnbuffWriter(_path, True, _
  529. 1024 * (AsyncUnbuffWriter.GetPageSize()), IncomingFileSize)
  530. Catch ex As Exception
  531. _path = ex.Message
  532. ReceivingFile = False
  533. End Try
  534. If Not ReceivingFile Then
  535. Try
  536. fileWriter.Close()
  537. Catch ex As Exception
  538. End Try
  539. Return False
  540. End If
  541. End Function
  542. Private Function HandleIncomingFileBytes(ByRef bytes() As Byte) As Boolean
  543. Try
  544. fileWriter.Write(bytes, bytes.Length)
  545. HandleIncomingFileBytes = True
  546. Catch ex As Exception
  547. HandleIncomingFileBytes = False
  548. End Try
  549. End Function
  550. Private Sub FinishReceivingTheFile()
  551. Try
  552. fileWriter.Close()
  553. fileWriter = Nothing
  554. ReceivingFile = False
  555. Catch ex As Exception
  556. ReceivingFile = False
  557. End Try
  558. End Sub
  559. Private Sub StopSendingTheFile()
  560. Try
  561. SendingFile = False
  562. fileReader.Close()
  563. fileReader = Nothing
  564. GC.GetTotalMemory(True)
  565. Catch ex As Exception
  566. SendingFile = False
  567. GC.GetTotalMemory(True)
  568. End Try
  569. End Sub
  570. Private Sub WrapUpIncomingFile()
  571. If ReceivingFile Then
  572. Try
  573. fileWriter.Close()
  574. fileWriter = Nothing
  575. GC.GetTotalMemory(True)
  576. Catch ex As Exception
  577. End Try
  578. Try
  579. File.Delete(ReceivedFilesFolder & "\" & IncomingFileName)
  580. Catch ex As Exception
  581. End Try
  582. End If
  583. End Sub
  584. Private Function CheckSessionPermissions(ByVal cmd As String) As Boolean
  585. ' Your security code here...
  586. Return True
  587. End Function
  588. Private Function BeginFileSend(ByVal _path As String, ByVal fileLength As Long) As Boolean
  589. filebytesSent = 0
  590. Try
  591. fileReader = New FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.None, AsyncUnbuffWriter.GetPageSize)
  592. SendingFile = True
  593. BeginFileSend = True
  594. Catch ex As Exception
  595. BeginFileSend = False
  596. _path = ex.Message
  597. SendingFile = False
  598. End Try
  599. Try
  600. If Not BeginFileSend Then fileReader.Close()
  601. Catch ex As Exception
  602. End Try
  603. End Function
  604. Private Sub GetMoreFileBytesIfAvailable()
  605. Dim bytesRead As Integer
  606. If SendingFile And Not SystemBytesToBeSentAvailable Then
  607. Try
  608. If SystemBytesToBeSent.Length <> blockSize Then ReDim SystemBytesToBeSent(blockSize - 1)
  609. bytesRead = fileReader.Read(SystemBytesToBeSent, 0, blockSize)
  610. If bytesRead <> blockSize Then ReDim Preserve SystemBytesToBeSent(bytesRead - 1)
  611. If bytesRead > 0 Then
  612. SystemOutputChannel = 252 ' File transfer from client to server
  613. SystemBytesToBeSentAvailable = True
  614. filebytesSent += bytesRead
  615. Else
  616. ReDim SystemBytesToBeSent(blockSize - 1)
  617. SendExternalSystemMessage("<-Done") ' Send the server a completion notice.
  618. SystemMessage("<-Done")
  619. SendingFile = False
  620. ' Clean up
  621. fileReader.Close()
  622. fileReader = Nothing
  623. GC.GetTotalMemory(True)
  624. End If
  625. Catch ex As Exception
  626. SendExternalSystemMessage("ERR: " & ex.Message)
  627. ' We're finished.
  628. ReDim SystemBytesToBeSent(blockSize - 1)
  629. SendingFile = False
  630. fileReader.Close()
  631. End Try
  632. End If
  633. End Sub
  634. Private Function GetFilenameFromPath(ByVal filePath As String) As String
  635. Dim filePathParts() As String
  636. If filePath.Trim = "" Then Return ""
  637. filePathParts = Split(filePath, "\")
  638. GetFilenameFromPath = filePathParts(filePathParts.Length - 1)
  639. End Function
  640. Private Sub HandleIncomingSystemMessages(ByVal bytes() As Byte, ByVal channel As Byte)
  641. If channel = 254 Then ' Text commands / messages passed between server and client
  642. Dim message As String = Utilities.BytesToString(bytes)
  643. Dim tmp As String = ""
  644. Dim filePath As String
  645. ' Get File Request: The server wants us to send them a file.
  646. If message.Length > 4 Then tmp = message.Substring(0, 4)
  647. If tmp = "GFR:" Then ' Get File Request
  648. ' Get file path...
  649. filePath = message.Substring(4, message.Length - 4)
  650. ' Does it exist?
  651. If File.Exists(message.Substring(4, message.Length - 4)) Then
  652. ' Are we already busy sending them a file?
  653. If Not SendingFile Then
  654. Dim _theFilesInfo As New FileInfo(filePath)
  655. outgoingFileName = GetFilenameFromPath(filePath)
  656. outgoingFileSize = CULng(_theFilesInfo.Length)
  657. If BeginFileSend(filePath, _theFilesInfo.Length) Then
  658. ' Send only the file NAME. It will have a different path on the other side.
  659. SendExternalSystemMessage("Sending:" & outgoingFileName & _
  660. ":" & outgoingFileSize.ToString)
  661. SystemMessage("Sending file:" & outgoingFileName)
  662. Else
  663. ' FilePath contains the error message.
  664. SendExternalSystemMessage("ERR: " & filePath)
  665. End If
  666. Else
  667. ' There's already a GFR in progress.
  668. SendExternalSystemMessage("ERR: File: ''" & _
  669. FileBeingSentPath & _
  670. "'' is still in progress. Only one file " & _
  671. "may be transfered (from client to server) at a time.")
  672. End If
  673. Else
  674. ' File doesn't exist. Send an error.
  675. SendExternalSystemMessage("ERR: The requested file can not be found by the server.")
  676. End If
  677. End If
  678. If message.Length > 7 Then tmp = message.Substring(0, 8)
  679. If tmp = "Sending:" Then
  680. ' Strip away the headder...
  681. Dim msgParts() As String = Split(message, ":")
  682. IncomingFileSize = Convert.ToInt64(msgParts(2))
  683. IncomingFileName = msgParts(1)
  684. tmp = ReceivedFilesFolder & "\" & IncomingFileName
  685. SystemMessage("Receiving file: " & IncomingFileName)
  686. If Not BeginToReceiveAFile(tmp) Then
  687. SystemMessage("ERR: " & tmp)
  688. SendExternalSystemMessage("Abort<-")
  689. End If
  690. End If
  691. If message.Length > 10 Then tmp = message.Substring(0, 10)
  692. If tmp = "blocksize:" Then
  693. Dim msgParts() As String = Split(message, ":")
  694. blockSize = Convert.ToUInt16(msgParts(1))
  695. End If
  696. If message = "->Done" Then
  697. FinishReceivingTheFile()
  698. SystemMessage("->Done")
  699. End If
  700. ' We've been notified that no file data will be forthcoming.
  701. If message = "Abort->" Then
  702. FinishReceivingTheFile()
  703. SystemMessage("->Aborted.")
  704. Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal
  705. Try
  706. File.Delete(ReceivedFilesFolder & "\" & IncomingFileName)
  707. Catch ex As Exception
  708. End Try
  709. End If
  710. ' Send File Request: The server wants to send us a file.
  711. If message.Length > 4 Then tmp = message.Substring(0, 4)
  712. If tmp = "SFR:" Then
  713. If CheckSessionPermissions("SFR") Then
  714. Dim parts() As String
  715. parts = Split(message, "SFR:")
  716. SendExternalSystemMessage("GFR:" & parts(1))
  717. Else
  718. ' This user doesn't have rights to this file. Send an error.
  719. SendExternalSystemMessage("ERR: You do not have permission to send files. Access Denied.")
  720. End If
  721. End If
  722. ' Notification that the server has complied with our
  723. ' request to stop sending bytes for this
  724. ' (server->client) file transfer.
  725. If message = "->Aborted." Then
  726. SystemMessage("->Aborted.")
  727. WrapUpIncomingFile()
  728. End If
  729. ' Notification that the server has complied with our
  730. ' request to stop recieving bytes for this
  731. ' (client->server) file transfer.
  732. If message = "<-Aborted." Then
  733. SystemMessage("<-Aborted.")
  734. End If
  735. If message.Length > 4 Then tmp = message.Substring(0, 4)
  736. If tmp = "ERR:" Then ' The server has sent us an error message.
  737. ' Pass it on up to the user.
  738. SystemMessage(message)
  739. End If
  740. If message.Length > 5 Then tmp = message.Substring(0, 5)
  741. If tmp = "CERR:" Then ' The server has sent us a connection error message.
  742. ' Pass it on up to the user.
  743. errMsg = message.Replace("CERR:", "")
  744. End If
  745. ' New queue throttling code
  746. If message = "pause" Then
  747. 'sendBuffer.PauseSending()
  748. End If
  749. If message = "resume" Then
  750. 'sendBuffer.ResumeSending()
  751. End If
  752. ' Preform gracefull shutdown.
  753. If message = "close" then
  754. 'SystemMessage("Disconnected by server.")
  755. continue_running = False
  756. 'disConnectComplete = True
  757. Throw New Exception("Shutting down gracefully")
  758. End If
  759. If message = "connection:rejected" then
  760. 'continue_running = False
  761. connectionRejected = True
  762. InternalClose()
  763. End If
  764. If message = "connection:accepted" then
  765. connectionAccepted = True
  766. End If
  767. ElseIf channel = 253 Then ' File transfer from server to client
  768. Try
  769. If ReceivingFile Then
  770. HandleIncomingFileBytes(bytes)
  771. fileBytesRecieved += bytes.LongLength
  772. End If
  773. Catch ex As Exception
  774. End Try
  775. ElseIf channel = 252 Then ' File transfer from client to server
  776. ElseIf channel = 251 Then ' reserved.
  777. End If
  778. End Sub
  779. Private Function HandleOutgoingInternalSystemMessage() As Boolean
  780. Dim tmp(1) As Byte
  781. HandleOutgoingInternalSystemMessage = False
  782. Dim _size As Integer
  783. GetMoreFileBytesIfAvailable()
  784. ' Handle outgoing system stuff here
  785. If SystemBytesToBeSentAvailable = True Then
  786. HandleOutgoingInternalSystemMessage = True
  787. If SystemBytesToBeSent.Length > blockSize Then
  788. ' Send Channel
  789. tmp(0) = SystemOutputChannel
  790. Stream.Write(tmp, 0, 1)
  791. bytesSentThisSecond += 1
  792. ' Send packet size
  793. _size = blockSize
  794. tmp = BitConverter.GetBytes(_size)
  795. Stream.Write(tmp, 0, 2)
  796. bytesSentThisSecond += 2
  797. ' Send packet
  798. Stream.Write(GetSome(SystemBytesToBeSent, blockSize, SystemBytesToBeSentAvailable), 0, _size)
  799. bytesSentThisSecond += _size
  800. Else
  801. ' Send Channel
  802. tmp(0) = SystemOutputChannel
  803. Stream.Write(tmp, 0, 1)
  804. bytesSentThisSecond += 1
  805. ' Send packet size
  806. _size = SystemBytesToBeSent.Length
  807. tmp = BitConverter.GetBytes(_size)
  808. Stream.Write(tmp, 0, 2)
  809. bytesSentThisSecond += 2
  810. ' Send packet
  811. Stream.Write(SystemBytesToBeSent, 0, _size)
  812. bytesSentThisSecond += _size
  813. SystemBytesToBeSentAvailable = False
  814. End If
  815. End If
  816. End Function
  817. Private Function HandleOutgoingUserData() As Boolean
  818. Dim tmp(1) As Byte
  819. Dim _size As UShort
  820. Dim notify As Boolean = False
  821. Static packet(0) As Byte
  822. Dim msg As message = Nothing
  823. Dim stopMessageSent As Boolean = False
  824. If Not UserBytesToBeSentAvailable then
  825. If sendQueue.TryDequeue(msg) then
  826. UserBytesToBeSentAvailable = True
  827. UserBytesToBeSent.SetLength(0)
  828. UserBytesToBeSent.Write(msg.bytes, 0, msg.bytes.Length)
  829. UserBytesToBeSent.Position = 0
  830. UserOutputChannel = msg.dataChannel
  831. End If
  832. End If
  833. If theClientIsStopping() then
  834. UserBytesToBeSentAvailable = True
  835. Dim closeMessage As Byte() = Utilities.StrToByteArray("close")
  836. UserBytesToBeSent.SetLength(0)
  837. UserBytesToBeSent.Write(closeMessage, 0, closeMessage.Length)
  838. UserBytesToBeSent.Position = 0
  839. UserOutputChannel = 254
  840. stopMessageSent = True
  841. End If
  842. If UserBytesToBeSentAvailable = True Then
  843. Try
  844. If (UserBytesToBeSent.Length - UserBytesToBeSent.Position) > blockSize Then
  845. ' Send Channel
  846. tmp(0) = UserOutputChannel
  847. Stream.Write(tmp, 0, 1)
  848. ' Send packet size
  849. _size = blockSize
  850. tmp = BitConverter.GetBytes(_size)
  851. Stream.Write(tmp, 0, 2)
  852. ' Send packet
  853. If packet.Length <> _size Then ReDim packet(_size - 1)
  854. UserBytesToBeSent.Read(packet, 0, _size)
  855. 'Client.NoDelay = True
  856. Stream.Write(packet, 0, _size)
  857. bytesSentThisSecond += 3 + _size
  858. ' Check to see if we've sent it all...
  859. If UserBytesToBeSent.Length = UserBytesToBeSent.Position Then
  860. UserBytesToBeSentAvailable = False
  861. notify = True
  862. End If
  863. Else
  864. ' Send Channel
  865. tmp(0) = UserOutputChannel
  866. Stream.Write(tmp, 0, 1)
  867. ' Send packet size
  868. _size = Convert.ToUInt16(UserBytesToBeSent.Length - UserBytesToBeSent.Position)
  869. tmp = BitConverter.GetBytes(_size)
  870. Stream.Write(tmp, 0, 2)
  871. ' Send packet
  872. If packet.Length <> _size Then ReDim packet(_size - 1)
  873. UserBytesToBeSent.Read(packet, 0, _size)
  874. 'Client.NoDelay = True
  875. Stream.Write(packet, 0, _size)
  876. bytesSentThisSecond += 3 + _size
  877. UserBytesToBeSentAvailable = False
  878. notify = True
  879. End If
  880. Catch ex As Exception
  881. ' Report error attempting to send user data.
  882. Debug.WriteLine("Unexpected error in TcpCommClient\HandleOutgoingUserData: " & ex.Message)
  883. End Try
  884. ' Notify the user that the packet has been sent.
  885. If notify Then SystemMessage("UBS:" & UserOutputChannel)
  886. If stopMessageSent then Throw New Exception("Client closing gracefully.")
  887. Return True
  888. Else
  889. Return False
  890. End If
  891. End Function
  892. Private Function GetSome(ByRef bytes() As Byte, ByVal chunkToBreakOff As Integer, _
  893. ByRef bytesToBeSentAvailable As Boolean, _
  894. Optional ByVal theseAreUserBytes As Boolean = False) As Byte()
  895. Dim tmp(chunkToBreakOff - 1) As Byte
  896. Array.Copy(bytes, 0, tmp, 0, chunkToBreakOff)
  897. GetSome = tmp
  898. If bytes.Length = chunkToBreakOff Then
  899. bytesToBeSentAvailable = False
  900. If theseAreUserBytes Then SystemMessage("UBS")
  901. Else
  902. Dim tmp2(bytes.Length - chunkToBreakOff - 1) As Byte
  903. Array.Copy(bytes, chunkToBreakOff, tmp2, 0, bytes.Length - chunkToBreakOff)
  904. bytes = tmp2
  905. End If
  906. End Function
  907. Private Sub SystemMessage(ByVal MsgText As String)
  908. If silentShutdown = True then Return
  909. If isRunning then
  910. RcvBytes(Utilities.StrToByteArray(MsgText), 255)
  911. Else
  912. Dim bgMsg As New Thread(AddressOf BgMessage)
  913. bgMsg.IsBackground = True
  914. bgMsg.Start(MsgText)
  915. End If
  916. End Sub
  917. Private Sub BgMessage(ByVal _text As Object)
  918. Dim msg As String = CType(_text, String)
  919. ClientCallbackObject(Utilities.StrToByteArray(msg), 255)
  920. End Sub
  921. ' Check to see if our app is closing (set in FormClosing event)
  922. Private Function theClientIsStopping() As Boolean
  923. If continue_running = False then Return True
  924. Return False
  925. End Function
  926. Private Function CalculateMbps(Optional ByVal GetMbps As Boolean = False) As Decimal
  927. Static averagesCounter As Integer = 0
  928. Static tmr As Date = Now
  929. Static lastread As Int32 = 0
  930. Dim looper As Short = 0
  931. Dim tmp As Int32 = 0
  932. If mbpsOneSecondAverage Is Nothing Then ReDim mbpsOneSecondAverage(9)
  933. If Now >= tmr.AddMilliseconds(250) Then
  934. averagesCounter += 1
  935. If averagesCounter < 0 Then averagesCounter = 0
  936. Select Case averagesCounter
  937. Case 0
  938. SyncLock (mbpsSyncObject)
  939. Try
  940. mbpsOneSecondAverage(averagesCounter) = bytesSentThisSecond + bytesReceivedThisSecond
  941. bytesSentThisSecond = 0
  942. bytesReceivedThisSecond = 0
  943. Catch ex As Exception
  944. averagesCounter = -1
  945. End Try
  946. End SyncLock
  947. Case 1
  948. SyncLock (mbpsSyncObject)
  949. Try
  950. mbpsOneSecondAverage(averagesCounter) = bytesSentThisSecond + bytesReceivedThisSecond
  951. bytesSentThisSecond = 0
  952. bytesReceivedThisSecond = 0
  953. Catch ex As Exception
  954. averagesCounter = -1
  955. End Try
  956. End SyncLock
  957. Case 2
  958. SyncLock (mbpsSyncObject)
  959. Try
  960. mbpsOneSecondAverage(averagesCounter) = bytesSentThisSecond + bytesReceivedThisSecond
  961. bytesSentThisSecond = 0
  962. bytesReceivedThisSecond = 0
  963. Catch ex As Exception
  964. averagesCounter = -1
  965. End Try
  966. End SyncLock
  967. Case 3
  968. SyncLock (mbpsSyncObject)
  969. Try
  970. mbpsOneSecondAverage(averagesCounter) = bytesSentThisSecond + bytesReceivedThisSecond
  971. bytesSentThisSecond = 0
  972. bytesReceivedThisSecond = 0
  973. Catch ex As Exception
  974. averagesCounter = -1
  975. End Try
  976. End SyncLock
  977. End Select
  978. If averagesCounter > 2 Then averagesCounter = -1
  979. tmr = Now
  980. End If
  981. ' Did they ask us for the Mbps?
  982. If GetMbps Then
  983. For looper = 0 To 3
  984. SyncLock (mbpsSyncObject)
  985. tmp += mbpsOneSecondAverage(looper)
  986. End SyncLock
  987. Next
  988. CalculateMbps = tmp
  989. Else
  990. CalculateMbps = 0
  991. End If
  992. End Function
  993. Private Sub Run()
  994. Dim puck(1) As Byte : puck(0) = 0
  995. Dim theBuffer(blockSize - 1) As Byte
  996. Dim tmp(1) As Byte
  997. Dim dataChannel As Byte = 0
  998. Dim packetSize As UShort = 0
  999. Dim bytesread As Integer
  1000. Dim userOrSystemSwitcher As Integer = 0
  1001. Dim PercentUsage As Short = -1
  1002. Dim connectionLossTimer As Date
  1003. 'Dim CPUutil As New CpuMonitor
  1004. 'CPUutil.Start()
  1005. Try
  1006. Client = New TcpClient
  1007. Client.Connect(IP, Port)
  1008. ' Connection Accepted.
  1009. Stream = Client.GetStream()
  1010. Stream.ReadTimeout = 5000
  1011. ' Set the send and receive buffers to the maximum
  1012. ' size allowable in this application...
  1013. Client.Client.ReceiveBufferSize = 65535
  1014. Client.Client.SendBufferSize = 65535
  1015. ' no delay on partially filled packets...
  1016. ' Send it all as fast as possible.
  1017. Client.NoDelay = True
  1018. ' Pass a message up to the user about our status.
  1019. isRunning = True
  1020. SystemMessage("Connected.")
  1021. ' Start the communication loop
  1022. While True
  1023. ' Check to see if our app is shutting down.
  1024. 'If theClientIsStopping() Then Exit Do
  1025. ' Normal communications...
  1026. If weHaveThePuck Then
  1027. ' Send user data if there is any to be sent.
  1028. userOrSystemSwitcher += 1
  1029. Select Case userOrSystemSwitcher
  1030. Case 1
  1031. HandleOutgoingUserData()
  1032. Case 2
  1033. HandleOutgoingInternalSystemMessage()
  1034. End Select
  1035. If userOrSystemSwitcher > 1 Then userOrSystemSwitcher = 0
  1036. ' After sending our data, send the puck
  1037. Stream.Write(puck, 0, 1)
  1038. ' Uncomment this to see control bit traffic as part of your Mbps
  1039. 'bytesSentThisSecond += 1
  1040. weHaveThePuck = False
  1041. End If
  1042. If theBuffer.Length < 2 Then ReDim theBuffer(1)
  1043. ' Read in the control byte.
  1044. Stream.Read(theBuffer, 0, 1)
  1045. dataChannel = theBuffer(0)
  1046. ' Uncomment this to see control bit traffic as part of your Mbps
  1047. 'bytesReceivedThisSecond += 1
  1048. ' If it's just the puck (communictaion syncronization byte),
  1049. ' set weHaveThePuck true and that's all. dataChannel 0 is
  1050. ' reserved for the puck.
  1051. If dataChannel = 0 Then
  1052. weHaveThePuck = True
  1053. Else
  1054. ' It's not the puck: It's an incoming packet.
  1055. ' Get the packet size:
  1056. tmp(0) = Convert.ToByte(Stream.ReadByte)
  1057. tmp(1) = Convert.ToByte(Stream.ReadByte)
  1058. packetSize = BitConverter.ToUInt16(tmp, 0)
  1059. If theBuffer.Length <> packetSize Then ReDim theBuffer(packetSize - 1)
  1060. bytesReceivedThisSecond += 2
  1061. ' Get the packet:
  1062. connectionLossTimer = Now
  1063. Do
  1064. ' Read bytes in...
  1065. bytesread += Stream.Read(theBuffer, bytesread, (packetSize - bytesread))
  1066. ' If it takes longer then 3 seconds to get a packet, we've lost connection.
  1067. If connectionLossTimer.AddSeconds(3) < Now Then Throw New Exception("Time out waiting for packet to arrive. Connection lost.")
  1068. Loop While bytesread < packetSize
  1069. bytesread = 0
  1070. ' Record bytes read for throttling...
  1071. bytesReceivedThisSecond += packetSize
  1072. ' Handle the packet...
  1073. If dataChannel > 250 and continue_running Then
  1074. ' this is an internal system packet
  1075. HandleIncomingSystemMessages(theBuffer, dataChannel)
  1076. Else
  1077. ' Hand data off to the calling thread.
  1078. RcvBytes(theBuffer, dataChannel)
  1079. End If
  1080. End If
  1081. CalculateMbps(False)
  1082. ' Measure and display the CPU usage of the client (this thread).
  1083. 'If PercentUsage <> CPUutil.ThreadUsage Then
  1084. ' PercentUsage = CPUutil.ThreadUsage
  1085. ' SystemMessage("" & PercentUsage & "% Thread Usage (" & CPUutil.CPUusage & "% across all CPUs)")
  1086. 'End If
  1087. End While
  1088. Catch ex As Exception
  1089. ' Handle thrown errors here:
  1090. If ex IsNot Nothing Then errMsg = "Error caught in run thread: " & ex.Message 'And ex.Message <> "Shutting down gracefully"
  1091. End Try
  1092. Try
  1093. 'CPUutil.StopWatcher()
  1094. 'If Not Client.Client Is Nothing Then Client.Client.Close()
  1095. Client.Client.Dispose()
  1096. Client.Close()
  1097. Catch ex As Exception
  1098. ' An unexpected error.
  1099. Debug.WriteLine("Error atempting to shut down the theClient after Gracefull Disconnect: " & ex.Message)
  1100. End Try
  1101. Try
  1102. If fileWriter IsNot Nothing Then fileWriter.Close()
  1103. Catch ex As Exception
  1104. End Try
  1105. 'Try
  1106. ' 'CPUutil.StopWatcher()
  1107. ' 'If Not Client.Client Is Nothing Then Client.Client.Close()
  1108. 'Catch ex As Exception
  1109. ' ' An unexpected error.
  1110. ' Debug.WriteLine("Unexpected error in Client\theClientIsStopping: " & ex.Message)
  1111. 'End Try
  1112. WrapUpIncomingFile()
  1113. isRunning = False
  1114. If messageIn IsNot Nothing Then messageIn.Close()
  1115. If reconnectMonitorDetails.ReconnectOnDisconnection And _
  1116. Not reconnectMonitorDetails.Reconnecting And connectionAccepted Then
  1117. reconnectMonitorDetails.ipAddress = IP.ToString()
  1118. reconnectMonitorDetails.machineId = machineId
  1119. reconnectMonitorDetails.port = Port
  1120. Dim reconnectThread As New Thread(AddressOf ReconnectMonitor)
  1121. reconnectThread.Start()
  1122. End If
  1123. ' Report disconnection here:
  1124. If reconnectMonitorDetails.ReconnectOnDisconnection = False Then
  1125. ' We've been disconnected and we are con configured to reconnect automatically, so we report it.
  1126. SystemMessage("Disconnected.")
  1127. Else
  1128. ' We ARE configured to automatically reconnect, and we've been disconnected.
  1129. ' If continue_running = False, then we've been deliberately disconnected
  1130. ' by the server, and we should just report our status.
  1131. ' If continue_running = True, then we've LOST connection, possibly due to network
  1132. ' conditions, and we should not report it HERE. The automatic reconnect system
  1133. ' will either reconnect, or report that we are disconnected after the reconnect
  1134. ' duration has expired.
  1135. If continue_running = False then SystemMessage("Disconnected.")
  1136. End If
  1137. disConnectComplete = True
  1138. End Sub
  1139. End Class