通过TCP连接C#发送图像 [英] SEND IMAGE OVER TCP CONNECTION C#

查看:95
本文介绍了通过TCP连接C#发送图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

我必须为大学课程做一个应用程序客户端服务器.

服务器必须获取桌面,将其显示在pictureBox中,然后通过tcp连接将图像发送到客户端(或更多客户端).

服务器必须连续发送图像(如小视频)或停止发送(按钮上的事件).

不幸的是,我遇到了这个错误:二进制通量不包含有效的二进制头;这是由于无效的通量或序列化和反序列化之间对象版本的变化引起的."

请帮助我,我很拼命! Sissi

Hi everyone,

I must do an application client-server for a university course.

The server must acquire the desktop, show it in a pictureBox, then send the image over tcp connection to the client (or to more clients).

The server must send the images continuously (like a little video) or to stop the send (event on a button).

Unluckily I''ve this error: "The binary flux doesn''t contain a valid binary header; that due to a non-valid flux or a change on the version of the object between serialization and deserialization".

Please help me, I''m desperate!!!
Sissi

推荐答案

我的程序运行3次(按钮startCapture-stopCapture,startCapture-stopCapture和ERROR)

SERVER(VideoServer类,与主要形式分开)

My program run 3 times (buttons startCapture-stopCapture, startCapture-stopCapture, then ERROR)

SERVER(class VideoServer, separate from main form)

namespace ChatServer
{
    class VideoServer
    {
        // The thread that will hold the connection listener
        private Thread thrListener;
        private Thread thrCapturing;
        // The TCP object that listens for connections
        private TcpListener tlsClient;
        // Will tell the while loop to keep monitoring for connections
        bool ServRunning = false;
        public static List<tcpclient> ClientList = new List<tcpclient>();
   
        private TcpClient tcpClient;
     
        public Image img;
        public Image img1;
        public event EventHandler sendPicture;
        public Form1 padre;

       public VideoServer(Image image, Form1 dad)
       {
          img = image;
          padre = dad;  
           
       }

        public void StartListening()
        {
            // Create the TCP listener object using the IP of the server and the specified port
            tlsClient = new TcpListener(3700);


            // Start the TCP listener and listen for connections
            tlsClient.Start();

            // The while loop will check for true in this before checking for connections
            ServRunning = true;

            thrListener = new Thread(KeepListening);
            thrListener.Start();

        }

        private void KeepListening()
        {
            // While the server is running
            while (ServRunning == true)
            {
                // Accept a pending connection
                tcpClient = tlsClient.AcceptTcpClient();

                // Create a new instance of Connection
                ConnectionImage newConnection = new ConnectionImage(tcpClient);
            }
        }

        public void StartCapturing()
        { 
         thrCapturing = new Thread(KeepCapturing);
         thrCapturing.Start();
        }

        public void KeepCapturing()
        {
            while (true)
            {
                
                Console.WriteLine("DEBUG: Server--> Entra nel While");
                ScreenCapture sc = new ScreenCapture(); // capture entire screen
                img = sc.CaptureScreen();
                img1 = (Image)img.Clone();
                padre.setImage(img1);
                //if (img != null) //If you choosed an image
                //{
                    //videoServer.SendImage(img); //Send the image
                    this.SendImage(img);
                //}

            }
        }

        public void StopCapturing()
        {
            thrCapturing.Abort();
            
           /* //codice per deallocare memoria
            IntPtr ptr = Marshal.AllocHGlobal(1024);
            GC.AddMemoryPressure(1024);
            if (ptr != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(ptr);
                ptr = IntPtr.Zero;
                GC.RemoveMemoryPressure(1024);
            }
            */
        }

         // Add the user to the List
        public static void AddUser(TcpClient tcpUser)
        {
            ClientList.Add(tcpUser);
        }

        // Remove the user from the hash tables
        public static void RemoveUser(TcpClient tcpUser)
        {

                ClientList.Remove(tcpUser);
        }

        private  void CloseConnection(TcpClient tcpCon)
        {
            // Close the currently open objects
            tcpCon.Close();
        }

        public void SendImage(Image img)
        {
            for (int i = 0; i < ClientList.Count; i++)
            {
                TcpClient tempClient = (TcpClient)ClientList[i];
                if (tempClient.Connected) //If the client is connected
                {
                     BinaryFormatter formatter = new BinaryFormatter();
                     formatter.Serialize(tempClient.GetStream(), img);
                     //Serialize the image to the tempClient NetworkStream
                 }
                 else
                 {
                     ClientList.Remove(tempClient);
                     i--;
                 }

              
            }
        }

    }

    class ConnectionImage 
    {
        TcpClient tcpCon;
        // The thread that will send information to the client
        private Thread thrSender;

        // The constructor of the class takes in a TCP connection
        public ConnectionImage(TcpClient tcpClient)
        {
             tcpCon=tcpClient;
            // The thread that accepts the client and awaits messages
            thrSender = new Thread(AcceptClient);
            // The thread calls the AcceptClient() method
            thrSender.Start();
        }
 
        private void AcceptClient()
        {
          VideoServer.AddUser(tcpCon);
        }


    }
}

</tcpclient></tcpclient>




客户部分




CLIENT''S PART

//StartConnectionVideo();
        Client = new TcpClient();
         Client.Connect("127.0.0.1", 3700);
         //Connect to 127.0.0.1 on port 3700
         readingThread = new Thread(new ThreadStart(StartReading));
         //Start a new thread to receive images

         readingThread.Start();
     }


 private void StartReading()
        {
            while (true)
            {
             
                NetworkStream stream = Client.GetStream();
                    BinaryFormatter formatter = new BinaryFormatter();
                
                        Image img = (Image)formatter.Deserialize(stream);
                        //Deserialize the image from the NetworkStream
                        pictureBox.Image = img; //Show the image in the picturebox
                    
                  }
              
            }


TCP不一定每次发送都会给您一个接收;这里特别重要的是,您可以获得部分接收,这是一条不完整的消息,可能会导致反序列化失败,并且您可以获取合并的接收(即,上一条消息的最后一部分和下一条消息的第一部分)合并在一起),如果您在每个接收到的块的开头尝试反序列化,肯定会导致失败.

在尝试将内容用于任何内容之前,您需要先对流进行重新打包"(或消息传递"或任何数量的虚构词).由于您正在发送二进制数据,因此定界符将是不可靠的,因此您应该在每条消息的开头发送大小指示,并缓冲存储,直到读取了许多字节为止,以形成完整的消息.这并不像看起来那么琐碎,因为您可以获得部分或仅包含标头一部分的部分读取(是的,即使标头只有4个字节).有关如何处理它的示例,请参见我的套接字库文章中的ClientInfo.ReadInternal.
TCP won''t necessarily give you a single receive per send; of particular relevance here is that you can get a partial receive, which is an incomplete message and which will possibly cause deserialisation to fail, and you can get a combined receive (i.e. the last part of the previous message and the first part of the next mushed together) which, if you''re trying to deserialise at the start of each received block, will definitely cause a failure.

You need to ''repacketise'' (or ''messagise'' or any number of made up words) the stream before trying to use the contents for anything. Since you''re sending binary data, a delimiter will be unreliable, so you should send a size indication at the start of each message and buffer the storage until that many bytes have been read, to form a complete message. This isn''t as trivial as it might appear, because you can get a partial or combined read that includes only a part of the header (yes, even if the header is only 4 bytes). See ClientInfo.ReadInternal in my sockets library article for an example of how to handle it.


您能给我写一部分代码吗?
can you write me a portion of code may I use?


这篇关于通过TCP连接C#发送图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