Showing posts with label code sample. Show all posts
Showing posts with label code sample. Show all posts

Sunday, May 02, 2010

Async Socket Server Sample in C#

Networking Samples for .NET v4.0 contains some cool samples.

They also provide an example for an async socket server and client. very cool stuff!


Asynchronous Socket Server Sample
=================================

This sample demonstrates how to use the xxxAsync (xxx = receive, send, connect, etc) methods on the Sytem.Net.Sockets.Socket
class by implementing an echo server (ie. The server sends all the data read from a client back to the client).
The echo server implemented in this sample handles multiple clients simultaneously (up to a maximum specified as a command line argument)
and highlights some of the key elements of the event-based asynchronous socket methods.
The sample illustrates creating a pool of reusable data buffers and SocketAsyncEventArgs context objects as a method to
increase server performance.

The sample is intended for educational purposes and should not be used directly in production applications.



Sample Language Implementations
===============================
This sample is available in the following language implementations:
C#

Prerequisites
=============
This sample requires the .NET Framework v4.0



Building the Sample
===================
To build the sample using Visual Studio (preferred method):

1. Double-click the AsyncSocketServer.sln file to open the socket server sample in Visual Studio.

2. Using the menu, click Build > Build Solution.


To build the sample using the command prompt:

1. Open the Command Prompt window and navigate to the directory containing the socket server sample.

2. Type msbuild AsyncSocketServer.sln.


Running the Sample
==================
The socket server requires four command line parameters.


Usage:

AsyncSocketServer.exe <#connections>





# Connections: The maximum number of connections the server will accept simultaneously.

Receive Size in Bytes: The buffer size used by the server for each receive operation.

Address family: The address family of the socket the server will use to listen for incoming connections. Supported values are ‘ipv4’ and ‘ipv6’.

Local Port Number: The port to which the server will bind.



Example:

AsyncSocketServer.exe 500 1024 ipv4 8000




The client part:



using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

//Implements a sample socket client to connect to the server implmented in the AsyncSocketServer project
//Usage: AsyncSocketClient.exe <destination IP address> <destination port number>

//Destination IP address: The IP Address of the server to connect to
//Destination Port Number: The port number to connect to

namespace AsyncSocketClient
{
class Program
{
static ManualResetEvent clientDone = new ManualResetEvent(false);

static void Main(string[] args)
{
IPAddress destinationAddr = null; // IP Address of server to connect to
int destinationPort = 0; // Port number of server
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();


if (args.Length != 2)
{
Console.WriteLine("Usage: AsyncSocketClient.exe <destination IP address> <destination port number>");
}
try
{
destinationAddr = IPAddress.Parse(args[0]);
destinationPort = int.Parse(args[1]);
if (destinationPort <= 0){
throw new ArgumentException("Destination port number provided cannot be less than or equal to 0");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Usage: AsyncSocketClient.exe <destination IP address> <destination port number>");
}

// Create a socket and connect to the server
Socket sock = new Socket(destinationAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(SocketEventArg_Completed);
socketEventArg.RemoteEndPoint = new IPEndPoint(destinationAddr, destinationPort);
socketEventArg.UserToken = sock;
sock.ConnectAsync(socketEventArg);
clientDone.WaitOne();
}

/// <summary>
/// A single callback is used for all socket operations. This method forwards execution on to the correct handler
/// based on the type of completed operation
/// </summary>
static void SocketEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
ProcessConnect(e);
break;
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new Exception("Invalid operation completed");
}
}

/// <summary>
/// Called when a ConnectAsync operation completes
/// </summary>
private static void ProcessConnect(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Successfully connected to the server");

// Send 'Hello World' to the server
byte[] buffer = Encoding.UTF8.GetBytes("Hello World");
e.SetBuffer(buffer, 0, buffer.Length);
Socket sock = e.UserToken as Socket;
bool willRaiseEvent = sock.SendAsync(e);
if (!willRaiseEvent)
{
ProcessSend(e);
}
}
else
{
throw new SocketException((int)e.SocketError);
}
}

/// <summary>
/// Called when a ReceiveAsync operation completes
/// </summary>
private static void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Received from server: {0}", Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred));

// Data has now been sent and received from the server. Disconnect from the server
Socket sock = e.UserToken as Socket;
sock.Shutdown(SocketShutdown.Send);
sock.Close();
clientDone.Set();
}
else
{
throw new SocketException((int)e.SocketError);
}
}


/// <summary>
/// Called when a SendAsync operation completes
/// </summary>
private static void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Console.WriteLine("Sent 'Hello World' to the server");

//Read data sent from the server
Socket sock = e.UserToken as Socket;
bool willRaiseEvent = sock.ReceiveAsync(e);
if (!willRaiseEvent)
{
ProcessReceive(e);
}
}
else
{
throw new SocketException((int)e.SocketError);
}
}
}
}



The server classes:


using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace AsyncSocketSample
{

/// <summary>
/// This class is designed for use as the object to be assigned to the SocketAsyncEventArgs.UserToken property.
/// </summary>
class AsyncUserToken
{
Socket m_socket;

public AsyncUserToken() : this(null) { }

public AsyncUserToken(Socket socket)
{
m_socket = socket;
}

public Socket Socket
{
get { return m_socket; }
set { m_socket = value; }
}

}
}



using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace AsyncSocketSample
{
/// <summary>
/// This class creates a single large buffer which can be divided up and assigned to SocketAsyncEventArgs objects for use
/// with each socket I/O operation. This enables bufffers to be easily reused and gaurds against fragmenting heap memory.
///
/// The operations exposed on the BufferManager class are not thread safe.
/// </summary>
class BufferManager
{
int m_numBytes; // the total number of bytes controlled by the buffer pool
byte[] m_buffer; // the underlying byte array maintained by the Buffer Manager
Stack<int> m_freeIndexPool; //
int m_currentIndex;
int m_bufferSize;

public BufferManager(int totalBytes, int bufferSize)
{
m_numBytes = totalBytes;
m_currentIndex = 0;
m_bufferSize = bufferSize;
m_freeIndexPool = new Stack<int>();
}

/// <summary>
/// Allocates buffer space used by the buffer pool
/// </summary>
public void InitBuffer()
{
// create one big large buffer and divide that out to each SocketAsyncEventArg object
m_buffer = new byte[m_numBytes];
}

/// <summary>
/// Assigns a buffer from the buffer pool to the specified SocketAsyncEventArgs object
/// </summary>
/// <returns>true if the buffer was successfully set, else false</returns>
public bool SetBuffer(SocketAsyncEventArgs args)
{

if (m_freeIndexPool.Count > 0)
{
args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
}
else
{
if ((m_numBytes - m_bufferSize) < m_currentIndex)
{
return false;
}
args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
m_currentIndex += m_bufferSize;
}
return true;
}

/// <summary>
/// Removes the buffer from a SocketAsyncEventArg object. This frees the buffer back to the
/// buffer pool
/// </summary>
public void FreeBuffer(SocketAsyncEventArgs args)
{
m_freeIndexPool.Push(args.Offset);
args.SetBuffer(null, 0, 0);
}


}
}



