September 18, 2008

HTTP Connection Limit in .Net

There exists a web specification which suggests a server endpoint only allow up to two connections from any client at a time. The .Net Framework builds this limit in by default. This means that if you are trying to use HTTPWebRequest, WebRequest, etc, and attempt to maintain more than two connections at a time, it simply will not work. There is a rare case where a client application would require more than two maintained connections, though we found one in trying to watch more than two camera feeds from a video server. You can get around this limitation by changing the default connection limit like so:

System.Net.ServicePointManger.DefaultConnectionLimit = 4;

Creating .Net COM objects for interop with VB6

.Net has some nice tools to help you create COM objects. .Net COM objects are slightly different from regular that regular COM objects in that the .Net is still in its intermediate language form. Because of this, you cannot register a .Net COM object with "regsvr32" as usual, you must use "regasm", which comes with the .Net framework.

There are a few project properties that in Visual Studio that will do a lot of the work for you. First, create a standard class library project, or open an existing one. Go to the project properties and change the following settings. On the "Application" tab, click the "Assembly Information" button. Check the box to "make assembly com-visible". This option will wrap your library as a COM library. Next go to the "Build" tab and check the box to "Register for COM interop". This option will automatically register the output dll with regasm on the current machine after a build. The final, optional step is to go to the "Signing" tab and check the box to "Sign the assembly". Choose "New" in the pull-down for the sign file. Give it a name and a password if you would like. Signing helps to keep similar objects in different dlls from getting mixed up during runtime.

Now that we have our project prepped, now we need to create our objects. The only real requirement on your classes is that they have a public constructor. All of the attributes that you will find in this article can be accessed by including the following namespace:

using System.Runtime.InteropServices;

To flag a class as an object that you would like to be available in your COM library, use the following class attribute:

[ClassInterface(ClassInterfaceType.AutoDual)]

This attribute tells the compiler to automatically create an interface for this class and do the other magic that is required to create a COM object. That is all you have to do to create a simple COM object. If you compile right now, you should be able to access the library from the add references portion of a development tool that can use COM libraries.

Often times you will want to have events in your class. To support .Net events, you will need to do a few extra steps. First you must create an interface with METHOD declarations for each one of your events. So for example, this event:

public void delegate MyEventHandler(int a, double b);
public event MyEventHandler MyEvent;

would have a declaration in the interface that looks like this:

void MyEvent(int a, double b);

Now place this attribute on your interface:

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

and this attribute on your class:

[ComSourceInterfaces(typeof(IMyEvents))]

where "IMyEvents" is the name of your interface. DO NOT declare this interface as an interface of your class. The compiler will take care of everything for you underneath. These attributes do some magic that allows other languages to hook into the .Net events properly.

Here is a simple complete example:

using System.Runtime.InteropServices;

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyEvents
{


void MyEvent(int a, double b);

}


[ComSourceInterfaces(typeof(IMyEvents))]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class MyClass
{


public void delegate MyEventHandler(int a, double b);
public event MyEventHandler MyEvent;


public int MyProperty { get; set; }

public void MyMethod() { }

}


To use this COM object in VB6, declare it like normal:

Dim WithEvents myComObject As MyCLass

One thing to note is that VB6 has a bug that gives a compile error whenever you try to call a .Net method that takes an array parameter. In order for arrays to work properly, the parameters must be passed by reference using the 'ref' keyword before the parameter declaration.

July 16, 2008

A Quick Note On Ports and Sockets

At this point, most people are familiar with the use of an IP address. Basically it is a unique number used on a network to identify a network computer. When we talk about computers communicating with each other, an IP address alone is useless. A single computer may have many programs running that want to communicate over the network. This means that a single address point (the IP address) is not enough to define what program a remote computer would like to communicate with. This is where port numbers come in. A program can bind itself to one or many open ports (meaning they are not currently in use by another program). Once bound to a port, a remote computer can communicate with a program by addressing the computer's address (IP) along with the program's address on that computer (Port).

A common misconception is that a socket represents a bound port on a computer (the IP:Port pair). In reality, this is only half of what a socket represents. In fact, a socket represents two IP:Port pairs: one for the host, and one for the client. This means that multiple remote computers can connect to a program via the same port while each connection is represented by a different socket. Each socket is unique because they each have a different remote IP:Port pair even though they all have the same host IP:Port pair. To take this a little further, one remote computer can have multiple connections to a port on a host. This is possible because each remote connection will be bound to different ports on the remote machine, again giving us unique IP:Port pairs for each socket connection.

The way this generally works behind this scenes goes something like this. The host computer will open a socket which it will bind to some port to listen for incoming connections. When a remote computer connects, the listening socket will create a new socket and bind it to the host and connecting remote IP:Port pairs. The original listening socket will then continue listening on its bound port for more incoming connections. Sockets are typically implemented in this way because only a single connection can be represented by a socket at a time. The original socket could have handled the communications of the incoming connection itself, but there would then be no socket open to listen for other incoming connections.

July 2, 2008

Visual Studio Project Settings

