在c#中通过socket类经常用计时器发送多个图片 [英] sending multiple pictures frequently with timer by socket class in c#

查看:62
本文介绍了在c#中通过socket类经常用计时器发送多个图片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从桌面发送图片,我是通过计时器获取的。客户端版本收到第一张图片,但没有从服务器版本的计时器获得另一张图片。

这是服务器版本代码:




I want to send the pictures from my desktop which I get them by a timer. the client version receives the first picture and doesn't get another picture from timer of server version.
this is the server version code:


using System.Net;
using System.IO;
using System.Net.Sockets;
Graphics g;
byte[] msg = new byte[1024];
int msglen;
byte[] sendmsg = new byte[1024];
Socket sktlis;
byte[] ib = new byte[20000];

private void btnConnect_Click(object sender, EventArgs e)
    {
        sktlis = new Socket(AddressFamily.InterNetwork, SocketType.Stream,        ProtocolType.Tcp);
        IPEndPoint iplocal = new IPEndPoint(IPAddress.Any, Convert.ToInt32(txtPort.Text));
        sktlis.Bind(iplocal);
        sktlis.Listen(1);
        lblStatus.Text = "connected";
        sktlis = sktlis.Accept();
        tt = true;
        timer2.Enabled = true;
    }

   private void timer2_Tick(object sender, EventArgs e)
    {

        Bitmap bmpScreenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
        g = Graphics.FromImage(bmpScreenCapture);
        g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                     Screen.PrimaryScreen.Bounds.Y,
                     0, 0,
                     bmpScreenCapture.Size,
                     CopyPixelOperation.SourceCopy);
        MemoryStream ms = new MemoryStream();

        bmpScreenCapture.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
        ib = ms.ToArray();
        Image aa = Image.FromStream(ms);
        Bitmap objBitmap = new Bitmap(aa, new Size(500, 200));
        picR.Image = objBitmap;
        sktlis.Send(ib);


    }





这是客户版本:





and this is the client version:

 byte[] msg = new byte[20000];
    byte[] msgtest = new byte[20000];
    int  msglen;
    MemoryStream msc = new MemoryStream();
    Image aa;
    Boolean tt = false;
    static Socket sktlisc;
    byte[] answer = new byte[1024];

private void btnConnect_Click(object sender, EventArgs e)
{
    sktlisc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPHostEntry iphe = Dns.Resolve(txtIc.Text);
    IPAddress ipa = iphe.AddressList[0];
    IPEndPoint iplocal = new IPEndPoint(ipa,Convert.ToInt32(txtPort.Text));
    sktlisc.Connect(iplocal);
    lblStatus.Text = "Connected";
    tt = true;
    timer1.Enabled = true;
}

private void timer1_Tick(object sender, EventArgs e)
{

    if (tt)
    {
        if (sktlisc.Available != 0)
        {
            msglen = sktlisc.Receive(msg);

            msc.Write(msg, 0, msglen);
            aa = Image.FromStream(msc);

            Bitmap objBitmap = new Bitmap(aa, new Size(500, 200));

            picR.Image = objBitmap;

        }
    }
}

推荐答案



对不起,我很抱歉。关于客户/服务器的一些想法。


Sorry for the delay. Some thoughts on client/servers.



客户总是控制交互。这意味着服务器在客户端联系之前是静默的(服务器实际上处于某种形式的侦听状态)。这意味着你使用推送是错误的。服务器端应该没有计时器。只有当客户端连接到服务器时,服务器才应准备并发送数据。


The client always controls the interaction. This means that the server is silent until contacted by the client (the server is actually in some form of listening state). This means that your use of a push is wrong. There should be no timer on the server side. Only when the client connects to the server should the server prepare and send the data.



客户端,我建议你最初不要使用计时器。它只是混淆了调试过程。而是每次单击连接按钮时,客户端连接到服务器并等待服务器的响应。


On the client side, I'd suggest that you initially not use a timer. It just confuses the debugging process. Rather each time that a "connect" button is clicked, the client connects to the server and awaits the server's response.



这是典型的客户端/服务器范例。


This is the classic client/server paradigm.



您正在收集大量数据。我的显示器屏幕分辨率是1920x1080。这是需要传输的8294400字节。由于您选择了TCP(而不是UDP),因此图像需要大约5525个数据包才能从服务器传输到客户端(假设MTU为1400字节,即标称值)。在16mbit / sec的带宽下,该数据量将(最佳地)超过四秒。因此,您的计时器必须设置为大于该值。如果您遵循我的建议,即服务器仅在联系时响应,则客户端可以调整其连接时间以考虑传输时间。请参阅 TCP连接的最大数据包大小 [ ^ ]讨论MTU。


You are collecting an enormous amount of data. My monitor screen resolution is 1920x1080. That's 8294400 bytes that need to be transmitted. Since you have chosen TCP (rather than UDP), the image requires about 5525 packets to cross from the server to the client (assuming an MTU of 1400 bytes, a nominal value). At a bandwidth of 16mbit/sec, that amount of data will take (optimally) more than four seconds. So your timer must be set to greater than that value. If you follow my recommendation that server only responds when contacted, then the client can adjust its connect timing to account for the transit time. See maximum packet size for a TCP connection[^] for a discussion of MTU.



如果您只能专注于桌面上的一个窗口,可以通过多种方式捕获该窗口的图像。这将显着减少您必须传输的数据量。以下代码执行图像捕获窗口。


If you can concentrate on only one window on the desktop, there are ways in which an image of that window can be captured. That will significantly reduce that amount of data you must transmit. The following code performs the window to image capture.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;

// **************************************** class CaptureDesktopWindow

public class CaptureDesktopWindow
    {

    const int SRCCOPY = 0x00CC0020;     // BitBlt dwRop

    [ StructLayout ( LayoutKind.Sequential ) ]
    struct RECT
        {
        public int left;
        public int top;
        public int right;
        public int bottom;
        }

    [ DllImport ( "gdi32.dll" ) ]
    static extern bool BitBlt ( IntPtr   hObject, 
                                int      nXDest, 
                                int      nYDest,
                                int      nWidth, 
                                int      nHeight, 
                                IntPtr   hObjectSource,
                                int      nXSrc, 
                                int      nYSrc, 
                                int      dwRop );

    [ DllImport ( "gdi32.dll" ) ]
    static extern IntPtr CreateCompatibleBitmap ( IntPtr hDC, 
                                                  int nWidth,
                                                  int nHeight );

    [ DllImport ( "gdi32.dll" ) ]
    static extern IntPtr CreateCompatibleDC ( IntPtr hDC );

    [ DllImport ( "gdi32.dll" ) ]
    static extern bool DeleteDC ( IntPtr hDC );

    [ DllImport ( "gdi32.dll" ) ]
    static extern bool DeleteObject ( IntPtr hObject );

    [ DllImport ( "user32.dll" ) ]
    static extern IntPtr GetWindowDC ( IntPtr hWnd );

    [ DllImport ( "user32.dll" ) ]
    static extern IntPtr GetWindowRect (     IntPtr hWnd, 
                                         ref RECT rect );

    [ DllImport ( "user32.dll" ) ]
    static extern IntPtr ReleaseDC ( IntPtr hWnd, 
                                     IntPtr hDC );

    [ DllImport ( "gdi32.dll" ) ]
    static extern IntPtr SelectObject ( IntPtr hDC, 
                                        IntPtr hObject );


    // ************************************************** window_image

    /// <summary>
    /// obtains the image of the desktop window with the given handle
    /// </summary>
    /// <param name="handle">
    /// handle to the window
    /// </param>
    /// <returns>
    /// if successful, image of the window whose handle was passed; 
    /// otherwise, null
    /// </returns>
    public static Image window_image ( IntPtr handle )
        {
        IntPtr  hBitmap = IntPtr.Zero;
        IntPtr  hdcDest = IntPtr.Zero;
        IntPtr  hdcSrc = IntPtr.Zero;
        IntPtr  hOld = IntPtr.Zero;
        int     height = 0;
        Image   image = null;
        int     width = 0;
        RECT    windowRect;

        try
            {
                                        // get the hDC of the window 
            hdcSrc = GetWindowDC ( handle );
                                        // get the size
            windowRect = new RECT ( );
            GetWindowRect ( handle, ref windowRect );
            width = windowRect.right - windowRect.left;
            height = windowRect.bottom - windowRect.top;
                                        // create a device context to 
                                        // which we can copy
            hdcDest = CreateCompatibleDC ( hdcSrc );
                                        // create a bitmap to which we 
                                        // can copy
            hBitmap = CreateCompatibleBitmap ( hdcSrc, 
                                               width, 
                                               height );
                                        // select the bitmap object
            hOld = SelectObject ( hdcDest, hBitmap );
                                        // bitblt the image
            BitBlt ( hdcDest,
                     0,
                     0,
                     width,
                     height,
                     hdcSrc,
                     0,
                     0,
                     SRCCOPY );
                                        // restore selection
            SelectObject ( hdcDest, hOld );
                                        // get the .NET image object
            image = Image.FromHbitmap ( hBitmap );
            }
        catch
            {
            image = null;
            }
        finally
            {
                                        // clean up 
            if ( hdcDest != IntPtr.Zero );
                {
                DeleteDC ( hdcDest );
                }
            if ( hdcSrc != IntPtr.Zero )
                {
                ReleaseDC ( handle, hdcSrc );
                }
            if ( hBitmap != IntPtr.Zero )
                {
                DeleteObject ( hBitmap );
                }
            }

        return ( image );
        }

    // ****************************************** capture_window_image

    /// <summary>
    /// obtains the image of the desktop window with the given title
    /// </summary>
    /// <param name="title">
    /// string containing the title of the window
    /// </param>
    /// <returns>
    /// if successful, image of the window whose title was passed; 
    /// otherwise, null
    /// </returns>
    public static Image capture_window_image ( string title )
        {
        Image   image = null;
        IntPtr  window_handle = IntPtr.Zero;
                                        // get window handle
        foreach ( Process process in Process.GetProcesses ( ) )
            {
            if ( process.MainWindowTitle.
                         ToLower ( ).
                         Trim ( ).
                         StartsWith ( title.ToLower ( ).
                                            Trim ( ) ) )
               {
               window_handle = process.MainWindowHandle;
               break;
               }
            }

        if ( window_handle != IntPtr.Zero )
            {
            image = window_image ( window_handle );
            }

        return ( image );
        }

    } // class CaptureDesktopWindow





调用


It is invoked by

Image   image = CaptureDesktopWindow.capture_window_image ( "Dynamic Update" );



在这种情况下,桌面上有一个标题为动态更新的窗口。


In this case, there is a window titled "Dynamic Update" on the desktop.



希望有所帮助。


Hope that helps.


这篇关于在c#中通过socket类经常用计时器发送多个图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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