using System;
using System.Collections.Generic;
using System.Text;
using System.Net;


//This project implements an echo socket server.
//The socket server requires four command line parameters:
//Usage: AsyncSocketServer.exe <#connections> <Receive Size In Bytes> <address family: ipv4 | ipv6> <Local Port Number>

//# Connections: The maximum number of connections the server will accept simultaneously.
//Receive Size in Bytes: The buffer size used by the server for each receive operation.
//Address family: The address family of the socket the server will use to listen for incoming connections. Supported values are ‘ipv4’ and ‘ipv6’.
//Local Port Number: The port the server will bind to.

//Example: AsyncSocketServer.exe 500 1024 ipv4 8000



namespace AsyncSocketSample
{
class Program
{
static void Main(string[] args)
{
int numConnections;
int receiveSize;
IPEndPoint localEndPoint;
int port;

// parse command line parameters
//format: #connections, receive size per connection, address family, port num
if (args.Length < 4)
{
Console.WriteLine("Usage: AsyncSocketServer.exe <#connections> <receiveSizeInBytes> <address family: ipv4 | ipv6> <Local Port Number>");
return;
}

try
{
numConnections = int.Parse(args[0]);
receiveSize = int.Parse(args[1]);
string addressFamily = args[2].ToLower();
port = int.Parse(args[3]);


if (numConnections <= 0)
{
throw new ArgumentException("The number of connections specified must be greater than 0");
}
if (receiveSize <= 0)
{
throw new ArgumentException("The receive size specified must be greater than 0");
}
if (port <= 0)
{
throw new ArgumentException("The port specified must be greater than 0");
}

// This sample supports two address family types: ipv4 and ipv6
if (addressFamily.Equals("ipv4"))
{
localEndPoint = new IPEndPoint(IPAddress.Any, port);
}
else if (addressFamily.Equals("ipv6"))
{
localEndPoint = new IPEndPoint(IPAddress.IPv6Any, port);
}
else
{
throw new ArgumentException("Invalid address family specified");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine("Usage: AsyncSocketServer.exe <#connections> <receiveSizeInBytes> <address family: ipv4 | ipv6> <Local Port Number>");
return;
}

Console.WriteLine("Press any key to start the server ...");
Console.ReadKey();

// Start the server listening for incoming connection requests
Server server = new Server(numConnections, receiveSize);
server.Init();
server.Start(localEndPoint);


}
}
}





using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;


namespace AsyncSocketSample
{
/// <summary>
/// Implements the connection logic for the socket server. After accepting a connection, all data read
/// from the client is sent back to the client. The read and echo back to the client pattern is continued
/// until the client disconnects.
/// </summary>
class Server
{
private int m_numConnections; // the maximum number of connections the sample is designed to handle simultaneously
private int m_receiveBufferSize;// buffer size to use for each socket I/O operation
BufferManager m_bufferManager; // represents a large reusable set of buffers for all socket operations
const int opsToPreAlloc = 2; // read, write (don't alloc buffer space for accepts)
Socket listenSocket; // the socket used to listen for incoming connection requests
// pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations
SocketAsyncEventArgsPool m_readWritePool;
int m_totalBytesRead; // counter of the total # bytes received by the server
int m_numConnectedSockets; // the total number of clients connected to the server
Semaphore m_maxNumberAcceptedClients;

/// <summary>
/// Create an uninitialized server instance. To start the server listening for connection requests
/// call the Init method followed by Start method
/// </summary>
/// <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously</param>
/// <param name="receiveBufferSize">buffer size to use for each socket I/O operation</param>
public Server(int numConnections, int receiveBufferSize)
{
m_totalBytesRead = 0;
m_numConnectedSockets = 0;
m_numConnections = numConnections;
m_receiveBufferSize = receiveBufferSize;
// allocate buffers such that the maximum number of sockets can have one outstanding read and
//write posted to the socket simultaneously
m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc,
receiveBufferSize);

m_readWritePool = new SocketAsyncEventArgsPool(numConnections);
m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
}

/// <summary>
/// Initializes the server by preallocating reusable buffers and context objects. These objects do not
/// need to be preallocated or reused, by is done this way to illustrate how the API can easily be used
/// to create reusable objects to increase server performance.
/// </summary>
public void Init()
{
// Allocates one large byte buffer which all I/O operations use a piece of. This gaurds
// against memory fragmentation
m_bufferManager.InitBuffer();

// preallocate pool of SocketAsyncEventArgs objects
SocketAsyncEventArgs readWriteEventArg;

for (int i = 0; i < m_numConnections; i++)
{
//Pre-allocate a set of reusable SocketAsyncEventArgs
readWriteEventArg = new SocketAsyncEventArgs();
readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
readWriteEventArg.UserToken = new AsyncUserToken();

// assign a byte buffer from the buffer pool to the SocketAsyncEventArg object
m_bufferManager.SetBuffer(readWriteEventArg);

// add SocketAsyncEventArg to the pool
m_readWritePool.Push(readWriteEventArg);
}

}

/// <summary>
/// Starts the server such that it is listening for incoming connection requests.
/// </summary>
/// <param name="localEndPoint">The endpoint which the server will listening for conenction requests on</param>
public void Start(IPEndPoint localEndPoint)
{
// create the socket which listens for incoming connections
listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(localEndPoint);
// start the server with a listen backlog of 100 connections
listenSocket.Listen(100);

// post accepts on the listening socket
StartAccept(null);

//Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount);
Console.WriteLine("Press any key to terminate the server process....");
Console.ReadKey();
}


/// <summary>
/// Begins an operation to accept a connection request from the client
/// </summary>
/// <param name="acceptEventArg">The context object to use when issuing the accept operation on the
/// server's listening socket</param>
public void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
}
else
{
// socket must be cleared since the context object is being reused
acceptEventArg.AcceptSocket = null;
}

m_maxNumberAcceptedClients.WaitOne();
bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
if (!willRaiseEvent)
{
ProcessAccept(acceptEventArg);
}
}

/// <summary>
/// This method is the callback method associated with Socket.AcceptAsync operations and is invoked
/// when an accept operation is complete
/// </summary>
void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}

private void ProcessAccept(SocketAsyncEventArgs e)
{
Interlocked.Increment(ref m_numConnectedSockets);
Console.WriteLine("Client connection accepted. There are {0} clients connected to the server",
m_numConnectedSockets);

// Get the socket for the accepted client connection and put it into the
//ReadEventArg object user token
SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket;

// As soon as the client is connected, post a receive to the connection
bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
if(!willRaiseEvent){
ProcessReceive(readEventArgs);
}

// Accept the next connection request
StartAccept(e);
}

