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