i made a client and server socket based gui app in which screen is captured and via socket it is transfered to desired listner but i am getting a black out put image a recei
Just because you are sending the image with a single call to Send(...)
, it's very unlikely (unless the image is small, which if it's a screenshot, it probably isn't) that it will be received completely with a single call to Receive(...)
on the client side.
You will need to call Receive(...)
repeatedly, building up the received image buffer until Receive(...)
returns 0, indicating that the socket has been closed. You should then have the complete image for display.
I used tcp client and listner method and it worked fine but with one prob on the reciver side it only shows the 1/4 of the image and throws an exception connection was not established .. now what is the prb
public partial class Form1 : Form { private static Bitmap bmpScreenshot; bool start = false; private static Graphics gfxScreenshot;
public Form1()
{
InitializeComponent();
button2.Enabled = false;
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
start = true;
fillpic();
backgroundWorker1.RunWorkerAsync();
}
public void fillpic()
{
bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
pictureBox1.Image = bmpScreenshot;
}
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
start = false;
}
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
public void caal()
{
TcpClient TCPC = new TcpClient();
TCPC.Connect("127.0.0.1", 5002);
if (TCPC.Connected)
{
NetworkStream ns = TCPC.GetStream();
while (ns.CanWrite)
{
fillpic();
byte[] data = imageToByteArray(bmpScreenshot);
ns.Write(data, 0, data.Length);
}
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
caal();
}
}
Like @Iridium mentioned, you need to loop Read()-ing until no more data is received.
Also, please look at MemoryStream to replace all the array element shuffling. A simple Array.CopyTo would already be a vast improvent over the code you have to copy byte arrays
Here's a reasonably complete (albeit quick and dirty) solution:
Server:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace ImageServer
{
static class Program
{
static void Main()
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Bind(new IPEndPoint(IPAddress.Any, 23456));
socket.Listen(100);
while (true)
{
using (var client = socket.Accept())
{
var bounds = Screen.PrimaryScreen.Bounds;
var bitmap = new Bitmap(bounds.Width, bounds.Height);
try
{
while (true)
{
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(bounds.X, 0, bounds.Y, 0, bounds.Size);
}
byte[] imageData;
using (var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
imageData = stream.ToArray();
}
var lengthData = BitConverter.GetBytes(imageData.Length);
if (client.Send(lengthData) < lengthData.Length) break;
if (client.Send(imageData) < imageData.Length) break;
Thread.Sleep(1000);
}
}
catch
{
break;
}
}
}
}
}
}
}
Client (a form with a single button: "button1" and a single pictureBox: "pictureBox1"):
using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
namespace ImageClient
{
public partial class Form1 : Form
{
private Bitmap _buffer;
public Form1()
{
InitializeComponent();
}
private void Button1Click(object sender, EventArgs e)
{
button1.Enabled = false;
ThreadPool.QueueUserWorkItem(GetSnapshots);
}
private void GetSnapshots(object state)
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Connect(new IPEndPoint(IPAddress.Loopback, 23456));
while (true)
{
var lengthData = new byte[4];
var lengthBytesRead = 0;
while (lengthBytesRead < lengthData.Length)
{
var read = socket.Receive(lengthData, lengthBytesRead, lengthData.Length - lengthBytesRead, SocketFlags.None);
if (read == 0) return;
lengthBytesRead += read;
}
var length = BitConverter.ToInt32(lengthData, 0);
var imageData = new byte[length];
var imageBytesRead = 0;
while (imageBytesRead < imageData.Length)
{
var read = socket.Receive(imageData, imageBytesRead, imageData.Length - imageBytesRead, SocketFlags.None);
if (read == 0) return;
imageBytesRead += read;
}
using (var stream = new MemoryStream(imageData))
{
var bitmap = new Bitmap(stream);
Invoke(new ImageCompleteDelegate(ImageComplete), new object[] { bitmap });
}
}
}
}
private delegate void ImageCompleteDelegate(Bitmap bitmap);
private void ImageComplete(Bitmap bitmap)
{
if (_buffer != null)
{
_buffer.Dispose();
}
_buffer = new Bitmap(bitmap);
pictureBox1.Size = _buffer.Size;
pictureBox1.Invalidate();
}
private void PictureBox1Paint(object sender, PaintEventArgs e)
{
if (_buffer == null) return;
e.Graphics.DrawImage(_buffer, 0, 0);
}
}
}
Not sure what your actual problem is but I notice there is a potential bug in byteArrayToImage()
; you must keep the stream open for the lifetime of the image (yeah, it's not the most usable .NET API method!): http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx