Visual C # to establish a simple messaging system (2)

Source: Internet
Author: User
Tags reflection socket thread port number
visual object-oriented design vs. pragmatism

One of the drawbacks of this approach is that you have to end up with a big switch statement, but seniors have been teaching us that Big Switch statements are poor design performance. The common object-oriented (object Oriented,oo) approach is to use polymorphism (polymorphism). To do this, we first create an abstract base class (base class), and then derive all the message objects from that class. Each class needs to perform multiple methods such as serialization, parallelization, and processing of messages, and the main code is:

· Reading message types

· Create an instance (using reflection)

· Call virtual Handlemessage () function

This is achievable, but the effect is poor and I don't like it. First, it's hard to write code that builds an instance, and it's slower because it uses reflection. More importantly, the processing of the message is not within the handlemessage () function, which means it must be part of the shared library. This is not appropriate because the processing of the message has nothing to do with how the message is delivered. As a result of these problems, I still decided to use a less object-oriented but easier way to write.

The preceding example handles only a single message. In the real world, we need to handle multiple messages at the same time.

Server-side Multithreading

My ultimate goal is to add the functionality of the server program to an existing application. Because I don't want to modify the code of an existing application, I have to run the server program on a thread. Again, I want to be able to accept multiple connections at the same time.

The example above is listening on port 9999, but since a client can only talk to one port, I need to use a different port for each connection. The SocketListener class will be monitored on port 9999 and, when a new connection request arrives, it will look for an unused port and send it back to the client. The following is a general scenario for this class:

public class SocketListener
{
int port;
Thread thread;

public SocketListener (int port)
{
This.port = port;
ThreadStart ts = new ThreadStart (waitforconnection);
thread = new thread (TS);
Thread. IsBackground = true;
Thread. Start ();
}

public void Waitforconnection ()
{
The main code
}
}


Waitforconnection () is the way to do all of these operations. The constructor of this class executes the task of creating a new thread that will run Waitforconnection (). Opening the socket and accepting the connection is similar to the previous example. The following is the main loop for the thread:

while (true)
{
Console.WriteLine ("Waiting for initial connection");
Listener. Start ();
Socket socket = listener. AcceptSocket ();
NetworkStream stream = new NetworkStream (socket);
BinaryReader reader = new BinaryReader (stream);
BinaryWriter writer = new BinaryWriter (stream);

Console.WriteLine ("Connection requested");

int userport = port + 1;
TcpListener Specificlistener;
while (true)
{
Try
{
Specificlistener =
New TcpListener (LOCALADDR, Userport);
Specificlistener.start ();
Break
}
catch (SocketException)
{
userport++;
}
}
Remote users should use Specificlistener.
Send the port back to the remote user and set up a server application for us on that port.
Socketserver socketserver = new Socketserver (Specificlistener);

Writer. Write (Userport);
Writer. Close ();
Reader. Close ();
Stream. Close ();
Socket. Close ();
}

I want to be able to support multiple connections, so use a port to make it easier for clients to indicate that they want a connection, then the server program finds an empty port and sends that port back to the client, which is used for a specific client connection.

I didn't find a way to find unused ports, so the while loop was used to find unused ports. It then sends the port number back to the client and clears the object.

Here's a little bit of subtlety to point out. The original version of Socketserver the port number as a parameter. Unfortunately, this means that the client cannot make a request before the listener is established on the port, which is bad. To prevent this, I set up a tcplistener before sending the port number to the client, which ensures that there is no such emergency.

The Socketserver class creates additional threads and uses the following main loop:

Try
{
while (true)
{
MessageType MessageType = (messagetype) reader. ReadInt32 ();

Switch (MessageType)
{
Case Messagetype.requestemployee:
Employee Employee =
New Employee ("Eric Gunnerson", "one Microsoft Way");
Employee. Send (writer);
Break
}
}
}
catch (IOException)
{

}
Finally
{
Socket. Close ();
}

This main loop is a simple loop to get request/process requests. Try-catch-finally is used here to recover from an exception when the client disconnects.

Events for clients

On the client side, I wrote a traditional Windows client program that I could use for my PC or for my Pocket PC. The Windows Forms environment is event-based and is ideal for using event-handling socket messages. This is done through the Socketclient class. The first step is to define a delegate and event for each message:

public delegate void Employeehandler (employee employee);
public event Employeehandler employeereceived;

The second step is to write the code that sends the event:

Case Messagetype.employee:
Employee Employee = new Employee (reader);
if (employeereceived!= null)
Form. Invoke (employeereceived, new object[] {employee});
Break

The form should be updated when the event occurs. To be more reliable, this operation needs to occur on the main UI thread. This is implemented by invoking the form's Invoke (), which will schedule the delegate to be invoked on the main UI thread.

Because of this message based architecture, the server program has built-in support for asynchronous events. The example has a currentcount message, which is sent by the server program every second.

Summarize

I am satisfied with this socket based architecture, which is lightweight and easy to use, and it can run on both PC and Pocket PCs.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.