/// <summary>
/// This method is called whenever a receive or send opreation is completed on a socket
/// </summary>
/// <param name="e">SocketAsyncEventArg associated with the completed receive operation</param>
void IO_Completed(object sender, SocketAsyncEventArgs e)
{
// determine which type of operation just completed and call the associated handler
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}

}

/// <summary>
/// This method is invoked when an asycnhronous receive operation completes. If the
/// remote host closed the connection, then the socket is closed. If data was received then
/// the data is echoed back to the client.
/// </summary>
private void ProcessReceive(SocketAsyncEventArgs e)
{
// check if the remote host closed the connection
AsyncUserToken token = (AsyncUserToken)e.UserToken;
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
//increment the count of the total bytes receive by the server
Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred);
Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead);

//echo the data received back to the client
bool willRaiseEvent = token.Socket.SendAsync(e);
if (!willRaiseEvent)
{
ProcessSend(e);
}

}
else
{
CloseClientSocket(e);
}
}

/// <summary>
/// This method is invoked when an asynchronous send operation completes. The method issues another receive
/// on the socket to read any additional data sent from the client
/// </summary>
/// <param name="e"></param>
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
// done echoing data back to the client
AsyncUserToken token = (AsyncUserToken)e.UserToken;
// read the next block of data send from the client
bool willRaiseEvent = token.Socket.ReceiveAsync(e);
if (!willRaiseEvent)
{
ProcessReceive(e);
}
}
else
{
CloseClientSocket(e);
}
}

private void CloseClientSocket(SocketAsyncEventArgs e)
{
AsyncUserToken token = e.UserToken as AsyncUserToken;

// close the socket associated with the client
try
{
token.Socket.Shutdown(SocketShutdown.Send);
}
// throws if client process has already closed
catch (Exception) { }
token.Socket.Close();

// decrement the counter keeping track of the total number of clients connected to the server
Interlocked.Decrement(ref m_numConnectedSockets);
m_maxNumberAcceptedClients.Release();
Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets);

// Free the SocketAsyncEventArg so they can be reused by another client
m_readWritePool.Push(e);
}

}
}



using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace AsyncSocketSample
{
/// <summary>
/// Represents a collection of resusable SocketAsyncEventArgs objects.
/// </summary>
class SocketAsyncEventArgsPool
{
Stack<SocketAsyncEventArgs> m_pool;

/// <summary>
/// Initializes the object pool to the specified size
/// </summary>
/// <param name="capacity">The maximum number of SocketAsyncEventArgs objects the pool can hold</param>
public SocketAsyncEventArgsPool(int capacity)
{
m_pool = new Stack<SocketAsyncEventArgs>(capacity);
}

/// <summary>
/// Add a SocketAsyncEventArg instance to the pool
/// </summary>
/// <param name="item">The SocketAsyncEventArgs instance to add to the pool</param>
public void Push(SocketAsyncEventArgs item)
{
if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); }
lock (m_pool)
{
m_pool.Push(item);
}
}

/// <summary>
/// Removes a SocketAsyncEventArgs instance from the pool
/// </summary>
/// <returns>The object removed from the pool</returns>
public SocketAsyncEventArgs Pop()
{
lock (m_pool)
{
return m_pool.Pop();
}
}

/// <summary>
/// The number of SocketAsyncEventArgs instances in the pool
/// </summary>
public int Count
{
get { return m_pool.Count; }
}

}
}

IPv6 Client Code in C#

Pretty cool and short sample how to make a IPv6 client in C#.

Additional networking samples with .net 4.0 can be found here.

The server code sample can be found here.


//---------------------------------------------------------------------
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace Microsoft.Samples.IPv6Sockets
{
static class IPv6Client
{
static void Main(string[] args)
{
if (args.Length < 1) {
DisplayUsage();
return;
}

string serverDnsName = args[0];
try
{
IPHostEntry resolvedServer = Dns.GetHostEntry(serverDnsName);
for (int i = 0; i < resolvedServer.AddressList.Length; i++)
{
IPAddress address = resolvedServer.AddressList[i];
IPEndPoint serverEndPoint = new IPEndPoint(address, 5150);
Socket tcpSocket =
new Socket(
address.AddressFamily,
SocketType.Stream,
ProtocolType.Tcp);
try
{
tcpSocket.Connect(serverEndPoint);
StreamWriter writer = null;
StreamReader reader = null;
try
{
NetworkStream networkStream =
new NetworkStream(tcpSocket);
writer = new StreamWriter(networkStream);
string clientMessage = "Hi there!";
writer.WriteLine(clientMessage);
writer.Flush();
Console.WriteLine(
"Client sent message: {0}", clientMessage);

reader = new StreamReader(networkStream);
string serverMessage = reader.ReadLine();
Console.WriteLine(
"Client received message: {0}", serverMessage);
}
catch (SocketException ex)
{
Console.WriteLine(
"Message exchange failed: {0}", ex.Message);
}
catch (IOException ex)
{
Console.WriteLine(
"Message exchange failed: {0}", ex.Message);
}
finally
{
if (reader != null)
reader.Close();
if (writer != null)
writer.Close();
}
break;
}
catch (SocketException)
{
if (tcpSocket != null)
tcpSocket.Close();
if (i == resolvedServer.AddressList.Length - 1)
Console.WriteLine(
"Failed to connect to the server.");
}
}

}
catch (SocketException ex)
{
Console.WriteLine(
"Could not resolve server DNS name: {0}", ex.Message);
}
}

private static void DisplayUsage()
{
Console.WriteLine("IPv6Client server_name");
}
}
}

IPv6 Server Code in C#

Pretty cool and short sample how to make a IPv6 server in C#.

Additional networking samples with .net 4.0 can be found here.

The client code sample can be found here.



//---------------------------------------------------------------------
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace Microsoft.Samples.IPv6Sockets
{
static class IPv6Server
{
static void Main()
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.IPv6Any, 5150);
Socket serverSocket =
new Socket(
AddressFamily.InterNetworkV6,
SocketType.Stream,
ProtocolType.Tcp);
try
{
serverSocket.Bind(localEndPoint);
serverSocket.Listen(int.MaxValue);
Console.WriteLine("Server started.");
Console.WriteLine("Listening on " + localEndPoint.Address.ToString());

while (true)
{
try
{
Socket clientSocket = serverSocket.Accept();
Console.WriteLine(
"Accepted connection from: {0}",
clientSocket.RemoteEndPoint.ToString());

StreamReader reader = null;
StreamWriter writer = null;
try
{
NetworkStream networkStream =
new NetworkStream(clientSocket);
reader = new StreamReader(networkStream);
string clientMessage = reader.ReadLine();
Console.WriteLine(
"Server received message: {0}", clientMessage);

writer = new StreamWriter(networkStream);
string serverMessage = "Hello!";
writer.WriteLine(serverMessage);
writer.Flush();
Console.WriteLine(
"Server sent message: {0}", serverMessage);
}
catch (SocketException ex)
{
Console.WriteLine(
"Message exchange failed: {0}", ex.Message);
}
finally
{
if (reader != null)
reader.Close();
if (writer != null)
writer.Close();
}
}
catch (SocketException ex)
{
Console.WriteLine(
"Server could not accept connection: {0}",
ex.Message);
}
}
}
catch (SocketException ex)
{
Console.WriteLine("Failed to start server: {0}", ex.Message);
}
finally
{
if (serverSocket != null)
serverSocket.Close();
}
}
}
}

