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 receiver end or client the image is there at server but cannot show it in my client app it just show a black pic?
code as : server
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.Drawing.Imaging;
using System.Net.Sockets;
using System.IO;
using System.Net;
namespace LanMonitoring
{
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();
}
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;
sendbmp(bmpScreenshot);
}
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
start = false;
}
public void sendbmp(Bitmap bmp)
{
Socket mm = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(textBox1.Text), 5002);
try
{
mm.Connect(remoteEP);
}
catch (Exception)
{
sendbmp(bmpScreenshot);
}
Image temp = bmp;
byte[] buf = imageToByteArray(temp);
mm.Send(buf);
mm.Close();
}
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
}
}
client as:
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.Net.Sockets;
using System.IO;
using System.Net;
namespace LanReciver
{
public partial class Client : Form
{
byte[] buf = new byte[5000];
public Client()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
public void call()
{
Socket mm = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mm.Bind(new IPEndPoint(0, 5002));
mm.Listen(100);
Socket acc = mm.Accept();
buf = new byte[acc.SendBufferSize];
int byteread = acc.Receive(buf);
byte[] rev = new byte[byteread];
for (int i = 0; i < byteread; i++)
{
rev[i] = buf[i];
}
byteArrayToImage(rev);
mm.Close();
acc.Close();
call();
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
call();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Recieved");
}
}
}
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);
}
}
}
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.
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
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
Related
I need some help for one part of my project. I need webcam to capture 3 images in 2-seconds intervals triggered by motion detector. Here is my code. The problem is I have three times the same image (the first one).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.ComponentModel;
using System.Data;
using System.Threading.Tasks;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Data.SqlClient;
using System.Drawing;
using System.Threading;
namespace pro
{
class Program
{
static SerialPort serialPort = new SerialPort("COM4", 9600);
static FilterInfoCollection WebcamColl;
static VideoCaptureDevice Device;
static int no = 1;
static void Main(string[] args)
{
if (!serialPort.IsOpen)
serialPort.Open();
Console.WriteLine("");
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
Console.ReadKey();
}
static void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string _read = serialPort.ReadExisting().ToString();
if (_read == "ERROR" )
{
WebcamColl = new FilterInfoCollection(FilterCategory.VideoInputDevice);
Device = new VideoCaptureDevice(WebcamColl[0].MonikerString);
Device.Start();
Device.NewFrame += new NewFrameEventHandler( Device_NewFrame);
Console.ReadLine();
}
}
static void Device_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
for (int i = 0; i < 3; i++)
{
System.Drawing.Image img = (Bitmap)eventArgs.Frame.Clone();
string imagePath;
string fileName = "Image";
fileName = fileName + no.ToString() + ".jpg";
img.Save("D:\\aaaa\\" + fileName);
Thread.Sleep(2000);
Console.WriteLine("Snapshot Saved.");
imagePath = "D:\\aaaa\\" + fileName;
FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] _image = br.ReadBytes((int)fs.Length);
br.Close();
fs.Close();
SqlConnection conn = new SqlConnection("Data source=ULTRASLAN\\SQLEXPRESS; Initial Catalog=veritabani; Integrated Security=true");
SqlCommand kmt = new SqlCommand("insert into _imageler(_image,kullanici_id,tarih) Values (#image,22,getdate())", conn);
kmt.Parameters.Add("#image", SqlDbType.Image, _image.Length).Value = _image;
try
{
conn.Open();
kmt.ExecuteNonQuery();
Console.WriteLine(" Saving image to the database successfull..");
no++;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
finally
{
conn.Close();
}
}
Device.SignalToStop();
}
}
}
I'm currently converting someone else's code. It is written in C# Windows FORM. and I want it to be in C# WPF.
this is the original code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace FileReceiver
{
public partial class MainForm : Form
{
const int PORT = 1723;
public MainForm()
{
InitializeComponent();
}
private void resetControls()
{
progressBar1.Style = ProgressBarStyle.Marquee;
textBox1.Text = "Waiting for connection...";
}
protected override async void OnShown(EventArgs e)
{
// Listen
TcpListener listener = TcpListener.Create(PORT);
listener.Start();
textBox1.Text = "Waiting for connection...";
TcpClient client = await listener.AcceptTcpClientAsync();
NetworkStream ns = client.GetStream();
// Get file info
long fileLength;
string fileName;
{
byte[] fileNameBytes;
byte[] fileNameLengthBytes = new byte[4]; //int32
byte[] fileLengthBytes = new byte[8]; //int64
await ns.ReadAsync(fileLengthBytes, 0, 8); // int64
await ns.ReadAsync(fileNameLengthBytes, 0, 4); // int32
fileNameBytes = new byte[BitConverter.ToInt32(fileNameLengthBytes, 0)];
await ns.ReadAsync(fileNameBytes, 0, fileNameBytes.Length);
fileLength = BitConverter.ToInt64(fileLengthBytes, 0);
fileName = ASCIIEncoding.ASCII.GetString(fileNameBytes);
}
// Get permission
if (MessageBox.Show(String.Format("Requesting permission to receive file:\r\n\r\n{0}\r\n{1} bytes long", fileName, fileLength), "", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;
}
// Set save location
SaveFileDialog sfd = new SaveFileDialog();
sfd.CreatePrompt = false;
sfd.OverwritePrompt = true;
sfd.FileName = fileName;
if (sfd.ShowDialog() != DialogResult.OK)
{
ns.WriteByte(0); // Permission denied
return;
}
ns.WriteByte(1); // Permission grantedd
FileStream fileStream = File.Open(sfd.FileName, FileMode.Create);
// Receive
textBox1.Text = "Receiving...";
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.Value = 0;
int read;
int totalRead = 0;
byte[] buffer = new byte[32 * 1024]; // 32k chunks
while ((read = await ns.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, read);
totalRead += read;
progressBar1.Value = (int)((100d * totalRead) / fileLength);
}
fileStream.Dispose();
client.Close();
MessageBox.Show("File successfully received");
resetControls();
}
}
}
I've successfully converted all the things in this code into WPF.
and the ONLY problem I am getting in WPF is this:
protected override async void OnShown(EventArgs e)
Error 8 'EmployeeLocatorv2.receiver.OnShown(System.EventArgs)': no suitable method found to override
This means that the class your main form is inheriting (probably Window or UserControl) does not have a virtual method named "OnShown" that you can override.
According to Chango V., Window.ContentRendered is the event you're looking for.
You can use the Window.ContentRendered event to know when the WPF form is rendered.
You can declare the event in your XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" ContentRendered="Window_ContentRendered_1">
And the corresponding code:
private void Window_ContentRendered_1(object sender, EventArgs e)
{
// Place your code here.
}
In WPF, ContentRendered has a similar behavior.
bool _hasShown;
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (!_hasShown)
{
_hasShown = true;
// void OnShown() code here!
}
}
I'm trying to make a video conferencing application (written in c#) that would allow 2 users to video conference using TCP. In addition, users can text chat separately. Right now, I have a working video stream, yet don't have the audio working yet. I'm unsure of how to access the microphone, stream it using TCP, and then play it on the other user's speakers as I'm relatively new to c# and brand new to using media.
If anyone could point me towards sample code, help me know how to access the mic, or anything else you think would help me, that'd be great.
I'm attaching my code as is for reference.
WEBCAM.cs
using System;
using System.IO;
using System.Linq;
using System.Text;
using WebCam_Capture;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Net;
using System.Net.Sockets;
using System.Windows;
namespace DuckTalk
{
class WebCam
{
const int TEXT_VIDEO_NUM = 45674;
private System.Windows.Controls.TextBox _hostIpAddressBox;
private WebCamCapture webcam;
private int FrameNumber = 30;
public void InitializeWebCam(ref System.Windows.Controls.TextBox hostIpAddressBox)
{
webcam = new WebCamCapture();
webcam.FrameNumber = ((ulong)(0ul));
webcam.TimeToCapture_milliseconds = FrameNumber;
webcam.ImageCaptured += new WebCamCapture.WebCamEventHandler(webcam_ImageCaptured);
_hostIpAddressBox = hostIpAddressBox;
}
void webcam_ImageCaptured(object source, WebcamEventArgs e)
{
TcpClient connection = null;
NetworkStream stream = null;
byte[] imgBytes;
try
{
//Set up IPAddress
IPAddress ipAddress = IPAddress.Parse(_hostIpAddressBox.Text);
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, TEXT_VIDEO_NUM);
//Connect to TCP
connection = new TcpClient();
connection.Connect(ipLocalEndPoint);
// Get a client stream for reading and writing.
stream = connection.GetStream();
//Send image as bytes
imgBytes = ImageByteConverter.ImageToBytes((System.Drawing.Bitmap)e.WebCamImage);
stream.Write(imgBytes, 0, imgBytes.Length);
}
catch (Exception error)
{
MessageBox.Show("ERROR: " + error.Message);
}
finally
{
// Close everything.
if (connection != null)
connection.Close();
if (stream != null)
stream.Close();
}
}
public void Start()
{
webcam.TimeToCapture_milliseconds = FrameNumber;
webcam.Start(0);
}
public void Stop()
{
webcam.Stop();
}
}
}
ImageByteConverter.cs
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
namespace DuckTalk
{
class ImageByteConverter
{
public static byte[] ImageToBytes(System.Drawing.Bitmap bitmap)
{
byte[] byteArray;
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
}
return byteArray;
}
public static BitmapImage BytesToImage(byte[] imgBytes)
{
var image = new BitmapImage();
image.BeginInit();
image.StreamSource = new System.IO.MemoryStream(imgBytes);
image.EndInit();
return image;
}
}
}
Window1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
namespace DuckTalk
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class MainWindow : Window
{
const int TEXT_PORT_NUM = 45673;
const int TEXT_VIDEO_NUM = 45674;
WebCam webcam;
public MainWindow()
{
InitializeComponent();
}
private void mainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
webcam = new WebCam();
webcam.InitializeWebCam(ref xaml_hostTextBox);
var _backgroundIMWorker = new BackgroundWorker();
var _backgroundVidWorker = new BackgroundWorker();
_backgroundIMWorker.WorkerReportsProgress = true;
_backgroundVidWorker.WorkerReportsProgress = true;
// Set up the Background Worker Events
_backgroundIMWorker.DoWork += new DoWorkEventHandler(keepListeningForInstantMessages);
_backgroundVidWorker.DoWork += new DoWorkEventHandler(keepListeningForVideoMessages);
// Run the Background Workers
_backgroundIMWorker.RunWorkerAsync();
_backgroundVidWorker.RunWorkerAsync();
}
///////////////////////////////////////////////////////////////////////////////////////////////
//
//
// The next 2 functions take care of the instant messaging part of the program
//
//
//
///////////////////////////////////////////////////////////////////////////////////////////////
private void keepListeningForInstantMessages(object sender, DoWorkEventArgs e)
{
Action<string> displayIncomingMessage = (incomingMsg) =>
{
xaml_incomingTextBox.Text += "\n\nINCOMING MESSAGE: " + incomingMsg;
xaml_incomingTextScroll.ScrollToBottom();
};
Socket connection;
Byte[] data;
String msg;
// create the socket
Socket listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// bind the listening socket to the port
IPEndPoint ep = new IPEndPoint(IPAddress.Any, TEXT_PORT_NUM);
listenSocket.Bind(ep);
while (true)
{
msg = "";
data = new Byte[3000];
// start listening
listenSocket.Listen(1);
//Received a connection
connection = listenSocket.Accept();
//Get Data
connection.Receive(data);
//Get the message in string format
msg = System.Text.Encoding.Default.GetString(data);
msg = msg.Substring(0,msg.IndexOf((char)0));
//Send message to the UI
xaml_incomingTextBox.Dispatcher.BeginInvoke(displayIncomingMessage, msg);
connection.Close();
}
}//end of keepListeningForInstantMessages
void SendInstantMsg(object sender, RoutedEventArgs e)
{
TcpClient connection = null;
NetworkStream stream = null;
byte[] data;
xaml_incomingTextBox.Text += "\n\nOUTGOING MESSAGE: " + xaml_outgoingTextBox.Text;
try
{
//Set up IPAddress
IPAddress ipAddress = IPAddress.Parse(xaml_hostTextBox.Text);
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, TEXT_PORT_NUM);
//Connect to TCP
connection = new TcpClient();
connection.Connect(ipLocalEndPoint);
//Convert text to bytes
data = System.Text.Encoding.ASCII.GetBytes(xaml_outgoingTextBox.Text);
// Get a client stream for reading and writing.
stream = connection.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Count());
xaml_outgoingTextBox.Text = "";
}
catch (Exception error)
{
MessageBox.Show("ERROR: " + error.Message);
}
finally
{
// Close everything.
if (connection != null)
connection.Close();
if (stream != null)
stream.Close();
}
}//end of SendInstantMsg
///////////////////////////////////////////////////////////////////////////////////////////////
//
//
// The next 2 functions take care of the video part of the program
//
//
//
///////////////////////////////////////////////////////////////////////////////////////////////
private void keepListeningForVideoMessages(object sender, DoWorkEventArgs e)
{
Action<Byte[]> displayIncomingVideo = (incomingImgBytes) =>
{
xaml_incomingVideo.Source = ImageByteConverter.BytesToImage(incomingImgBytes);
};
Socket connection;
Byte[] incomingBytes;
Byte[] data;
int offset;
int numOfBytesRecieved;
// create the socket
Socket listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// bind the listening socket to the port
IPEndPoint ep = new IPEndPoint(IPAddress.Any, TEXT_VIDEO_NUM);
listenSocket.Bind(ep);
while (true)
{
offset = 0;
numOfBytesRecieved = -1;
incomingBytes = new Byte[300000];
// start listening
listenSocket.Listen(1);
//Received a connection
connection = listenSocket.Accept();
//Get all the data from the connection stream
while (numOfBytesRecieved != 0)
{
numOfBytesRecieved = connection.Receive(incomingBytes, offset, 10000, SocketFlags.None);
offset += numOfBytesRecieved;
}
data = new Byte[offset];
Array.Copy(incomingBytes, data, offset);
//Send image to the UI
xaml_incomingTextBox.Dispatcher.BeginInvoke(displayIncomingVideo, data);
connection.Close();
}
}//end of keepListeningForVideoMessages
private void SendVideoMsg(object sender, RoutedEventArgs e)
{
xaml_incomingVideo.Visibility = Visibility.Visible;
xaml_StopVideoButton.Visibility = Visibility.Visible;
xaml_SendTextButton.Visibility = Visibility.Hidden;
webcam.Start();
}
private void StopVideoMsg(object sender, RoutedEventArgs e)
{
xaml_incomingVideo.Visibility = Visibility.Hidden;
xaml_StopVideoButton.Visibility = Visibility.Hidden;
xaml_SendTextButton.Visibility = Visibility.Visible;
webcam.Stop();
}
}//end of Class
}//end of NameSpace
You should try downloading NAudio, it is an open source audio library. It comes with a demo on how to stream audio using UDP from one pc to another; it is in the NAudioDemo app called "Network Chat".
http://naudio.codeplex.com/
TCP which you are currently using is not really recommended for audio. Use UDP instead
http://www.onsip.com/about-voip/sip/udp-versus-tcp-for-voip
Alternatively, if you do not want to reinvent the wheel ( I am not sure what is your ultimate goal with your project ), you can try downloading our iConf.NET video conferencing SDK that does most of the leg work for you ( but is not free )
http://avspeed.com/
I am trying to build a basic server client application in winforms. However the server does nothing. Just sort of opens up and hangs if i may say so. What am i doing wrong. I made the application as follows:
The Server Winform
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.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace ServerWinForms
{
public partial class Form1 : Form
{
public delegate void AddText(TcpClient tcp, RichTextBox rtb);
public AddText myDelegate;
Thread myThread;
public Form1()
{
InitializeComponent();
myDelegate = new AddText(ClientSession);
}
void begin(Object obj)
{
var loaclAddress = IPAddress.Parse("127.0.0.1");
var tcpListener = new TcpListener(loaclAddress, 81);
tcpListener.Start();
while (true)
{
var tcpClient = tcpListener.AcceptTcpClient();
Form1 myForm1 = (Form1)obj;
myForm1.Invoke(myForm1.myDelegate);
//rtb.AppendText("Waiting for connection ");
// Console.WriteLine("Waiting for a connection");
//rtb.AppendText("Client Accepted ");
//Console.WriteLine("Client Accepted");
/*Thread thread = new Thread(() => ClientSession(tcpClient))
{
IsBackground = true
};
thread.Start();
//Console.WriteLine("Client Session thread started");
*/
}
}
private static bool tryRead(Stream stream, byte[] buffer, int offset, int count)
{
int bytesRead;
while (count > 0 && (bytesRead = stream.Read(buffer, offset, count)) > 0)
{
offset += bytesRead;
count -= bytesRead;
}
return count == 0;
}
public static void ClientSession(TcpClient tcpClient, RichTextBox rtb)
{
const int totalByteBuffer = 4096;
byte[] buffer = new byte[256];
// UC ucObj = new UC();
using (var networkStream = tcpClient.GetStream())
using (var bufferedStream = new BufferedStream(networkStream, totalByteBuffer))
while (true)
{
if (!tryRead(bufferedStream, buffer, 0, 1))
{
break;
}
byte messageLen = buffer[0];
if (!tryRead(bufferedStream, buffer, 1, messageLen))
{
break;
}
var message = Encoding.ASCII.GetString(buffer, 1, messageLen);
//Console.WriteLine(/*"Message Recieved: {0}", */ message);
RichTextBox rcb = new RichTextBox();
rtb.AppendText(message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
myThread = new Thread(begin);
myThread.Start(this);
//begin();
}
}
}
The Client Winform (though i believe everything is in order here but still... )
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.Net;
using System.Net.Sockets;
using System.IO;
namespace ClientWinForms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private static byte[] msg2ByteArray(string message, Encoding enc)
{
var byteCount = enc.GetByteCount(message);
if (byteCount > byte.MaxValue)
{
throw new ArgumentException("Message size is greater than 255 bytes in the provided encoding");
}
var byteArray = new byte[byteCount + 1];
byteArray[0] = (byte)byteCount;
enc.GetBytes(message, 0, message.Length, byteArray, 1);
return byteArray;
}
void sendMsg()
{
String message;
using (var tcpClient = new TcpClient())
{
tcpClient.Connect("127.0.0.1", 81);
using (var networkStream = tcpClient.GetStream())
using (var bufferedStream = new BufferedStream(networkStream))
{
//while (true)
//{
byte[] buffer = new byte[256];
//Console.WriteLine("Write Message");
message = richTextBox.Text;
var byteArray = msg2ByteArray(message, Encoding.ASCII);
bufferedStream.Write(byteArray, 0, byteArray.Length);
bufferedStream.Flush();
//}
}
}
}
private void btnSend_Click(object sender, EventArgs e)
{
sendMsg();
}
}
}
kewal, your code looks good and your program also. i also liked that you share all the code, it is most frustrating when i need to ask almost every other asked to do that.
now to the problem. you use tcpListener.Start(); in your server.
as we can read here:
"If a connection request is received, the Start method will queue
the request and continue listening for additional requests until you
call the Stop method"
i believe what you wanted is to use AcceptSocket() method - read
here
i can suggest: use different port. low number ports are taken
already and might not work. i think 81 if for http's, though i'm not
sure
EDIT
3. for the client use this MSDN example to see if the basic
example works for you
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