Click here to Skip to main content
15,893,337 members
Articles / Programming Languages / C#

Web-Cam SecureChat

Rate me:
Please Sign up or sign in to vote.
4.94/5 (16 votes)
12 Mar 2010CPOL6 min read 93.8K   7.4K   70  
This article will explain how to create a simple chat program using this remoting technology, which supports web-cam and sending files.
using System;
using System.IO;
using System.IO.Pipes;
using Pfz.Threading;

namespace Pfz.Remoting
{
	/// <summary>
	/// Helper class to create the DuplexStream generic class.
	/// </summary>
	public static class DuplexStream
	{
		#region Create
			/// <summary>
			/// Creates a new Duplex stream using the given stream.
			/// Method useful when you don't want to type the full name of the
			/// stream.
			/// Example: var duplexStream = DuplexStream.Create(readStream, writeStream);
			/// </summary>
			public static DuplexStream<T> Create<T>(T readStream, T writeStream)
			where
				T: Stream
			{
				return new DuplexStream<T>(readStream, writeStream);
			}
		#endregion
	
		#region CreateNamedPipeServer
			/// <summary>
			/// Creates a full duplex named pipe server.
			/// </summary>
			public static DuplexStream<NamedPipeServerStream> CreateNamedPipeServer(string pipeName, bool mustWaitForConnection)
			{
				NamedPipeServerStream readStream = null;
				NamedPipeServerStream writeStream = null;
				try
				{
					readStream = new NamedPipeServerStream(pipeName + "_ServerRead", PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
					writeStream = new NamedPipeServerStream(pipeName + "_ServerWrite", PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
					
					if (mustWaitForConnection)
					{
						readStream.WaitForConnection();
						writeStream.WaitForConnection();
					}
					
					var result = Create(readStream, writeStream);
					return result;
				}
				catch
				{
					if (readStream != null)
						readStream.Close();
					
					if (writeStream != null)
						writeStream.Close();
						
					throw;
				}
			}
		#endregion
		#region CreateNamedPipeClient
			/// <summary>
			/// Creates a full duplex named pipe client.
			/// </summary>
			public static DuplexStream<NamedPipeClientStream> CreateNamedPipeClient(string serverName, string pipeName, bool mustConnect)
			{
				NamedPipeClientStream readStream = null;
				NamedPipeClientStream writeStream = null;
				try
				{
					readStream = new NamedPipeClientStream(serverName, pipeName + "_ServerWrite", PipeDirection.In, PipeOptions.WriteThrough);
					writeStream = new NamedPipeClientStream(serverName, pipeName + "_ServerRead", PipeDirection.Out, PipeOptions.WriteThrough);
					
					if (mustConnect)
					{
						readStream.Connect(60000);
						writeStream.Connect(60000);
					}
					
					var result = Create(readStream, writeStream);
					return result;
				}
				catch
				{
					if (readStream != null)
						readStream.Close();
					
					if (writeStream != null)
						writeStream.Close();
						
					throw;
				}
			}
		#endregion
	}

	/// <summary>
	/// This class creates a "duplex" stream using two other streams,
	/// which one must be capable of reading and the other of writing.
	/// This class is used when working with NamedPipes, as if the server and the
	/// client try to read at the same time the custom namepipe will not work.
	/// </summary>
	public class DuplexStream<T>:
		ExceptionAwareStream
	where
		T: Stream
	{
		#region Constructor
			/// <summary>
			/// Creates the duplex stream using one stream to read and one to write.
			/// The other side must use the stream in the opposite order.
			/// </summary>
			public DuplexStream(T readStream, T writeStream)
			{
				if (readStream == null)
					throw new ArgumentNullException("readStream");
					
				if (writeStream == null)
					throw new ArgumentNullException("writeStream");
			
				ReadStream = readStream;
				WriteStream = writeStream;
			}
		#endregion
		#region Dispose
			/// <summary>
			/// Releases the read and write streams.
			/// </summary>
			protected override void OnDispose(bool disposing)
			{
				if (disposing)
				{
					var readStream = ReadStream;
					if (readStream != null)
					{
						ReadStream = null;
						readStream.Dispose();
					}
					
					var writeStream = WriteStream;
					if (writeStream != null)
					{
						WriteStream = null;
						writeStream.Dispose();
					}
				}

				base.OnDispose(disposing);
			}
		#endregion
		
		#region Properties
			#region ReadStream
				/// <summary>
				/// Gets the stream used for reading.
				/// </summary>
				public T ReadStream { get; private set; }
			#endregion
			#region WriteStream
				/// <summary>
				/// Gets the stream used for writing.
				/// </summary>
				public T WriteStream { get; private set; }
			#endregion

			#region Always true
				/// <summary>
				/// Always returns true.
				/// </summary>
				public override bool CanRead
				{
					get
					{
						return true;
					}
				}

				/// <summary>
				/// Always returns true.
				/// </summary>
				public override bool CanWrite
				{
					get
					{
						return true;
					}
				}
			#endregion
			#region Always false
				/// <summary>
				/// Always returns false.
				/// </summary>
				public override bool CanSeek
				{
					get
					{
						return false;
					}
				}
			#endregion
		#endregion
		#region Methods
			#region Flush
				/// <summary>
				/// Flushes the write stream.
				/// </summary>
				public override void Flush()
				{
					AbortSafe.Lock
					(
						DisposeLock,
						delegate
						{
							CheckUndisposed();
							WriteStream.Flush();
						}
					);
				}
			#endregion
			#region Read
				/// <summary>
				/// Reads from the ReadStream.
				/// </summary>
				public override int Read(byte[] buffer, int offset, int count)
				{
					CheckUndisposed();
					return ReadStream.Read(buffer, offset, count);
				}
			#endregion
			#region Write
				/// <summary>
				/// Writes to the WriteStream.
				/// </summary>
				public override void Write(byte[] buffer, int offset, int count)
				{
					AbortSafe.Lock
					(
						DisposeLock,
						delegate
						{
							CheckUndisposed();
							WriteStream.Write(buffer, offset, count);
						}
					);
				}
			#endregion
		#endregion
		
		#region Not Supported
			/// <summary>
			/// Throws NotSupportedException.
			/// </summary>
			public override long Length
			{
				get
				{
					throw new NotSupportedException();
				}
			}

			/// <summary>
			/// Throws NotSupportedException.
			/// </summary>
			public override long Position
			{
				get
				{
					throw new NotSupportedException();
				}
				set
				{
					throw new NotSupportedException();
				}
			}

			/// <summary>
			/// Throws NotSupportedException.
			/// </summary>
			public override long Seek(long offset, SeekOrigin origin)
			{
				throw new NotSupportedException();
			}

			/// <summary>
			/// Throws NotSupportedException.
			/// </summary>
			public override void SetLength(long value)
			{
				throw new NotSupportedException();
			}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Microsoft
United States United States
I started to program computers when I was 11 years old, as a hobbyist, programming in AMOS Basic and Blitz Basic for Amiga.
At 12 I had my first try with assembler, but it was too difficult at the time. Then, in the same year, I learned C and, after learning C, I was finally able to learn assembler (for Motorola 680x0).
Not sure, but probably between 12 and 13, I started to learn C++. I always programmed "in an object oriented way", but using function pointers instead of virtual methods.

At 15 I started to learn Pascal at school and to use Delphi. At 16 I started my first internship (using Delphi). At 18 I started to work professionally using C++ and since then I've developed my programming skills as a professional developer in C++ and C#, generally creating libraries that help other developers do their work easier, faster and with less errors.

Want more info or simply want to contact me?
Take a look at: http://paulozemek.azurewebsites.net/
Or e-mail me at: paulozemek@outlook.com

Codeproject MVP 2012, 2015 & 2016
Microsoft MVP 2013-2014 (in October 2014 I started working at Microsoft, so I can't be a Microsoft MVP anymore).

Comments and Discussions