Sending and receiving an image over sockets with C# - c#

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

Related

How do I send and receive a file through tcp socket

Now I know that this question has been asked a lot but I really just don't get how to do it. I tried this but the file don't get complete I just receive just a bit of the file and the rest is just NULL here is my code in client part I first send a message to the server that contain the file size like this :
// here I send the a upload request with the size of the file that I want to send
byte[] data = Encoding.Unicode.GetBytes("uploadreq~"+new FileInfo(ofg.FileName).Length);
// here is the socket client
target.Send(data);
Then on the server side :
if (cmd.Contains(update.update_request))
{
// here I set an int var to the file size
update.update_size = int.Parse(cmd.Split('~')[1]);
// here I setup the a new byte array with the given file size
update.update_received = new byte[update.update_size];
// then I send a upload confirm command
Connection.sendCommand(Commands.update_confirme);
update.isupdate = true;
}
Again on the client side when the confirmation has been received :
if (cmd.StartsWith("updateConfirm"))
{
// reading all the bytes of the file and sending them
byte[] datatosend = File.ReadAllBytes("the file path");
Connection.send_bytes(datatosend);
}
Finally on the client side :
private void receiveInfo()
{
byte[] buffer = new byte[999999];
int received = 0;
try
{
received = Connection.clientSocket.Receive(buffer);
}
catch (SocketException)
{
Connection.clientSocket.Close();
Connection.clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Connection.makeConnection();
}
if (received == 0)
return;
byte[] data = new byte[received];
Array.Copy(buffer, data, received);
if (update.isupdate == true)
{
// this calls a method that process the data received
update.process_update(data);
}
}
public static void process_update(byte[] data)
{
int writeSize = 0;
Buffer.BlockCopy(data, 0, update_received, writeSize, data.Length);
writeSize += data.Length;
if (update_received.Length == update_size)
{
using (FileStream fs = File.Create("the path to where the file shloud go"))
{
byte[] info = update_received;
fs.Write(info, 0, info.Length);
}
Array.Clear(update_received, 0, update_received.Length);
isupdate = false;
}
}
As I was writing this question I changed the buffer size in the receive info method and that seems to change stuff a bit but still, the file won't arrive fully..
Try this for the client:
private void SendFile(String FileName,String IPAddress,int Port )
{
System.Net.Sockets.TcpClient TcpClient = new System.Net.Sockets.TcpClient(IPAddress, Port);
System.Net.Sockets.NetworkStream NetworkStream = TcpClient.GetStream();
System.IO.Stream FileStream = System.IO.File.OpenRead(FileName);
byte[] FileBuffer = new byte[FileStream.Length];
FileStream.Read(FileBuffer, 0, (int)FileStream.Length);
NetworkStream.Write(FileBuffer, 0, FileBuffer.GetLength(0));
NetworkStream.Close();
}
and this is the code for the server:
private void ReceiveFile(String FilePath, int Port)
{
System.Threading.Thread WorkerThread = new System.Threading.Thread(() =>
{
System.Net.Sockets.TcpListener TcpListener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 60000);
TcpListener.Start();
System.Net.Sockets.Socket HandlerSocket = TcpListener.AcceptSocket();
System.Net.Sockets.NetworkStream NetworkStream = new System.Net.Sockets.NetworkStream(HandlerSocket);
int BlockSize = 1024;
int DataRead = 0;
Byte[] DataByte = new Byte[BlockSize];
lock (this)
{
System.IO.Stream FileStream = System.IO.File.OpenWrite(FilePath);
while (true)
{
DataRead = NetworkStream.Read(DataByte, 0, BlockSize);
FileStream.Write(DataByte, 0, DataRead);
if (DataRead == 0)
{
break;
}
}
FileStream.Close();
}
});
WorkerThread.Start();
}
This will only transfer one file.

Choppy Audio with Naudio and TCP Stream. Buffer Full Exception