When I first started using the settings feature that was built into Visual Studio, I thought that they were pretty straight forward. It turns out that I had virtually no idea what was really going on. This is probably has mostly to do with MSDN's lack of documentation, as usual. Now I will attempt to lay out how this monster really works.

First goto the properties page of a project and goto the settings tab. From here you can set up either Application or User settings. It turns out that the differences are pretty self explanitory. A user setting will actually end up in a user.config file burried in the Documents And Settings folder for each user. This means that each user will be able to have a different set of settings for these. Application settings are actually read from the myapp.exe.config file in the application path (usually in Program Files).

To access these settings from code, all you need to do is:

string mySetting = Properties.Settings.Default.MySetting;

If you are accessing a user setting, the program will first look in the user.config file burried in the user's Documents And Settings, then in the myApp.exe.config file, and finally in the hardcoded default values. For an application setting, the same order is used starting at the myApp.exe.config file.

To add to the excitement, it turns out that it is only possible to save user settings from your application. If you are writing to a user setting to the user.config file in the user's Documents And Settings, all you have to do is:

Properties.Settings.Default.MySetting = mySetting;
Properties.Settings.Default.Save();

If you want to save a user setting or an application setting to the myApp.config file in the application's path, there is no built in way. You will have to resort to loading the file into an XML DOM API and edit the file manually.

The main point to recognize here is that even if you uninstall an application, the user settings will stick around in the Application Data for a user, and magically reappear next time the application is installed. These files must be removed if you want to reset your user settings.

January 16, 2008

TableAdapter.Update Error

Error Exception: InvalidOperationException

Error Message: Update requires a valid UpdateCommand when passed DataRow collection with modified rows.

Problem: The update command is missing from the table adapter.

Cause: I believe that this must have occured by changing the database structure after the dataset was created from it.

Solution: Configure the data table of for the table in question. Assure that "Generate Insert, Update and Delete Statments" is checked inside of Advanced Options. Finish the wizard. Your command statements will be rebuilt (including the Update command).

January 4, 2008

The wonderful world of UDP Broadcasts

I have been working on a set of server/client applications lately. Basically, the server and client communicate via TCP. This means you need to provide an IP address and port number that the server is on so that the client can connect to it. The problem is that many users do not understand what an IP address is, much less how to find one; all hope is lost, then, if they must supply a port as well. The port problem is somewhat resolved in that the port number is typically fixed. No mater what machine the server is on, it will always communicate on say, port 4040. This will only be a problem if another application on the same machine is also attempting to use port 4040. The more complex issue to try to get around is obtaining the IP address. Every machine will have a different IP address, and even then it may change every time you enable its network device.

Now assuming that your server and client will be on two machines that are very close to one another (not spanning across the internet), there is a nice way to build into your server and client that will help the client 'magically' figure out the server's IP address. The answer lies with UDP broadcasts. UDP is similar to TCP in that they both require an IP address and a port number. The beauty of UDP is that it allow something called a broadcast. A broadcast will allow you to send information to a certain port, but to every computer on your network. If there is an application listening on that port on any computer on the network, it will be able to receive the information. There is also a Time To Live (TTL) associated with the UDP broadcast which says how many routers deep the transmission is to go.

The way we will work our 'magic' is by having our client broadcast a message via UDP broadcast to a port that our server will be listening on. Once the server receive the information, it automatically gets the IP address of the client along with it. Once we have the client's IP address, we can send that client a UDP message on a port that it will be listening on to the IP that we obtained. Once the client receives that message, guess what, we now automatically get the IP address of the server. Now that we have the IP address of the server, we can connect to our server via TCP to the port that it is listening on.

Here is an idea of what some of the code may look like.

The following segment of code shows how we can open a UDP socket to listen for any incoming messages on port 4040.



using System.Net;
using System.Net.Sockets;

...

IPEndPoint endpoint = null;
int port = 4040;
UdpClient listener = new UdpClient(port);

byte[] receivedData = listener.Receive(endpoint);

IPAddress addressOfSender = endpoint.Address;



The following segment of code shows how we can open a UDP socket to broadcast a message on port 4040 to all network computers.

using System.Net;
using System.Net.Sockets;

...

int port = 4040;

//IPAddress.Broadcast can be replaced with a specific IP here if we do not want to broadcast to everyone
IPEndPoint broadcastEndpoint = new IPEndPoint(IPAddress.Broadcast, port);
UdpClient broadcaster = new UdpClient();

byte[] broadcastData = /* assign some data do broadcastData */;

broadcaster.Send(broadcastData, broadcastData.Length, broadcastEndpoint);


I have implemented the UDP broadcast mechanism that I have mentioned above into my projects. The result is that now I can put my client and server on any two computers on the network, and they will automatically start communicating with one another without having the user supply an IP address or a port. It is often suggested that if you use this method that you still provide a way to allow the user to manually supply the IP and port in the event that UDP transmission are blocked on some firewall or router. It is also likely that you will want to modify the above code to use asynchronous sends and receives by replacing listener.Receive with listener.BeginReceive and broadcaster.Send with broadcaster.BeginSend. There is, of course, a bit of other code that will be needed to implement asynchronous transmissions, but that is beyond the scope of this article. Happy broadcasting!