使用Net.Sockets.TcpListener和Net.Sockets.TcpClient进行图片传输时如何精确控制接收缓存数组大小

<span style="font-size:18px;">在dotnet平台Net.Sockets.TcpListener和Net.Sockets.TcpClient已经为我们封装了所有Socket关于tcp部分,操作也更为简单,面向数据流。使用TcpClient的GetStream方法获取数据流后可以方便的对数据流进行读写操作,就如同本地磁盘的文件读写一样,使得程序员在设计程序时更为便捷简单。</span>

但如果你使用过这两个对象进行数据传输的时候,你会发现问题也随之而来——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这么小,该如何精确控制缓冲区呢?

其实我们可以很容易的解决这个问题,就像很多文件格式所做的事情一样,我们可以在Stream的前几个字节写入实际有效数据的长度,然后根据这个长度来分配内存,再读取内容,我所做的客户端与服务器之间传递屏幕的源代码如下:

‘----------------客户端----------------

<pre name="code" class="vb">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 Sub
End Class


‘------------服务器----------------

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 Sub
End Class

使用Net.Sockets.TcpListener和Net.Sockets.TcpClient进行图片传输时如何精确控制接收缓存数组大小

时间: 2024-10-13 13:23:10

使用Net.Sockets.TcpListener和Net.Sockets.TcpClient进行图片传输时如何精确控制接收缓存数组大小的相关文章

使用Net.Sockets.TcpListener和Net.Sockets.TcpClient进行图片传输时怎样精确控制接收缓存数组大小

<span style="font-size:18px;">在dotnet平台Net.Sockets.TcpListener和Net.Sockets.TcpClient已经为我们封装了全部Socket关于tcp部分,操作也更为简单,面向数据流.使用TcpClient的GetStream方法获取数据流后能够方便的对数据流进行读写操作,就如同本地磁盘的文件读写一样,使得程序猿在设计程序时更为便捷简单.</span> 但假设你使用过这两个对象进行传输数据的时候,你会发

linux内核参数详解

内核参数列表 kernel.acct acct功能用于系统记录进程信息,正常结束的进程都会在该文件尾添加对应的信息.异常结束是指重启或其它致命的系统问题,不能够记录永不停止的进程.该设置需要配置三个值,分别是: 1.如果文件系统可用空间低于这个百分比值,则停止记录进程信息. 2.如果文件系统可用空间高于这个百分比值,则开始记录进程信息. 3.检查上面两个值的频率(以秒为单位). kernel.auto_msgmni 系统自动设置同时运行的消息队列个数. 0:不自动 1:自动 kernel.blk

TCP 接收窗口自动调节

https://technet.microsoft.com/zh-cn/magazine/2007.01.cableguy.aspx 欢迎来到 TechNet 杂志“网络专家”的第一部分.TechNet 网站上的专栏爱好者都知道我们探讨各种网络问题,我们每个月都将继续保持这个传统.如果您是新手,要查找以前专栏的存档,请访问网络专家站点. 现在开始介绍我们的第一个主题 - TCP 接收窗口. TCP 连接的吞吐量可以通过发送和接收应用程序.发送和接收 TCP 的实现以及 TCP 对等方之间的传输路

(1) Socket网络编程(C#)----TcpListener 与 TcpClient

◇TcpListener 用于阻止同步模式下侦听和接受传入连接请求.(用于侦听) ◇我们先来做一件事情,对本地机器上某一端口的侦听. ◇因为如果想要与外界进行通信,第一件要做的事情就是开启对端口的侦听,这就像为计算机打开了一个“门”,所有向这个“门”发送的请求(“敲门”)都会被系统接收到. ◇在C#中可以通过下面几个步骤完成,首先使用本机Ip地址和端口号创建一个System.Net.Sockets.TcpListener类型的实例,然后在该实例上调用Start()方法,从而开启对指定端口的侦听.

使用 TCP / IP 套接字(Sockets)

使用TCP / IP 套接字(Sockets) TCP/IP 套接字提供了跨网络的低层控制.TCP/IP套接字是两台计算机之间的逻辑连接,通过它,计算机能够在任何时间发送或接收数据:这个连接一直保持,直到这台计算机显式发出关闭指令.它提供了高度的灵活性,但也带来了大量的问题,在这一章中我们会看到,因此,除非真的需要非常高度的控制,否则,最好还是使用更抽象的网络协议,在这一章的后面我们也会谈到. 为了使用TCP/IP 套接字所必须的类包含在命名空间System.Net,表 11-1 进行了汇总.

解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接

开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决方案都是千篇一律互相转发的,并且没有明确的解决方案或者按照,各个博客中的解决方案都没能解决这个问题. 为此我整整浪费了一天时间用来解决这个问题,而且用了最笨的办法一点点的尝试网上所查到的方案.对于精研WCF来说的这可能是一个小问题,但是对于仅仅了解wcf,一知半解的会很困惑.将解决方案贴出来希望能帮

[HTML5_WebSockets]HTML 5 Web Sockets应用初探

HTML 5之中一个很酷的新特性就是Web Sockets,在本文之前51CTO在<HTML 5 Web Socket:下一次Web通信革命揭幕>一文中已经详细的为大家介绍过HTML 5 Web Sockets为Web通信带来的改变,而本文将介绍通过PHP环境的服务器端运行Web Socket,创建客户端并通过Web Sockets协议发送和接收服务器端信息. 什么是Web Sockets? Web Sockets是在一个(TCP)接口进行双向通信的技术,PUSH技术类型.同时Web Sock

开源免费的C/C++网络库(c/c++ sockets library)

(1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boost开发的异步IO库,封装了Socket,简化基于socket程序的开发. 开源.免费,支持跨平台. http://think-async.com/ (3)POCO POCO C++ Libraries 提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程.线程同步.文件系统访问

Net.Sockets

1 #region 程序集 System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 2 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll 3 #endregion 4 5 using System.Collections; 6 using System.Colle