I am attempting to stream audio using Naudio over a TCP connection. The problem is the audio sounds choppy. I believe this is because I am getting an exception saying the buffer is full when I try to add samples to the bufferedwaveprovider.
I have tried increasing the buffer size however the result remains unchanged.
-----CLIENT CODE-----
public TcpClient client;
public WaveOut waveplayer = new WaveOut();
public BufferedWaveProvider bwp = new BufferedWaveProvider(new WaveFormat(8000, 16, 1));
public byte[] buffer = new byte[1024 * 16];
public Form1()
{
bwp.BufferLength = 1024 * 16;
waveplayer.Init(bwp);
waveplayer.Play();
}
public void audio()
{
try
{
client = new TcpClient(textBox1.Text.ToString(), 8001);
NetworkStream ns = client.GetStream();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
while (true)
{
try
{
ns.Read(buffer, 0, buffer.Length);
bwp.AddSamples(buffer, 0, buffer.Length);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
-----SERVER CODE------
public NAudio.Wave.WaveInEvent sourcestream = null;
public TcpListener listener = new TcpListener(IPAddress.Any, 8001);
public TcpClient client;
public NetworkStream ns;
public Form1()
{
InitializeComponent();
sourcestream = new NAudio.Wave.WaveInEvent();
sourcestream.DeviceNumber = 0;
sourcestream.WaveFormat = new NAudio.Wave.WaveFormat(8000, 16, 1);
sourcestream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(audioDataAvailable);
sourcestream.StartRecording();
}
public void acceptclients()
{
listener = new TcpListener(IPAddress.Any, 8001);
listener.Start();
client = listener.AcceptTcpClient();
ns = client.GetStream();
}
void audioDataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
try
{
if (client.Connected)
{
ns.Write(e.Buffer, 0, e.Buffer.Length);
ns.Flush();
}
}
catch(Exception ex)
{
Here is the exact error I recieve
"System.InvalidOperationException: Buffer full at NAudio.Wave.BufferedWaveProvider.AddSamples(Byte[] buffer, Int32 offset, Int32 count
If you're getting a buffer full exception, that means audio is arriving faster than you are playing it. You either need a larger buffer size, or to throttle audio before downloading it.
You also should use e.BytesRecorded, not e.Buffer.Length on the server side. That might also account for the issue you are seeing.
Another bug is that you should examine the number of bytes read from ns.Read and use that number when calling bwp.AddSamples

Sending and Receiving large amount of data through TCPClient doesnot read all the data

Receiving bytes here in this code(server)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Drawing;
namespace ByteLengthReading
{
class Program
{
static void Main(string[] args)
{
StartServer();
}
private static TcpListener _listener;
public static void StartServer()
{
IPAddress localIPAddress = IPAddress.Parse("119.43.29.182");
IPEndPoint ipLocal = new IPEndPoint(localIPAddress, 8001);
_listener = new TcpListener(ipLocal);
_listener.Start();
WaitForClientConnect();
}
private static void WaitForClientConnect()
{
object obj = new object();
_listener.BeginAcceptTcpClient(new System.AsyncCallback(OnClientConnect), obj);
Console.In.ReadLine();
}
private static void OnClientConnect(IAsyncResult asyn)
{
try
{
TcpClient clientSocket = default(TcpClient);
clientSocket = _listener.EndAcceptTcpClient(asyn);
HandleClientRequest clientReq = new HandleClientRequest(clientSocket);
clientReq.StartClient();
}
catch (Exception ex)
{
throw ex;
}
WaitForClientConnect();
}
public class HandleClientRequest
{
TcpClient _clientSocket;
NetworkStream _networkStream = null;
public HandleClientRequest(TcpClient clientConnected)
{
this._clientSocket = clientConnected;
}
public void StartClient()
{
_networkStream = _clientSocket.GetStream();
WaitForRequest();
}
public void WaitForRequest()
{
byte[] buffer = new byte[_clientSocket.ReceiveBufferSize];
_networkStream.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);
}
private void ReadCallback(IAsyncResult result)
{
NetworkStream networkStream = _clientSocket.GetStream();
byte[] buffer = new byte[16384];
int read = -1;
int totRead = 0;
using (FileStream fileStream = new FileStream(#"C:\Foo" + Guid.NewGuid().ToString("N") + ".txt", FileMode.Create))
{
while ((read = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
totRead += read;
fileStream.Write(buffer, 0, read);
Console.WriteLine("Total Read" + totRead);
//fileStream.Write(buffer, 0, totRead);
//fileStream.Close();
}
fileStream.Close();
}
}
}
}
Sending bytes (Client), Sending bytes of length 4047810. But the abover server code is recieving only 4039618 bytes. Please help someone. Don't know y? At the time of reading last set of data it is coming out of the while loop. Please test this code and tell me where the problem lies.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Drawing;
using System.Threading;
namespace ByteLengthSending
{
class Program
{
static void Main(string[] args)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect(IPAddress.Parse("119.43.29.182"), 8001);
//IPAddress ipAd = IPAddress.Parse("119.43.29.182");
//TcpClient client = new TcpClient(ipAd.ToString(), 8001);
//NetworkStream stream = client.GetStream();
int totread = 0;
byte[] longBuffer = new byte[3824726];
byte[] buffer = new byte[4096];
using (var fileStream = File.OpenRead("C:/Foo.txt"))
{
while (true)
{
int read = fileStream.Read(buffer, 0, buffer.Length);
totread += read;
if (read <= 0)
{
break;
}
for (int sendBytes = 0; sendBytes < read; sendBytes += client.Send(buffer, sendBytes, read - sendBytes, SocketFlags.None))
{
}
}
}
client.Close();
Console.WriteLine("Total Read" + totread);
Console.In.ReadLine();
}
}
}
Here is a sample which uses my library Griffin.Framework to transmit a file (Apache license).
All you need to do is to install the nuget package "griffin.framework" and then create a console application and replace Program class with the following:
class Program
{
static void Main(string[] args)
{
var server = new ChannelTcpListener();
server.MessageReceived = OnServerReceivedMessage;
server.Start(IPAddress.Any, 0);
var client = new ChannelTcpClient<object>(new MicroMessageEncoder(new DataContractMessageSerializer()),
new MicroMessageDecoder(new DataContractMessageSerializer()));
client.ConnectAsync(IPAddress.Loopback, server.LocalPort).Wait();
client.SendAsync(new FileStream("TextSample.txt", FileMode.Open)).Wait();
Console.ReadLine();
}
private static void OnServerReceivedMessage(ITcpChannel channel, object message)
{
var file = (Stream) message;
var reader = new StreamReader(file);
var fileContents = reader.ReadToEnd();
Console.WriteLine(fileContents);
}
}
The library can send/receive any type of stream of any size (as long as the size is known). The client will automatically create a MemoryStream or FileStream depending on the stream size.

Trying to stream 2 way audio over TCP?

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/

TCP Client Disconnects

Im a newbie to TCPClient, Im trying to make a webcam app that sends small images ~4kb each to another IP which will run an identical program. So its going to send and receive at the same time.
Problem I have is the _tcpOut disconnects after one send which means I only see one frame. In the code below there are two sections, first the NewFrameReceived is run on every new image from the camera, which is then sent, the other method is the receive method which puts the received pic into a picture box (at the moment my own from 127.0.0.1) :
private void fChat_Load(object sender, EventArgs e)
{
// fire up listener
listeningThread.RunWorkerAsync();
// tcp server setup
_tcpOut = new TcpClient();
_tcpOut.Connect("127.0.0.1", 54321);
}
private void NewFrameReceived(object sender, NewFrameEventArgs e)
{
Bitmap img = (Bitmap)e.Frame.Clone();
byte[] imgBytes = EncodeToJpeg(img, 25).ToArray();
if (_tcpOut.Connected) <-- PROBLEM HERE, THIS IS FALSE ON 2ND ITERATION
{
using (NetworkStream ns = _tcpOut.GetStream())
{
if (ns.CanWrite)
{
ns.Write(BitConverter.GetBytes(imgBytes.Length), 0, 4);
ns.Write(imgBytes, 0, imgBytes.Length);
}
}
}
}
private void listeningThread_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// start listening for connections
_tcpIn = new TcpListener(IPAddress.Any, 54321);
_tcpIn.Start();
while (true)
{
using (TcpClient _inClient = _tcpIn.AcceptTcpClient()) // blocks until connected
{
using (NetworkStream stream = _inClient.GetStream())
{
Byte[] imgSizeBytes = new Byte[4];
stream.Read(imgSizeBytes, 0, 4);
int imgSize = BitConverter.ToInt32(imgSizeBytes, 0);
Byte[] imgBytes = new Byte[imgSize];
stream.Read(imgBytes, 0, imgSize);
MemoryStream ms = new MemoryStream(imgBytes);
Image img = Image.FromStream(ms);
picVideo.Image = img;
}
}
}
}
Many thanks in advance.
It disconnects because you're disposing the TcpClient with the using statement.

Categories

Resources