Sockets in C#: How to make a HEAD request

this sample have been taken from: http://stackoverflow.com/questions/523930/sockets-in-c-how-to-get-the-response-stream and only one single line needed to be adapted to make a HTTP HEAD request instead of a get



using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO.Compression;

namespace HttpUsingSockets
{
public class Program2
{
private static readonly Encoding DefaultEncoding = Encoding.ASCII;
private static readonly byte[] LineTerminator = new byte[] { 13, 10 };

public static void Main2()
{
var host = "stackoverflow.com";
var url = "/questions/523930/sockets-in-c-how-to-get-the-response-stream";

IPHostEntry ipAddress = Dns.GetHostEntry(host);
var ip = new IPEndPoint(ipAddress.AddressList[0], 80);
using (var socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
socket.Connect(ip);
using (var n = new NetworkStream(socket))
{
// SendRequest(n, new[] { "GET " + url + " HTTP/1.1", "Host: " + host, "Connection: Close", "Accept-Encoding: gzip" });
SendRequest(n, new[] { "HEAD " + url + " HTTP/1.1", "Host: " + host, "Connection: Close", "Accept-Encoding: gzip" });

var headers = new Dictionary<string, string>();
while (true)
{
var line = ReadLine(n);
if (line.Length == 0)
{
break;
}
int index = line.IndexOf(':');
headers.Add(line.Substring(0, index), line.Substring(index + 2));
}

Console.WriteLine("Headers: ");

foreach (string key in headers.Keys)
{
Console.WriteLine("{0}: {1} ", key, headers[key]);
}

string contentEncoding;
if (headers.TryGetValue("Content-Encoding", out contentEncoding))
{
Stream responseStream = n;
if (contentEncoding.Equals("gzip"))
{
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
}
else if (contentEncoding.Equals("deflate"))
{
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
}

var memStream = new MemoryStream();

var respBuffer = new byte[4096];
try
{
int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
while (bytesRead > 0)
{
memStream.Write(respBuffer, 0, bytesRead);
bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
}
}
finally
{
responseStream.Close();
}

var body = DefaultEncoding.GetString(memStream.ToArray());
Console.WriteLine(body);
}
else
{
while (true)
{
var line = ReadLine(n);
if (line == null)
{
break;
}
Console.WriteLine(line);
}
}
}
}
}

static void SendRequest(Stream stream, IEnumerable<string> request)
{
foreach (var r in request)
{
var data = DefaultEncoding.GetBytes(r);
stream.Write(data, 0, data.Length);
stream.Write(LineTerminator, 0, 2);
}
stream.Write(LineTerminator, 0, 2);
// Eat response
var response = ReadLine(stream);
}

static string ReadLine(Stream stream)
{
var lineBuffer = new List<byte>();
while (true)
{
int b = stream.ReadByte();
if (b == -1)
{
return null;
}
if (b == 10)
{
break;
}
if (b != 13)
{
lineBuffer.Add((byte)b);
}
}
return DefaultEncoding.GetString(lineBuffer.ToArray());
}
}
}

All you need for TCP / HTTP IP Tunneling

Definition of tunneling (port forwarding) is the transmission of data intended for use only within a private or corporate network through a public network. This way data gets routed to a different destination. Usually it's nothing else the to encapsulate the private network data and protocol information to a public network. Tunneling simple allows Internet users (from a public network) to send and receive data from your home network (or any other private network).

One approach to tunneling is Point-To-Point tunneling protocol (PPTP) which has been developed by Microsoft and many other companies. The PPTP makes it possible to receive access to a private network (virtual private network - [VPN]) over your Internet service provider or any other online service.

Normally data will be encrypted and decrypted upon transfers. In cases where a high level of security is necessary the highest level is given by VPN iteself.

One some other researches I done i found a project who can manage that. The full source code project can be found below the following repository.


Update: Ian van Reenen request [comments] me to remove the code from this post. I did not fully understand why he means illegal but he ask for so i'll respekt it.
the code were public available in various source repositories withou any license terms - is ther a default license term when the owner does not add one? i don't know it.

anyway: soon I post a different solution for tcp tunneling - in the meanwhile you find a solution from mentalis.org over here.

the project descirption sounds good:

The proxy project is an implementation of an HTTP, FTP and SOCKS proxy server and PortMap server. It is very configurable and, as far as we know, very stable and secure. It is an excellent tool for .NET programmers who want to install a home network. All the classes are fully documented and can be used in other projects that require similar functionality. The project does not require you to have Visual Studio .NET.

Only return first IP which is IP4


// This is separate as we need to encapsulate more than FCL offers us
// It is here so it is reusable by all
// It only returns the first IP, that is by design. If you want the full
// list, use the FCL methods directly.
protected IPAddress ResolveAddress(string aAddress) {
IPHostEntry xIP = Dns.GetHostEntry(aAddress);
// Some host names (ie localhost) can return mult entries
// For now we want the first IP4 one, which is not always in [0]
return xIP.AddressList.First(x => x.AddressFamily == AddressFamily.InterNetwork);
}

The ISO 8601 format string


/// <summary>
/// The ISO 8601 format string.
/// </summary>

private const string Iso8601Format = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";

//SortableDateTimePattern (ISO 8601)
public static string ToIso8601(DateTime value)
{
return value.ToUniversalTime().ToString(Iso8601Format, CultureInfo.InvariantCulture);
}

public static DateTime ParseIso8601(string value)
{
return DateTime.ParseExact(value,
Iso8601Format, CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
}

Kayak is a lightweight HTTP server & framework

The Author say:
It's written in C#, it has been carefully designed to be true to the protocol it implements, get out of your way, and not tell you how to live. It is easy to integrate into a variety of applications, and is an excellent choice for creating interactive websites and web APIs. Whether your coming from ASP.NET, PHP, Django, or elsewhere, you’ll find Kayak to be refreshingly simple to use.

http://kayakhttp.com/

especially i liked the extensions to read / write http

using System;
using System.IO;
using System.Text;

namespace Kayak
{
struct HttpRequestLine
{
public string Verb;
public string RequestUri;
public string HttpVersion;
}

struct HttpStatusLine
{
public string HttpVersion;
public int StatusCode;
public string ReasonPhrase;
}

/// <summary>
/// A collection of extension methods to help speak HTTP.
/// </summary>
static class HttpExtensions
{
/// <summary>
/// Parses the first line of an incoming HTTP request.
/// </summary>
public static HttpRequestLine ReadHttpRequestLine(this Stream stream)
{
string statusLine = stream.ReadLine(Encoding.ASCII, 1024 * 4);

if (string.IsNullOrEmpty(statusLine))
throw new Exception("Could not parse request status.");

int firstSpace = statusLine.IndexOf(' ');
int lastSpace = statusLine.LastIndexOf(' ');

if (firstSpace == -1 || lastSpace == -1)
throw new Exception("Could not parse request status.");

var requestLine = new HttpRequestLine();
requestLine.Verb = statusLine.Substring(0, firstSpace);

bool hasVersion = lastSpace != firstSpace;

if (hasVersion)
requestLine.HttpVersion = statusLine.Substring(lastSpace + 1);
else
requestLine.HttpVersion = "HTTP/1.0";

requestLine.RequestUri = hasVersion
? statusLine.Substring(firstSpace + 1, lastSpace - firstSpace - 1)
: statusLine.Substring(firstSpace + 1);

return requestLine;
}

/// <summary>
/// Parses a list of HTTP request headers, terminated by an empty line.
/// </summary>
public static NameValueDictionary ReadHttpHeaders(this Stream stream)
{
var headers = new NameValueDictionary();
string line = null;

while (!string.IsNullOrEmpty(line = stream.ReadLine(Encoding.ASCII, 1024 * 4)))
{
int colon = line.IndexOf(':');
headers.Add(line.Substring(0, colon), line.Substring(colon + 1).Trim());
}

headers.BecomeReadOnly();

return headers;
}

public static void WriteHttpStatusLine(this Stream stream,
HttpStatusLine statusLine)
{
// e.g. HTTP/1.0 200 OK
string line = string.Format("{0} {1} {2}\r\n", statusLine.HttpVersion, statusLine.StatusCode, statusLine.ReasonPhrase);
byte[] statusBytes = Encoding.ASCII.GetBytes(line);
stream.Write(statusBytes, 0, statusBytes.Length);
}

public static void WriteHttpHeaders(this Stream stream, NameValueDictionary headers)
{
using (StreamWriter writer = new StreamWriter(stream, Encoding.ASCII))
{
writer.NewLine = "\r\n";

foreach (NameValuePair pair in headers)
foreach (string value in pair.Values)
writer.WriteLine("{0}: {1}", pair.Name, value);

writer.WriteLine();
writer.Flush();
}
}
}
}



some cool cookie extensions are also available:

using System.Text;
using System.Web;

namespace Kayak
{
static class CookieExtensions
{
public static HttpCookieCollection ParseAsCookieHeader(this string cookies)
{
var coll = new HttpCookieCollection();

if (!string.IsNullOrEmpty(cookies))
foreach (string cookie in cookies.Split(';'))
{
int index = cookie.IndexOf('=');
if (index >= 0)
coll.Add(new HttpCookie(cookie.Substring(0, index).Trim(), cookie.Substring(index + 1)));
}

return coll;
}

public static void CopyToHeaderDictionary(this HttpCookieCollection cookies,
NameValueDictionary headers)
{
foreach (string name in cookies)
headers.Add("Set-Cookie", cookies[name].ToSetCookieHeader());
}

public static string ToSetCookieHeader(this HttpCookie cookie)
{
var sb = new StringBuilder()
.Append(cookie.Name)
.Append('=')
.Append(cookie.Value);

if (cookie.Domain != null)
sb.Append("; domain=").Append(cookie.Domain);

if (cookie.Path != null)
sb.Append("; path=").Append(cookie.Path);

sb.Append("; expires=").Append(cookie.Expires.ToUniversalTime().ToString("r"));

if (cookie.Secure)
sb.Append("; secure");

if (cookie.HttpOnly)
sb.Append("; HttpOnly");

return sb.ToString();
}
}
}

Thursday, April 22, 2010

MOSS 2007 reading from list including attachments

The following code sample display how to read from a Sharepoint 2007 list which includes also attachments. I haven't used this code for MOSS 2010!

    

private ICredentials GetCredentials()
{
return new NetworkCredential("username", "password", "domain");
}

private DataRowCollection LoadSharepointData(string viewFields, string listName)
{
WebServiceRef.Lists sp = new WebServiceRef.Lists();
sp.Url = "http://your.sharepoint.com/_vti_bin/Lists.asmx";
sp.Credentials = GetCredentials();

// this part is needed to receive the link to document attachments and all specified fields
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
ndQueryOptions.InnerXml = "<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>";
ndViewFields.InnerXml = viewFields;
ndQuery.InnerXml = ""; // <Query />

XmlNode allLists = sp.GetListCollection();
XmlNode lists = sp.GetListItems(listName, "", ndQuery, ndViewFields, "10000", ndQueryOptions, "");

XmlNodeReader r = new XmlNodeReader(lists);
DataSet ds = new DataSet();
ds.ReadXml(r, XmlReadMode.Auto);

return ds.Tables[1].Rows;
}


WebServiceRef is a normal Web Service reference to Sharepoints List Webservice:
- http://your.sharepoint.com/_vti_bin/lists.asmx

The following code blocks contain various helper classes to extract data row by row, download attachments and saving data to a local folder.

Here we have the class to download files from Sharepoint:


public class AttchmentHandler
{
private static CookieContainer _cookieContainer;
public static CookieContainer CookieContainer
{
get
{
if (_cookieContainer == null)
{
_cookieContainer = new CookieContainer();
}
return _cookieContainer;
}
}

public class CookieAwareWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = AttchmentHandler.CookieContainer;
(request as HttpWebRequest).KeepAlive = false;
}
return request;
}
}

public string DownloadSharepointAttachment(string url, string filename, ICredentials credentials)
{
string localFolder = @"D:\\LocalFolder\\";

// ensure we do not overwrite files with the same name.
string uniqueGuid = Guid.NewGuid().ToString();
//now the code that will download the file
try
{
using (WebClient client = new CookieAwareWebClient())
{
client.Credentials = credentials;
// client.DownloadFile("http://address.com/somefile.pdf", @"c:\\temp\savedfile.pdf");
client.DownloadFile(url, localFolder + uniqueGuid + "_-_" + filename);
client.Dispose();
}
return localFolder + uniqueGuid + "_-_" + filename;
}
catch (Exception ex)
{
Console.WriteLine("DownloadSharepointAttachment: " + ex.Message);
return string.Empty;
}
}
}


To extract data from the DataRowCollection we have to Parse each row. For that i had to write 2 methods, one which retrieves the row and another one which extract the data from the column.



public void ParseAndExtractRow(System.Data.DataRow data, ICredentials credentials)
{
this.ContentTypeId = this.GetRowValue(data, "ows_ContentTypeId");
this.Title = this.GetRowValue(data, "ows_Title");
this.Date = this.GetRowValue(data, "ows_Date");

if (string.IsNullOrEmpty(this.Date))
this.Date = DateTime.Now.ToString();

DateTime.TryParse(this.Date, out this.DateTimeSorting);

this.Attribute_01 = this.GetRowValue(data, "Attribute_01");
// add here all other attributes
// ....
// ...
// ...
}

private string GetRowValue(System.Data.DataRow data, string columnName)
{
try
{
if (data[columnName] != null)
return data[columnName].ToString();
else
return string.Empty;
}
catch (Exception ex)
{
// Console.WriteLine(ex.Message);
return string.Empty;
}
}


Finally a method which uses all this code:

    private List<Data> ExtractList()
{
string listname = "SharepointListName";

string viewFields = "";
DataRowCollection rows = LoadSharepointData(viewFields, listname);
List<Data> data = new List<Data>();
int i = 0;
foreach (DataRow row in rows)
{
Data b = new Data();
try
{
b.ParseAndExtractRow("Name", row, GetCredentials());
data.Add(b);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
b = null;
}
}
return data;
}


enjoy

Tuesday, April 20, 2010

The security validation for this page is invalid. Click Back in your Web

While i was developing certain Sharepoint MOSS 2007 maintenance stuff I received the following error:

"The security validation for this page is invalid. Click Back in your Web..."

I developed the code against MOSS API and not on the website and was a kind of irritated about it!

The solution to solve this can be one of the following ways:

Option A)
turn off the security validation over your central administration:
- Central Administration
- Application Management
- Web Application Aettings
- "turn security validation off"

Option B)
You can modify the setting also within you coding:

SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(
delegate()
{
using (SPSite oSite = new SPSite("http://your.website.com/"))
{
using (SPWeb web = oSite.OpenWeb())
{
SPWebApplication webApp = web.Site.WebApplication;
webApp.FormDigestSettings.Enabled = false;
web.AllowUnsafeUpdates = true;


web.AllowUnsafeUpdates = false;
webApp.FormDigestSettings.Enabled = true;
web.close();
}
}
}
)
);

Monday, April 13, 2009

Compare DateTime - Linq and orderby

I had to create a small chart about Asp.Net Membership users. The easy way how to do this is to use the Method GetAllUsers(). Once we loaded all Membership data we ready to run over our data with 2 simple LINQ statements:

      DateTime now = DateTime.UtcNow;
Dictionary<datetime,> day = new Dictionary<datetime,>();
for (int i = 0; i < 7; ++i)
{
DateTime compareDate = new DateTime(now.Year, now.Month, now.Day);
compareDate = compareDate.AddDays(-i);
var d = from a in data
where a.CreationDate.Year == compareDate.Year &amp;&amp;
a.CreationDate.Month == compareDate.Month &amp;&amp;
a.CreationDate.Day == compareDate.Day
orderby a.CreationDate descending
select a;
day.Add(compareDate, d.Count());
}

Dictionary<datetime,> month = new Dictionary<datetime,>();
for (int i = 0; i < 12; ++i)
{
DateTime compareDate = new DateTime(now.Year, now.Month, now.Day);
compareDate = compareDate.AddMonths(-i);
var d = from a in data
where a.CreationDate.Year == compareDate.Year &amp;&amp;
a.CreationDate.Month == compareDate.Month
orderby a.CreationDate descending
select a;
month.Add(compareDate, d.Count());
}

Thursday, December 11, 2008

Easly reading RSS Feeds or ATOM Feeds with System.ServiceModel.Syndication in C# with .net 3.0

Less code lines are almoast not possible! But one leak is available; the load method always download the full items and there is no option only to download item headers.

The formatted version is also available at my website: http://www.ronischuetz.com/code/reading_rss_atom_feeds.html


using System;

using
System.Collections.Generic;

using
System.Linq;

using
System.Text;

using
System.Collections.ObjectModel;

using
System.Xml.Linq;

using
System.IO;

using
System.Net;

using
System.ServiceModel.Syndication;

using
System.Xml;



namespace
ConsoleApplication1

{

class Program

{

static void Main(string[] args)

{

DateTime start
= DateTime.Now;

List<string> urls = new List<string>();

urls.Add("http://feedproxy.google.com/RoniSchuetz");

urls.Add("http://www.tagesanzeiger.ch/rss.html");

foreach
(var item in urls)

{

Console.WriteLine(item)
;

Reader(item);

}

TimeSpan d
= DateTime.Now - start;

Console.WriteLine(d.TotalMilliseconds);

Console.ReadLine();

}

private static int counter = 0;

private static void
Reader(string url)

{

SyndicationFeed blogFeed
= null;

try

{

// Read the feed using an XmlReader

using (XmlReader reader = XmlReader.Create(url))

{

// Load the feed into a SyndicationFeed

blogFeed = SyndicationFeed.Load(reader);

}

}

catch (Exception ex)

{

if (ex is WebException ex is XmlException)

{

// Handle bad url, timeout or xml error here.

Console.WriteLine("Handle bad url, timeout or xml error here: " + ex.Message);

}

else

Console.WriteLine("second case: " + ex.Message);

}

// Use the feed

foreach (SyndicationItem item in blogFeed.Items)

{

Console.WriteLine((++counter) +
" " + item.Title.Text);

}

}

}

}

Monday, October 27, 2008

ajax status display like google apps

during cleanup of my files i found the following Javascript status display js class.

unfortunately i don't know from where i have downloaded it, so if you know let me know that I can update this entry and add a link to the owner.

var ajaxStatus = Class.create();
ajaxStatus.prototype = {
ajaxStatusDisplayUserMessageElementID: 'ajaxStatusDisplay_userMessage',
ajaxStatusContainerID: 'ajaxStatusContainer',
ajaxStatusContainerCssClass: 'ajaxStatusDisplay_userStyle',
userDefinedAjaxStatusContainerCssClass: false,
ajaxStatusMessageContainerID: 'ajaxStatusMessageContainer',
ajaxStatusMessageContainerCssClass: 'ajaxStatusDisplay_userMessageStyle',
userDefinedAjaxStatusMessageContainerCssClass: false,
useUserCssStylesContainerID: 'ajaxStatusDisplay_useUserCssStyles',
statusMessage: 'Loading...',
useUserCssStyles: false,
/*
Function: initialize
Description: Creates the hidden status display elements and configures
the default status message and css styles
*/
initialize: function() {
// Create the ajax status container
Element.insert(
$$('body')[0],
{'bottom':
new Element('div', {
id: this.ajaxStatusContainerID,
style: 'display: none'
})
}
);

// Create the ajax status message container
Element.insert(
$(this.ajaxStatusContainerID),
{'bottom':
new Element('div', {
id: this.ajaxStatusMessageContainerID
})
}
);

// Setup the css styles
this.setCssStyles();

// Setup the status message text
this.setStatusMessage('');

// Register the global Ajax responders
// to show hide the status container
Ajax.Responders.register({
onCreate: this.toggle.bindAsEventListener(this),
onComplete: this.toggle.bindAsEventListener(this)
});
},
setCssStyles: function() {
// If the user has defined styles
if (document.styleSheets.length > 0) {
var theRules = new Array();

// If this is Firefox or other W3C complient browser
if (document.styleSheets[0].cssRules) {
theRules = document.styleSheets[0].cssRules;
}
// If this is IE
else if (document.styleSheets[0].rules) {
theRules = document.styleSheets[0].rules;
}

// Loop over the css rules
for (i = 0; i < theRules.length; i++) {
// If the current rule matches the name of the ajax status container css class
if (theRules[i].selectorText == '.' + this.ajaxStatusContainerCssClass) {
this.userDefinedAjaxStatusContainerCssClass = true;
}
// If the current rule matches the name of the ajax status message container css class
else if (theRules[i].selectorText == '.' + this.ajaxStatusMessageContainerCssClass) {
this.userDefinedAjaxStatusMessageContainerCssClass = true;
}
}
}

// If the user definfed css styles with the specific name
// for the ajax status container
if (this.userDefinedAjaxStatusContainerCssClass) {
// Set css class name for the container
$(this.ajaxStatusContainerID).addClassName(this.ajaxStatusContainerCssClass);
}
else {
// The user has not defined the custom css style class
// so apply default style
$(this.ajaxStatusContainerID).setStyle({
position: 'absolute',
left: '45%',
top: '2px',
height: '10px'
});
}

// If the user definfed css styles with the specific name
// for the ajax status message container
if (this.userDefinedAjaxStatusMessageContainerCssClass) {
$(this.ajaxStatusMessageContainerID).addClassName(this.ajaxStatusMessageContainerCssClass);
}
else {
// The user has not defined the custom css style class
// so apply default style
$(this.ajaxStatusMessageContainerID).setStyle({
background: '#FFF1A8 none repeat scroll 0%',
color: '#000',
padding: '0pt 5px',
fontFamily: 'Arial, Helvetica, sans-serif',
fontSize: '14px',
fontWeight: 'bold',
textAlign: 'center',
width: '100%'
});
}
},
setStatusMessage: function(statusMessage) {
if (!statusMessage.empty()) {
this.statusMessage = statusMessage;
}
else {
// If there is an element on the page with a user defined status message
if ($(this.ajaxStatusDisplayUserMessageElementID)) {
// If the user's status message is inside a input element
if ($(this.ajaxStatusDisplayUserMessageElementID).readAttribute('value') != null) {
// Use the value of the input element
// for the display as the status
this.statusMessage = $F(this.ajaxStatusDisplayUserMessageElementID);
}
else {
// Use the value of the element for the display as the status
this.statusMessage = $(this.ajaxStatusDisplayUserMessageElementID).innerHTML;
}

// Hide the user's status message container
$(this.ajaxStatusDisplayUserMessageElementID).hide();
}
}

$(this.ajaxStatusMessageContainerID).update(this.statusMessage);
},
toggle: function() {
$(this.ajaxStatusContainerID).toggle();
}
};

document.observe("dom:loaded", function() {
// Create an instance of the object defined above
ajaxStatusDisplay = new ajaxStatus();
});

Monday, October 20, 2008

Backup and Restore Database for SQL Server

@echo off
@echo BatchJob Start
@echo %date% %time% %0 Start >> ".\!Log\all.log"
@echo on

"Start backup database DISK='%cd%\ABC.bak'" >> ".\!Log\all.log"
osql /E /S localhost /Q "backup database DISK='%cd%\ABC.bak'"
"c:\Program Files\WinRAR\winrar" a ABC.rar erp.bak -df -ibck
"Done backup database DISK='%cd%\ABC.bak'" >> ".\!Log\all.log"

REM NOW WE RESTORE IT

"Start restore database DISK='%cd%\ABC.bak'" >> ".\!Log\all.log"
osql /E /Q "restore database ERP from DISK='%cd%\ABC.bak'"
"Done restore database DISK='%cd%\ABC.bak'" >> ".\!Log\all.log"

@echo off
@echo %date% %time% %0 End >> ".\!Log\all.log"

Sunday, October 19, 2008

C# Cross-Thread Operations made easy

Starting with .Net Framework 2.0 and higher, it's a must to write cross-thread operations.

Cross-thread operations in C# are calls on the method that attempts to access an object that was created in a different thread.

Lets say we would like to load data into a DropDown Control from a Background thread we will receive the following error:

Cross-thread operation not valid: Control 'Abc' accessed from a thread other than the thread it was created on.

We can solve this by using simple delegate and the attribute InvokeRequired. Lets look on 2 samples how to succeed with this once with and once without a parameter:


   1:  private delegate void DelegateManageLink(string url, bool isEmail);

   2:   

   3:  private void ManageLink(string url, bool isEmail)

   4:  {

   5:      if (this.InvokeRequired)

   6:      {

   7:          DelegateManageLink inv = new DelegateManageLink(this.ManageLink);

   8:          this.Invoke(inv, new object[] { url, isEmail });

   9:      }

  10:      else

  11:      {

  12:          if (!string.IsNullOrEmpty(url))

  13:          {

  14:              string tmp = (isEmail == true ? "mailto:" : "") + url;

  15:              System.Diagnostics.Process.Start(tmp);

  16:          }

  17:      }

  18:  }



Sample without parameter:

   1:  /// <summary>

   2:  /// A delegate method to invoke a method and prevent threading concurrent access

   3:  /// </summary>

   4:  private delegate void DelegateCheckServerVersions();

   5:  private void CheckServerVersions()

   6:  {

   7:      if (this.InvokeRequired)

   8:      {

   9:          DelegateCheckServerVersions inv = new DelegateCheckServerVersions(this.CheckServerVersions);

  10:          this.Invoke(inv, new object[] { });

  11:      }

  12:      else

  13:      {

  14:          // your stuff goes here ..

  15:      }

  16:  }

Friday, October 10, 2008

SGML Reader - convert HTML to XHTML

This is a web - based implementation of converting HTML to well-formed XHTML using a solution which could be found in the past at the following location:
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=B90FDDCE-E60D-43F8-A5C4-C3BD760564BC
There is one problem with this location, Microsoft closed gotdotnet.com so I decided to upload my adapted version. Maybe somebody knows how is the creator of this library so I can add this here.

You can download it from here: www.ronischuetz.com/download/sgmlreader.zip

Tuesday, August 26, 2008

Build a Web Chat Application using ASP.Net 3.5, LINQ and AJAX (in C# 3.5)

Junnark Vicencio explains how to build a chat application within 2 hours.

Technologies Used: ASP.Net 3.5, AJAX, JavaScript, C# 3.5, LINQ-to-SQL, MS SQL Server 2000/2005

http://www.junnark.com/Articles/Build-a-Web-Chat-Application-Using-ASP-Net-LINQ-and-AJAX-CS.aspx

Sunday, February 10, 2008

Threaded Asynchronous Tcp Server with a blocking Client

I don't know now how many prototypes I have written in the past few weeks to verify which approach would fit best to scale and be most performance for indeXus.Net Shared Cache. To write a Client / Server Architecture which mostly will be N:M connectivity was not that easy as I thought in beginning.

Honestly I believe I have study every single C# sample I found on the common search engines and arrived to the point where I started to adapt the samples. Unfortunately 99% of founded samples are showing how to pass a string from the client to the server beside one blog which has written down a lot of theory and some very nice diagrams without to come up with code. I only can recommend you to read this blog up and down before you write even one single line of code: http://www.coversant.net/Coversant/Blogs/tabid/88/EntryID/10/Default.aspx. There are some very smart people around they have done great work.

After a while of research, I get to koders.com where I found a strip-down version of their product.

Another very useful page with a lot of sample code around .net is Mike Woodrings's .net Sample Page which contains a bunch of great examples for different domains.

I think I have tried any way to use Sockets now:


  • Blocked Sockets
  • Unblocked Sockets
  • Poll Sockets
  • Select

Every prototype I have done so far had his advantages and disadvantages. In the end of this post I will provide 2 downloads:

  • prototype with poll sockets on client and server
  • protptype with block sockets on client side and async server handling
Once I get comfortable with all the different Issues which come across the write the server part I decided to use Asad Aziz - Asynchronous Server Socket using C# Sample as my base for the server. Its very easy written but my knowledge on this issue was limited until I started to work on it quite intensive and I think I learned every day at least 10 new things :-)

Lets dive into different key parts of the client and the server. An additional issue I would like to mention here is that the whole code is 100% managed.

We gone start first with the server. As already mention the server is working Asynchronous which means we have to handle with IAsyncResult. Upon Server start we begin run the server within a different thread and the client cleanup will be handled by a TimerCallback to purge disconnected clients in case they not removed before upon disconnection.

ThreadStart serverListener = new ThreadStart(this.StartListening);
serverThread[0] = new Thread(serverListener);
serverThread[0].IsBackground = true;
serverThread[0].Start();
TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
this.lostTimer = new Timer(timerDelegate, null, SharedCacheTcpServer.timerTimeout, SharedCacheTcpServer.timeoutMinutes);

Since we have started now the serverListener we Bind the server IPEndPoint to the requested ip and port and start to listen for connections from clients. Once a connection is received it only will be destroyed in one of the following 2 cases:

  1. The Socket has not been used for a certain amount of time
  2. Client Socket get disconnected.

With this we avoid to much Server resources. As started we will use a ManualResetEvent to accept only one by one client. I have commented this part for testing purposes and the server started to throw memory exceptions. So keep it simple in the meaning, only start a new BeginAccept once you finished to move the client into AccecptCallback.

private void AccecptCallback(IAsyncResult ar)
{
// signal main thread to continue
this.allDone.Set();
Socket clientListener = ar.AsyncState as Socket;
if (clientListener != null)
{
Socket handler = clientListener.EndAccept(ar);
Console.WriteLine(@"Connected by client: {0}", handler.RemoteEndPoint);
StateObject state = new StateObject();
state.WorkSocket = handler;
state.AliveTimeStamp = DateTime.Now;

... and some more code ..

once you have done all setup for you StateObject (this is the object which contains all different data between the calls) we able to call BeginReceive. SharedCache Protocol between client and server keep simple: [messageLength][message] so if we are not able to get the whole message at once we have to call several times BeginReceive until we have received everything from the client and we able to run the custom stuff on the server.

Once we done with our reading we can start to process received package and process with it. To keep server resources (amount of threads) under control I decided to use Mike's Threadpool.


I think the 2 most important parts are within this message is to know that we need to read the header which indicates to message length and if we need to read more data for this message or do we can proceed it arrived data.

// check for header
if (state.ReadHeader) { .....


// check for message length -> TODO: how to check longer values as int count in list????
if (state.DataBuffer.ToArray().LongLength == state.MessageLength) { ...


as you can see there is even one open point since I use in my state object a List. I had some discussions with people on asp.net forums but I believe i can life right now with this
int.MaxValue as maximal message length ;-)


the next key position in above code print screen is that we use at this place again handler.BeginReceive() since we want to client connection keep opened as long as possible. Some previous tests had shown me while i open and close 1000 Sockets the time reduction to use always the same is more then 50%. Before we can post the request into ThreadPool we need to remove the Range of our message size [8 bytes] that's why we do: state.DataBuffer.RemoveRange(0,8); once we have posted it to the threadpool to pool handles the message sending the Echo to the waiting client.
HandleClientMessage is the place which is called after you get the free Thread from the ThreadPool - here you can manage your Server side stuff and once you done you can send it back to the Client. If you work within Winform environment a more event driven design would be correct but for sharedcache this would not be correct since the client is waiting for the server response.



in the above example we do nothing else then to set an Attribute of the object IndexusMessage to Successful.
The response from the server needs to be prepared, then also the client waits for the same struct [message length][message data]. Therefore we call UtilByte.CreateMessageHeader(with the msg.GetBytes() which returns a byte array) and we combine both values to 1 single byte array. since this is done we can free up resources and set the actual messageLength on the state so we know how much data we need to send to the client which is not less important.



Within the Send() method we start the async call: socket.BeginSend() or if we do not have anything to send back (this case does not happen here) we reset all state data and start to receive again without to destroy the state and the socket which is included in the state. The
same idea happens within the SendCallback() we call BeginSend() as long we have data to send and once we sent everything to the client we reset the state and start to receive again with socket.BeginReceive().

These are all important parts on the server side, I will wrap up the client in a different post within the next few days.

The 2 best code-solution I have found on the web are the following 2 links:

http://www.codeproject.com/KB/IP/Generic_TCP_IP_server.aspx
http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx

Both of them could not handle the case I needed so I hope people can use the Prototypes in this or another way. It would be great if you let me know if you are using them. So here are the downloads:


I really would like to say "thank you very much" to all contributors of the following articles and coding samples:

Shared Cache - .Net Caching made easy

All information about Shared Cache is available here: http://www.sharedcache.com/. Its free and easy to use, we provide all sources at codeplex.

Facebook Badge