小弟现在我参与了一个项目组,要做一个教学系统。其中有个场景是这样的:每人一台机器,老师在自己的机器上打开的任何文件以及老师在自己机器上的任何操作,学生在自己的机器上都看得到!现在实现的思路是这样:对老师的机器做截屏操作,每隔若干毫秒截屏一次,然后将此截屏所得图形文件拆成6000字节大小的若干个向全局域网组播出去,每台学生机器接受这些包,并组装成图片,并显示在学生机器上,而且当有下一幅图片的包过来时接续接受,接受完之后刷新屏幕显示。
我负责的正是实现以上场景的这个模块,采用C/S架构。
服务器端:截屏并组播。代码核心部分用一个while死循环实现。
客户端: 接受并显示,并且每当新图形来的时候刷新并显示屏幕。核心部分也用一个while死循环实现。
服务器端while循环:
while(true){
try
{
//HighResolutionTimer timer = new HighResolutionTimer();
//timer.Start();
//截屏代码
img = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.AllScreens[0].Bounds.Size);
//将文件转化为流 发送
m = new MemoryStream();
img.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
m.Flush();
Byte[] b = m.GetBuffer();
//byte[] bytes = System.Text.Encoding.Unicode.GetBytes("This is a test Message");
//uc.Send(bytes, bytes.Length, iep);
m.Seek(0, SeekOrigin.Begin);
byte[] ReadBuffer = new byte[6000];
int i = 0;
for (i = 0; i <= (b.Length - 1) / 6000 - 1; i++)
{
m.Position = i * 6000;
m.Read(ReadBuffer, 0, 6000);
// i<=文件长度/6000,因为循环从0开始的。
//每次读6000个字节。一个数据报套接字上发送的消息大于内部消息缓冲器
uc.Send(ReadBuffer, ReadBuffer.Length, iep);
//每隔18毫秒发送一个UDP包
Thread.Sleep(18);
}
m.Position = i * 6000;
//最后一块
int count;
if (b.Length % 6000 == 0)
{ count = 6000; }
else
{
count = b.Length % 6000;
}
byte[] lastpiece = new byte[count];
m.Read(lastpiece, 0, lastpiece.Length);
uc.Send(lastpiece, lastpiece.Length, iep);
byte[] endSign = System.Text.Encoding.Unicode.GetBytes("it is over!");
uc.Send(endSign, endSign.Length, iep);
}
catch (Exception ee)
{
MessageBox.Show(ee.Message + ee.StackTrace);
}
}//end of while
客户端while循环接收并显示:
string str ="empty";
while (true)
{
//if (this.ipe.receive() > 0)
//{
// MessageBox.Show("有数据收到!");
//};
ArrayList a = new ArrayList();
do
{
byte[] bytes = uc.Receive(ref iep);
if ( bytes.Length > 0)
{
str = System.Text.Encoding.Unicode.GetString(bytes, 0, bytes.Length);
if (str != "it is over!")
a.Add(bytes);
}
} while (str != "it is over!" && str !="empty");
// a.Count;
Array b = a.ToArray();
Byte[] end = (Byte[])b.GetValue(b.Length - 1);
Byte[] bitmap = new Byte[(b.Length - 1) * 6000 + end.Length];
int t = 0;
for (int i = 0; i < b.Length; i++)
{
Byte[] temp = (Byte[])b.GetValue(i);
temp.CopyTo(bitmap, t);
t = t + temp.Length;
}
System.IO.MemoryStream ms = new System.IO.MemoryStream(bitmap, 0, bitmap.Length);
//这两句要研究一下
Bitmap bm = new Bitmap(ms, true);
bm.Save("e:\\2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
this.search.Visible = false;
this.start.Visible = false;
Image img = new Bitmap("e:\\2.jpg");
this.Size = img.Size;
this.pictureBox1.Image = bm;
//Thread.Sleep(1000);
//this.pictureBox1.Dispose();
a.Clear();
str = "empty";
//uc.Close();
}//end of while-loop
现在遇到的问题是:客户端之能显示一次,不能想预想中的刷新显示。而且有个GDI+的一般性错误出现,按照网上有个帖子解决GDI+一般性错误的终极解决方案,按照它做了,结果还是老样子。不过程序还是可以运行,但是客户端不行刷新显示,只显示第一次截屏图片。
情况紧急,请教各位大侠给小弟看看是啥原因,小弟跪谢各位的大恩大德了!!