博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Net.Sockets.TcpListener和Net.Sockets.TcpClient进行图片传输时怎样精确控制接收缓存数组大小...
阅读量:4673 次
发布时间:2019-06-09

本文共 4548 字,大约阅读时间需要 15 分钟。

在dotnet平台Net.Sockets.TcpListener和Net.Sockets.TcpClient已经为我们封装了全部Socket关于tcp部分,操作也更为简单,面向数据流。使用TcpClient的GetStream方法获取数据流后能够方便的对数据流进行读写操作,就如同本地磁盘的文件读写一样,使得程序猿在设计程序时更为便捷简单。

但假设你使用过这两个对象进行传输数据的时候,你会发现问题也随之而来——GetStream获取的数据流是一个永无止境的Stream,你无法获取它的详细长度。

来看一下微软MSDN关于这两个对象的例程:

Shared Sub Connect(server As [String], message As [String])   Try      ' Create a TcpClient.      ' Note, for this client to work you need to have a TcpServer       ' connected to the same address as specified by the server, port      ' combination.      Dim port As Int32 = 13000      Dim client As New TcpClient(server, port)      ' Translate the passed message into ASCII and store it as a Byte array.      Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(message)      ' Get a client stream for reading and writing.      '  Stream stream = client.GetStream();      Dim stream As NetworkStream = client.GetStream()      ' Send the message to the connected TcpServer.       stream.Write(data, 0, data.Length)      Console.WriteLine("Sent: {0}", message)      ' Receive the TcpServer.response.      ' Buffer to store the response bytes.      data = New [Byte](256) {}      ' String to store the response ASCII representation.      Dim responseData As [String] = [String].Empty      ' Read the first batch of the TcpServer response bytes.      Dim bytes As Int32 = stream.Read(data, 0, data.Length)      responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)      Console.WriteLine("Received: {0}", responseData)      ' Close everything.      stream.Close()      client.Close()   Catch e As ArgumentNullException      Console.WriteLine("ArgumentNullException: {0}", e)   Catch e As SocketException      Console.WriteLine("SocketException: {0}", e)   End Try   Console.WriteLine(ControlChars.Cr + " Press Enter to continue...")   Console.Read()End Sub 'Connect
你不得不去指定一个固定尺寸的缓冲区来接收数据,假设实际发送的数据超出了这个长度,你可能无法接收到所有完整的数据,而假设发送的数据少于缓冲区的大小,那么非常显然你的内存会比别人消耗的更快。更为严重的时。假设你要发送一副图片,图片容量可能依据内容的不同而各有千秋,容量也不止256Byte这么小,该怎样精确控制缓冲区呢?

事实上我们能够非常easy的解决问题,就像非常多文件格式所做的事情一样,我们能够在Stream的前几个字节写入实际有效数据的长度。然后依据这个长度来分配内存。再读取内容,我所做的client与server之间传递屏幕的源码例如以下:

'----------------client----------------

Public Class Form1    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick        Dim tcpc As New Net.Sockets.TcpClient        Dim slens(7) As Byte        Try            tcpc.Connect("127.0.0.1", 2099)            If tcpc.Connected Then                For i = 0 To 7                    slens(i) = tcpc.GetStream.ReadByte                Next                Dim buf(BitConverter.ToUInt64(slens, 0)) As Byte                Me.Text = buf.Length                tcpc.GetStream.Read(buf, 0, buf.Length)                Dim mem As New IO.MemoryStream(buf)                Dim bmp As New Bitmap(mem)                Me.PictureBox1.Image = bmp                tcpc.Close()            End If        Catch ex As Exception        Finally            tcpc.Close()        End Try    End Sub    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load    End SubEnd Class
 

 '------------server---------------- 

Public Class Form1    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork        Dim tcps As New Net.Sockets.TcpListener(2099)        tcps.Start()        While True            Dim slen As UInt64            Dim slens(7) As Byte            Dim tcpc As Net.Sockets.TcpClient            tcpc = tcps.AcceptTcpClient            '创建图片            Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)            bmp.SetResolution(1, 1)            Dim gph As Graphics = Graphics.FromImage(bmp)            gph.CopyFromScreen(New Point(0, 0), New Point(0, 0), bmp.Size)            gph.Flush()            '存入内存            Dim mem As New IO.MemoryStream            bmp.Save(mem, Drawing.Imaging.ImageFormat.Tiff)            '文件长度            slen = mem.Length            slens = BitConverter.GetBytes(slen)            '发送长度            For i = 0 To 7                tcpc.GetStream.WriteByte(slens(i))            Next            '发送内容            tcpc.GetStream.Write(mem.ToArray, 0, mem.Length)            tcpc.Close()        End While    End Sub    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load        Me.BackgroundWorker1.RunWorkerAsync()    End SubEnd Class

转载于:https://www.cnblogs.com/liguangsunls/p/7294641.html

你可能感兴趣的文章
Manacher's algorithm: 最长回文子串算法
查看>>
算法题003 斐波那契(Fibonacci)数列
查看>>
MySQL索引背后的数据结构及算法原理
查看>>
CSS定位 position
查看>>
冒泡排序
查看>>
es7新特性 includes用法
查看>>
block,inline和inline-block
查看>>
SQA
查看>>
Spring+Struts集成(方案一)
查看>>
在Windows 7中安装、配置和使用IIS7和ASP
查看>>
商业信息敏感、安全处理(口令、数字证书-U盾-密保卡、指纹识别-虹膜识别)...
查看>>
数据库设计的三大范式通俗解释
查看>>
H3C 典型数据链路层标准
查看>>
反向数据库表
查看>>
【原创】Elasticsearch无宕机迁移节点
查看>>
Stripe
查看>>
CC攻击及其解决方法
查看>>
Android安卓手机能不能实现BT文件边下边播?
查看>>
C/C++中printf和C++中cout的输出格式
查看>>
C# CharacterToBinary 将类似2进制字符串 10010110111 转换为数值型源码
查看>>