I simply want streaming capture screen with TCP protocol on C#.
private Bitmap bmpScreenshot;
private byte[] screenToByteArray()
{
byte[] result;
try
{
if (bmpScreenshot != null)
bmpScreenshot.Dispose();
bmpScreenshot = new Bitmap(SystemInformation.VirtualScreen.Width,
SystemInformation.VirtualScreen.Height,
PixelFormat.Format32bppArgb);
using (var gfxScreenshot = Graphics.FromImage(bmpScreenshot))
{
gfxScreenshot.CopyFromScreen(SystemInformation.VirtualScreen.X,
SystemInformation.VirtualScreen.Y,
0,
0,
SystemInformation.VirtualScreen.Size,
CopyPixelOperation.SourceCopy);
result = ImageToByte(bmpScreenshot);
}
}
catch (Exception ex)
{
Console.WriteLine("[ERROR]screenToByteArray Error..{0}", ex.Message);
result = null;
}
return result;
}
private byte[] ImageToByte(Image iImage)
{
if (mMemoryStream != null)
mMemoryStream.Dispose();
mMemoryStream = new MemoryStream();
iImage.Save(mMemoryStream, ImageFormat.Png);
if (iImage != null)
iImage.Dispose();
return mMemoryStream.ToArray();
}
I use that code part and I'm sending screenToByteArray() but I have a problem. If My screen does not have lots of image like that enter image description here, Listener can see correct display, but When my screen has complicated image(s) like that enter image description here , Listener sees distorted display like that enter image description here .When my screen has any complicate image, listener can't see the whole display. How can I do that. Thank for your help.
EDIT
I share my tcp code below
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.109"), 8500));
while(true)
{
try
{
byte[] sendData = screenToByteArray();
socket.Send(sendData, sendData.Length, SocketFlags.None);
sendData = null;
}
catch (Exception ex)
{
Console.WriteLine("[ERROR]sendScreen Error..{0}", ex.Message);
socket.Dispose();
break;
}
}
I did it. The streamed picture format has been changed.
private byte[] ImageToByte(Image iImage)
{
if (mMemoryStream != null)
mMemoryStream.Dispose();
mMemoryStream = new MemoryStream();
iImage.Save(mMemoryStream, ImageFormat.Jpeg);
if (iImage != null)
iImage.Dispose();
return mMemoryStream.ToArray();
}
Related
I have a problem. When I'm trying to send compressed file (byte[]) to server, and when decompress it, files do not match each other. I thought, problem is in the compress functions, but my client can compress and decompress byte array on his side. So, here's code:
Connection to server (client-side):
private void ConnectToServer() {
try {
_client = new TcpClient(_address, _port);
_stream = new SslStream(_client.GetStream(), true,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
try {
_stream.AuthenticateAsClient(_address);
_stream.Write(new byte[]{1});
} catch (AuthenticationException ex) {
_iClient.ExceptionHandler(ex);
_client.Close();
}
} catch (SocketException ex) {
_iClient.ExceptionHandler(ex);
_iClient.SuccessfulConnectionHandler();
Environment.Exit(0);
}
}
}
Accepting client (server-side):
private static void SetupServer() {
try {
IPAddress ipAddress;
if (!IPAddress.TryParse(_address, out ipAddress)) ipAddress = Dns.GetHostAddresses(_address)[0];
_listener = new TcpListener(ipAddress, _port);
_listener.Start();
WriteLine("\b\b\b - Успешно;");
WriteLine("Ожидание подключений...");
while (true) {
var client = _listener.AcceptTcpClient();
var sslStream = new SslStream(client.GetStream(), true);
try {
sslStream.AuthenticateAsServer(new X509Certificate(_certificate, _password),
false, SslProtocols.Tls, true);
WriteLine("{0} : [{1}] Успешное подключение",
DateTime.Now.ToString(CultureInfo.InvariantCulture),
(client.Client.RemoteEndPoint as IPEndPoint)?.Address);
new Thread(() => ProcessClient(client, sslStream)).Start();
} catch (AuthenticationException e) {
sslStream.Close();
client.Close();
}
}
} catch (Exception ex) {
WriteLine(ex.Message);
WriteLine(ex.StackTrace);
} finally {
_listener?.Stop();
}
}
And my compression fuctions:
byte[] Compress1(byte[] data) {
using (var compressedStream = new MemoryStream())
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) {
zipStream.Write(data, 0, data.Length);
zipStream.Close();
return compressedStream.ToArray();
}
}
byte[] Decompress1(byte[] data) {
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream()) {
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
So. Why does it happend?
And here is some extra information: I use ssl connection, I have problems only with big files, I can save files without compression.
I don't know why, but there are some features in sslstream. At first you can get only 1 byte (even if buffer size is much larger) and you should read remaining byte by calling Read function once more. But that's not my problem about. The maximum size of buffer you can get by calling reading function once is 16227
I was able to send image from server to client . there is two image when one comes after another it display like a video, but now i want to stream a video from my client to server. I want to stream the file from my own localhost.
Sending
private void Start_Sending_Video_Conference(string remote_IP, int port_number)
{
try
{
ms = new MemoryStream();// Store it in Binary Array as Stream
IDataObject data;
Image bmap;
// Copy image to clipboard
SendMessage(hHwnd, WM_CAP_EDIT_COPY, 0, 0);
// Get image from clipboard and convert it to a bitmap
data = Clipboard.GetDataObject();
if (data.GetDataPresent(typeof(System.Drawing.Bitmap)))
{
bmap = ((Image)(data.GetData(typeof(System.Drawing.Bitmap))));
bmap.Save(ms, ImageFormat.Bmp);
}
picCapture.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] arrImage = ms.GetBuffer();
myclient = new TcpClient(remote_IP, port_number);//Connecting with server
myns = myclient.GetStream();
mysw = new BinaryWriter(myns);
mysw.Write(arrImage);//send the stream to above address
ms.Flush();
mysw.Flush();
myns.Flush();
ms.Close();
mysw.Close();
myns.Close();
myclient.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Video Conference Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Receiving
private void Start_Receiving_Video_Conference()
{
try
{
// Open The Port
mytcpl = new TcpListener(6000);
mytcpl.Start(); // Start Listening on That Port
mysocket = mytcpl.AcceptSocket(); // Accept Any Request From Client and Start a Session
ns = new NetworkStream(mysocket); // Receives The Binary Data From Port
picture_comming.Image = Image.FromStream(ns);
mytcpl.Stop(); // Close TCP Session
if (mysocket.Connected == true) // Looping While Connected to Receive Another Message
{
while (true)
{
Start_Receiving_Video_Conference(); // Back to First Method
}
}
myns.Flush();
}
catch (Exception) { button1.Enabled = true; myth.Abort(); }
}
so how should i stream a video file in my client end where the file is in my server.
I try to receive a desktop screen capture from my PC using WPF (Client and server side WPF)
here is my code
private void ViewReceivedImage(byte[] buffer)
{
try
{
using (MemoryStream memoryStream = new MemoryStream(buffer))
{
BitmapImage imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = memoryStream;
imageSource.EndInit();
// Assign the Source property of your image
MyImage.Source = imageSource;
}
//MemoryStream ms = new MemoryStream(buffer);
//BitmapImage bi = new BitmapImage();
//bi.SetSource = ms;
//MyImage.Source = bi;
//ms.Close();
}
catch (Exception) { }
finally
{
StartReceiving();
}
}
The commented line above are for Windows phone app, I have already tested it and it works with WP8(Client Side), I have the problem only on WPF Client Side.
WPF Server Side and WP8 Client Side works
WPF Client Side not working but connection is successful
this method sends the image
void StartSending()
{
while (!stop)
try
{
System.Drawing.Image oldimage = scr.Get_Resized_Image(wToCompare, hToCompare, scr.GetDesktopBitmapBytes());
//Thread.Sleep(1);
System.Drawing.Image newimage = scr.Get_Resized_Image(wToCompare, hToCompare, scr.GetDesktopBitmapBytes());
byte[] buffer = scr.GetDesktop_ResizedBytes(wToSend, hToSend);
//float difference = scr.difference(newimage, oldimage);
//if (difference >= 1)
//{
SenderSocket.Send(buffer);
//}
}
catch (Exception) { }
}
and this Get_Resized_Image
public Image Get_Resized_Image(int w, int h, byte[] image)
{
MemoryStream ms = new MemoryStream(image);
Image bt = Image.FromStream(ms);
try
{
Size sizing = new Size(w, h);
bt = new System.Drawing.Bitmap(bt, sizing);
}
catch (Exception) { }
return bt;
}
edited
this is the output
I'm trying C# sockets to send images. It works, but it's unstable. The images sent through are quite large and are updated very quickly which causes it to flicker every now and then. I'm looking for a way to compress the data sent if possible. I'm using this code:
Server side:
System.IO.MemoryStream stream = new System.IO.MemoryStream();
// !! Code here that captures the screen !!
bitmap.Save(stream, myImageCodecInfo, myEncoderParameters);
byte[] imageBytes = stream.ToArray();
stream.Dispose();
// Send the image
clientSocket.Send(imageBytes);
// Empty the byte array?
for (int i = 0; i < imageBytes.Length; i++)
{
imageBytes[i] = 0;
}
Client side:
private void OnConnect(IAsyncResult ar)
{
try
{
MessageBox.Show("Connected");
//Start listening to the data asynchronously
clientSocket.BeginReceive(byteData,
0,
byteData.Length,
SocketFlags.None,
new AsyncCallback(OnReceive),
null);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Stream Error",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void OnReceive(IAsyncResult ar)
{
try
{
int byteCount = clientSocket.EndReceive(ar);
// Display the image on the pictureBox
MemoryStream ms = new MemoryStream(byteData);
pictureBox1.Image = Image.FromStream(ms);
}
catch (ArgumentException e)
{
//MessageBox.Show(e.Message);
}
clientSocket.BeginReceive(byteData,0,byteData.Length,SocketFlags.None,new AsyncCallback(OnReceive),null);
}
I ended up using gzip.
Turns out the flicker wasn't due to it being updated very quickly, but was because of the way I had sockets set up. It wasn't sending the whole image.
I am trying to set up two programs in C#. Basically, a simple client server set up where I want the server to listen for an image from the client. Then, upon receiving the image, will display it in a PictureBox.
I keep running into the following error:
A first chance exception of type
'System.ArgumentException' occurred in
System.Drawing.dll
The error is happening on the server code that is listening at this line:
Image bmp = Image.FromStream(ms);
Any ideas?
The Server code that listens:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace NetView
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
startListening();
}
private void startListening()
{
////////////////////////////////////////////
Console.WriteLine("Server is starting...");
byte[] data = new byte[1024];
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
Socket newsock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
newclient.Address, newclient.Port);
while (true)
{
data = ReceiveVarData(client);
MemoryStream ms = new MemoryStream(data);
try
{
Image bmp = Image.FromStream(ms);
pictureBox1.Image = bmp;
}
catch (ArgumentException e)
{
Console.WriteLine("something broke");
}
if (data.Length == 0)
newsock.Listen(10);
}
//Console.WriteLine("Disconnected from {0}", newclient.Address);
client.Close();
newsock.Close();
/////////////////////////////////////////////
}
private static byte[] ReceiveVarData(Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv = s.Receive(datasize, 0, 4, 0);
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv = s.Receive(data, total, dataleft, 0);
if (recv == 0)
{
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
The Client Code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Drawing;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
byte[] data = new byte[1024];
int sent;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
Console.ReadLine();
}
Bitmap bmp = new Bitmap("c:\\eek256.jpg");
MemoryStream ms = new MemoryStream();
// Save to memory using the Jpeg format
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
// read to end
byte[] bmpBytes = ms.GetBuffer();
bmp.Dispose();
ms.Close();
sent = SendVarData(server, bmpBytes);
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
Console.ReadLine();
}
private static int SendVarData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(size);
sent = s.Send(datasize);
while (total < size)
{
sent = s.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
return total;
}
}
}
ArgumentException tells you that the image format in the stream is invalid. Which is probably caused by the client application closing the memory stream before the data were sent.
Try replacing byte[] bmpBytes = ms.GetBuffer(); with
byte[] bmpBytes = ms.ToArray();
Or close the stream after the data were sent.
Remember that the byte-array returned by the .GetBuffer() returns the underlying array, not a copy of it (.ToArray() returns a copy), that is valid as long as the parent stream.
If you have access to the JPG file itself (as in the example), you should send the file bytes and not use the Image/Bitmap classes. By reading a JPG file and re-encoding into JPG you are decreasing the image quality and incurring unnecessary overhead. You can use File.ReadAllBytes() to quickly get the complete byte[] or read/send it in pieces if your memory space is limited.
A better way to send the image would be to use BinaryFormatter.
eg, some snippets from my own code to send an image every second...
sending:
TcpClient client = new TcpClient();
try
{
client.Connect(address, port);
// Retrieve the network stream.
NetworkStream stream = client.GetStream();
MessageData data = new MessageData(imageToSend);
IFormatter formatter = new BinaryFormatter();
while(true)
{
formatter.Serialize(stream, data);
Thread.Sleep(1000);
data.GetNewImage();
}
}
receiving:
TcpListener listener = new TcpListener(address, port);
listener.Start();
try
{
using (TcpClient client = listener.AcceptTcpClient())
{
stream = client.GetStream();
IFormatter formatter = new BinaryFormatter();
while (true)
{
MessageData data = (MessageData)formatter.Deserialize(stream);
if (ImageReceivedEvent != null) ImageReceivedEvent(data.Picture);
}
}
}
and the MessageData class simply holds the image and has the [Serializable] attribute.
Use Arul's code to get the data to send correctly -- you want .ToArray(), not .GetBuffer(). Then, you'll want to run the server's 'startListening' method on a background thread or you won't actually see anything (as the form thread will be busy running the server code. Try:
var t = new Thread(startListening);
t.IsBackground = true;
t.start();
In your Form_Load method instead of directly calling startListening in your constructor.
Here is a code that works for me. User starts server with a button and client selects photo by opening the file dialog of computer. At last sends the image but be careful about the photo size because UDP cannot transmit much large data.
Server:
delegate void showMessageInThread(string message);
UdpClient listener = null;
IPEndPoint endpoint = null;
Thread listenThread = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
startServer();
}
private void startServer()
{
endpoint = new IPEndPoint(IPAddress.Any, 1234);
listener = new UdpClient(endpoint);
ShowMsg("Waiting for a client!");
listenThread = new Thread(new ThreadStart(Listening));
listenThread.Start();
}
private void Listening()
{
while (true)
{
//take the coming data
byte[] comingDataFromClient = listener.Receive(ref endpoint);
ImageConverter convertData = new ImageConverter();
Image image = (Image)convertData.ConvertFrom(comingDataFromClient);
pictureBox1.Image = image;
}
private void ShowMsg(string msg)
{
this.richTextBox1.Text += msg + "\r\n";
}
Client:
Socket server = null;
MemoryStream ms;
IPEndPoint endpoint = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
server = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234);
}
private void btn_browse_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
string path = openFileDialog1.FileName;
pictureBox1.Image = Image.FromFile(path);
textPath.Text = path;
}
private void btn_send_Click(object sender, EventArgs e)
{
try
{
ms = new MemoryStream();
Bitmap bmp = new Bitmap(this.openFileDialog1.FileName);
bmp.Save(ms, ImageFormat.Jpeg);
byte[] byteArray = ms.ToArray();
server.Connect(endpoint);
server.SendTo(byteArray, endpoint);
}
}
catch (Exception ex)
{
}
data = ReceiveVarData(client);
MemoryStream ms = new MemoryStream(data);
Image bmp = Image.FromStream(ms);
pictureBox1.Image = bmp;
The error may due to corrupted or incomplete bmp image received in the MemoryStream
it worked fine for me after increasing the socket send/receive buffers values
adjust the sender "Socket.SendBufferSize" and the receiver "Socket.ReceiveBufferSize" to large values for example = 1024 * 2048 *10
this will help sending the entire image at once.
or another solution is to check whether the received data size (data.length) is the same as the sent image data size, before the code line of forming the received image stream