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; }
}
}
}
Sunday, May 02, 2010
Async Socket Server Sample in C#
at
11:00 PM
1 comments
Posted by
roni schuetz
Labels: C#, code sample, sync vs async
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");
}
}
}
at
10:56 PM
0
comments
Posted by
roni schuetz
Labels: C#, code sample
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();
}
}
}
}
at
10:54 PM
0
comments
Posted by
roni schuetz
Labels: C#, code sample
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());
}
}
}
at
12:46 PM
0
comments
Posted by
roni schuetz
Labels: C#, code sample
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.
at
11:00 AM
2
comments
Posted by
roni schuetz
Labels: C#, code sample
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);
}
at
10:46 AM
0
comments
Posted by
roni schuetz
Labels: C#, code sample
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);
}
at
10:44 AM
0
comments
Posted by
roni schuetz
Labels: C#, code sample
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();
}
}
}
at
9:54 AM
0
comments
Posted by
roni schuetz
Labels: C#, code sample, extensions
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
at
12:25 PM
0
comments
Posted by
roni schuetz
Labels: code sample, MOSS, sharepoint 2007
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();
}
}
}
)
);
at
11:29 AM
1 comments
Posted by
roni schuetz
Labels: C#, code sample, MOSS, sharepoint 2007
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 &&
a.CreationDate.Month == compareDate.Month &&
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 &&
a.CreationDate.Month == compareDate.Month
orderby a.CreationDate descending
select a;
month.Add(compareDate, d.Count());
}
at
8:12 PM
0
comments
Posted by
roni schuetz
Labels: C#, code sample, LINQ
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);
}
}
}
}
at
2:07 PM
0
comments
Posted by
roni schuetz
Labels: .net, asp.net, C#, code sample
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();
});
at
10:25 AM
0
comments
Posted by
roni schuetz
Labels: code sample, java script
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"
at
1:00 PM
0
comments
Posted by
roni schuetz
Labels: batch, code sample, Database, SQL Server
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: }
at
8:56 PM
1 comments
Posted by
roni schuetz
Labels: .net, C#, code sample, Windows Forms
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
at
10:30 PM
1 comments
Posted by
roni schuetz
Labels: .net, asp.net, C#, code sample, Helper Code, xhtml
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
at
11:10 PM
0
comments
Posted by
roni schuetz
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
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:
- The Socket has not been used for a certain amount of time
- 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
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:
- Atif Aziz for all his good suggestions about how to handle the different issues
- Gil Y. - Generic TCP/IP Client / Server
- Andre Azevedo - An Asynchronous Socket Server and Client
- Mike Woodring - Custom Thread Pool
- Chris Mullins - Windows Sockets and Threading: How well does it scale?
- Mark Strawmyer - Communication over Sockets: Blocking vs Unblocking
at
1:34 PM
4
comments
Posted by
roni schuetz
Labels: .net, C#, cache, code sample, debug, development, Helper Code, memory, network, performance, SharedCache, SharedCache thought, Threading