在c#中通过socket类经常用计时器发送多个图片 [英] sending multiple pictures frequently with timer by socket class in c#
问题描述
我想从桌面发送图片,我是通过计时器获取的。客户端版本收到第一张图片,但没有从服务器版本的计时器获得另一张图片。
这是服务器版本代码:
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屋!