У меня есть цель постоянно отправлять и получать снимки экрана с помощью асинхронного сокета, и я создал этот следующий код после просмотра нескольких ссылок в Интернете. Перед попыткой непрерывной отправки я протестировал отправку только один раз, но скриншот не был правильно получен на сервере.
Некоторая идея о том, как это исправить? Заранее спасибо.
Сервер:
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Public Class frmServer
Dim serverSocket As Socket
Dim clientSocket As Socket
Dim byteData(1023) As Byte
Private Sub FrmServer_Load(sender As Object, e As EventArgs) Handles MyBase.Load
serverSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim IpEndPoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8800)
serverSocket.Bind(IpEndPoint)
serverSocket.Listen(5)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
End Sub
Private Sub OnAccept(ByVal ar As IAsyncResult)
clientSocket = serverSocket.EndAccept(ar)
'New connection established
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket)
serverSocket.BeginAccept(New AsyncCallback(AddressOf OnAccept), Nothing)
End Sub
Private Sub OnReceive(ByVal ar As IAsyncResult)
Dim client As Socket = ar.AsyncState
client.EndReceive(ar)
'Using MStream As New MemoryStream(byteData)
'Dim returnImage As Image = Image.FromStream(MStream)
'pbDesktop.Image = returnImage
'End Using
File.WriteAllBytes(Environment.CurrentDirectory & "\screenshot.jpg", byteData)
'Array.Clear(byteData, 0, byteData.Length)
clientSocket.BeginReceive(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), clientSocket)
End Sub
Клиент:
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Net
Imports System.Net.Sockets
Public Class frmClient
Private Function BytesScreen() As Byte()
Dim bounds As Rectangle
Dim screenshot As Bitmap
Dim graph As Graphics
bounds = Screen.PrimaryScreen.Bounds
screenshot = New Bitmap(bounds.Width, bounds.Height)
graph = Graphics.FromImage(screenshot)
graph.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy)
Dim ms As New MemoryStream()
screenshot.Save(ms, ImageFormat.Jpeg)
Dim bitmapbytestream(ms.Length) As Byte
bitmapbytestream = ms.ToArray
Return bitmapbytestream
End Function
Dim clientSocket As Socket
Private Sub BtnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
clientSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
Dim IpAddress As IPAddress = IPAddress.Parse("127.0.0.1")
Dim IpEndPoint As IPEndPoint = New IPEndPoint(IpAddress, 8800)
clientSocket.BeginConnect(IpEndPoint, New AsyncCallback(AddressOf OnConnect), Nothing)
End Sub
Private Sub OnConnect(ByVal ar As IAsyncResult)
clientSocket.EndConnect(ar)
Send(BytesScreen, clientSocket)
End Sub
Private Sub Send(ByVal byteData As Byte(), ByVal client As Socket)
Try
client.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
Catch ex As Exception
If Not client.Connected Then 'if connection was forcibly disconnected
'reconnecting to the server
btnConnect.PerformClick()
End If
End Try
End Sub
Private Sub OnSend(ByVal ar As IAsyncResult)
Dim client As Socket = ar.AsyncState
client.EndSend(ar)
'Send(BytesScreen, clientSocket)
End Sub
End Class
Receive
. TCP — это потоковый протокол, то есть на прикладном уровне все данные представлены в виде непрерывного потока байтов, и вы получаете только то, что скачали на данный момент. Таким образом, для одного вызоваSend
может потребоваться несколько вызововReceive
в зависимости от размера ваших данных. - person Visual Vincent   schedule 05.03.2020BeginReceive()
иBeginSend()
, являются асинхронными сокетами, а не синхронными сокетами: D. Спасибо за ваше объяснение комментариев выше, они будут полезны тем, кто использует сокеты синхронизации. - person BrowJr   schedule 05.03.2020Send
иReceive
, я имел в виду не синхронные методы, а скорее любое время, когда вы выполняете операцию отправки или получения в потоке, асинхронную или нет. - person Visual Vincent   schedule 06.03.2020but if you need to send other kinds of data without waiting for the entire file to be sent
- Да, это тоже цель. - person BrowJr   schedule 06.03.2020BeginRead()
иBeginSend()
(в котором вы указываетеclientSocket
). Хотя я бы скорее рекомендовал методыReadAsync()
иSendAsync()
, поскольку они позволяют использовать асинхронность, но при этом сохраняют более чистый, синхронный стиль кода. - person Visual Vincent   schedule 06.03.2020ReadAsync()
иWriteAsync()
изNetworkStream
вместе сAwait
, если вы используете любую версию Visual Studio, более новую, чем 2010. Они созданы для того, чтобы ваш код сохранял свой обычный нисходящий поток, оставаясь при этом асинхронным и не прерывая вызывающий поток. - person Visual Vincent   schedule 06.03.2020however it isn't as simple as increasing the buffer size
— сработало увеличение размера буфера (Dim byteData(81927657) As Byte
).since you don't know how much data each Receive call will give you.
- Как это обнаружить? какая-то идея? - person BrowJr   schedule 06.03.2020since you don't know how much data each Receive call will give you.
- я думаю, что это можно решить. Также здесь можно увидеть пример кода, основанный на первой ссылке ответа @Mike. - person BrowJr   schedule 06.03.2020