Click here to Skip to main content
Click here to Skip to main content
Go to top

Fundamentals about data communication using socket with SocketPro

, 23 Feb 2002
Rate this:
Please Sign up or sign in to vote.
Socket, Data communication, internet/intranet, non-blocking

Purpose

This short article is written for telling you fundamentals about SocketPro, which helps you quickly write super client and server applications based on internet/intranet socket. It also comments on other technologies such as DCOM, Corba and Java Bean/RIM. These comments will help you understand the design principles of SocketPro. It is expected that you are a professional with development of distributed applications across machines. If you have any doubts, concerns and comments, please send them to UDAParts at yekerui@yahoo.com.

Two data communication patterns using socket

To understand the design principle of SocketPro, you'd better understand and compare the following two data communication patterns between a client and a server. Once you understand the two patterns, it is highly recommended that what data communication patterns are used with other popular technologies, DCOM/MTS, Cobra and Java Bean/RIM. You could think the data movement efficiency over internet/intranet with these popular technologies rooted on socket. In order to better understand the two data communication patterns, you should be also familiar with socket. If not, please see the site.

Patterns.bmp (287910 bytes)
Figure 1. Two patterns of communication between a server and a client using socket.

Pattern 1
A client sends one request to a server, and stays still and waits (blocking/synchronous) for one returned result from the server. It is really easy for you to understand the communication mechanism.
Pattern 2
It is slightly more complicate. Basically, a client posts n (n=1, 2, 3, .... or more) requests into a buffer of the local client machine and is immediately released (non-blocking/asynchronous) for processing other user requests. Socket stack sends all of requests to a buffer of a remote server at a proper time, and later a server application uses the data inside the buffer to process all of requests by distributing/assigning all of requests into different threads/queues. All of threads/queues processes their assigned requests independently and in parallel. Whenever a request is finished, the returned result is posted into a buffer of the server machine. Once the buffer collects an enough number of binary data or at a specific time frame, the server socket sends the buffer containing multiple returned results using one full packet back to the client. The client is automatically singled when the returned results arrives at the client machine, and retrieves returned results. As you can see with pattern 2, if the network is considered as a water channel, the requests are continuously flowed to a server through one channel, the multiple requests are processed in parallel, and returned results are continuously flowed back to a client through the other channel. Sending and processing could happens concurrently at client and server sides if multiple requests are available.

Pattern 2 has following advantages over pattern 1:

  1. Efficient data movement over network:    

    In average, a client call just sends about a binary data with size of 50 bytes to a server for a request, and gets a returned binary result with size of 50 bytes too. On an Ethernet network, the MTU (Maximum Transmission Unit) for TCP is 1460 bytes. If the pattern 1 is used with your applications, each of round trip can't fully use one data packet. The net efficiency,  which is calculated from the size of transferred binary data divided by MTU, is less than 0.035, and most of packet is empty and wasted. The efficiency is just too low, and far way from 1! As you can see, if your server supports many clients, such a low net work efficiency will kill the whole network system. However, if your applications use pattern 2, the situation could be different. If a client sends multiple requests to a server, Nagle algorithm or your code is able to coalesce all of requests into a big one with one full package (1460), and the server assigns multiples requests into different threads/queues for processing. If all of requests are not lengthy actions, all of returned results can be also sent back to the client with one full package. The client sending, server processing and server sending could be happens at the same time and in parallel if enough requests originates from a client. As you can see, the net efficiency can be a data between 1 and 0.035 with pattern 2. The more requests from a client, the higher the net efficiency with pattern 2.

  2. Client graphic user interfaces never frozen:    

    Unlike in-process and in-machine calls, cross machine calls are much slower. The time of a round trip is 2.5 ms at the best for most of net hardware. Usually, it is around 30 ms per call. If your client has to send 30 calls to a server continuously, your client user interfaces could be frozen and be dead for about one second. If a request is a lengthy action, the server has to spend a long time to process. For example, your server application starts a MTS object, which typically costs you 2 seconds or more. Many more examples can be given with authentication, database accessing, email accessing, and others. As you can see, if you use the pattern 1 for moving data over internet, your client application runs badly. In order to solve this problem, you must design your project very carefully so that the number of round-trips must be minimized. If not, your whole network system runs slow if many client applications are connected to the server application. If your applications use the pattern 1, in many cases you must use threads to do background work and send requests to a server for processing in order to prevent graphic user interfaces from being frozen. It is a common way to do so with all of painful thread problems such as data synchronization, dead lock, and messy in coding logical. If your client applications have too many threads, these problems will certainly hurt you when an application becomes large and complicate. Right? In comparison to the pattern 1, Pattern 2 releases a client application immediately after the client posts a set of requests into a local buffer of the client machine. All of graphic user interfaces functions immediately and correctly because the pattern 2 uses non-blocking mode. There are no stay-still and waiting between a sending and a returning. The client application just picks up an event sent from a client socket if one or a set of returned results arrive in the buffer of the client machine. This feature is actually very important for your client application development. You don't have to use threads now. Actually, there is no necessity at all to use a threads for data communication over network if your application uses the pattern 2. As you can imagine, all of threads problems are avoided. The end result dramatically reduces the complexity of your client codes, data synchronization and dead lock etc.

  3. Coding logic

    Pattern 1 is better in coding logical sometimes, but not always. If your client applications are not windows, pattern 1 will give your better coding logical. However, if your clients are window applications, pattern 2 is more proper to you because pattern 2 is naturally in accordance with window events. 

By default, SocketPro uses the pattern 2 for fast moving data on intranet and internet. It guarantees that data movement over internet or intranet is the most efficient. Additionally, SocketPro also guarantees that your client applications can reduce or completely avoid use of any worker threads in window development environment for exchanging data between a client and a server. Besides, SocketPro enables your applications to have multiple socket instances and connections from a client to a server, and all of instances and connections run independently and in parallel from ONE THREAD ONLY without blocking graphic user interfaces. The focus here is words, multiple, parallel and one thread. At the last, all of client function calls, which lead to data movement over internet, can be switched between blocking and non-blocking modes at your will. This is another particular advantage. It is hard to get this feature from other technologies, MS DCOM/COM+, Java Bean/RMI, and Corba.

It is time to comment on other technologies. Do you know what pattern is used with DCOM/MTS/COM+, Corba and Java Bean/RMI? DCOM/MTS/COM+ definitely uses the pattern 1 to move data over network. It is estimated that all of other technologies use the pattern 1 too. If you have network tools, you could verify it. Our test results show that under all cases SocketPro runs much faster than DCOM. If lots of requests need to be sent to a server, SocketPro could be easily 30 or more times faster than DCOM. All of these technologies highly recommend three-tier distribution systems, and push all (or as many as possible) of logical operations in the middle tier. The essence is to avoid bad data traffic between a client and a server over internet/intranet, and pattern 1 just can't use a network system efficiently. If you push all of logical operations into middle tier, you must deeply understand all of details of your projects. If you are really able to do so, your client applications will lack flexibility and extensibility. Whenever you want to add a feature to a client, you'd better reconsider the design of middle tier components. If your applications follow the pattern 2, the design of your project is less important, and adding more requests doesn't necessarily add extra data trips over expensive network, because pattern 2 coalesces all of requests into one whenever possible by default with non-blocking mode. 

Server side development with SocketPro

Even though your client applications send a set of requests into a server with pattern 2, your client applications may take too long time to get expected results. To get returned results fast, the server application must be carefully designed. Traditionally, the server applications are multithreaded with a thread pool. SocketPro has a multithreaded server component (NetBaseR.dll) running with multiple message queues for fast processing multiple requests in parallel. It is designed according to the following two fundamental points.

  1. How much time a server application needs to process a request from a client.

    No matter what a request is, it is always either slow or fast to be processed. Usually, when you write a server side function, you already know if the request needs a long time to be processed. At an extreme case, you know if the processing is lengthy or quick action at run time only.

  2. What dependency relationships among different requests

    Considering two requests from a client with lengthy actions, the two requests can be processed using two threads/queues if they are totally independent on each other. Here is an example. A client sends two requests to a server for resolving host name and ip address. There are two functions, gethostbyaddr and gethostbyname to be used for processing. You can use two threads/message queues to process them in parallel because there is no dependency between the two function calls. In many cases, one request must be processed after or before the other. For such cases, the two requests must be processed sequentially using one thread only. Here is an example. When you want to access a database, you send two requests to a server with one big stream. The first request is to open a session to the database, the second one is to open a query for records. Both the two requests could be lengthy actions. They must be processed using one thread/queue only, because the second request can be processed only after the first one is successfully processed.

How does SocketPro create and manage threads/queues? What functions and roles do they have? How many threads/queues are created? Basically, SocketPro creates them automatically according to your defined data structures, which describe method ids (requests) and method dependency relationships. Your code doesn't have to create any thread/queue. SocketPro has one main thread/message queue having the following roles:

  1. Main thread/message queue is responsible to listen all of connection requests from different clients, dynamically create and destroy various socket class objects, and close socket connections.
  2. Main thread/message queue is responsible to get all of socket events, and routes these events to different socket class objects, corresponding to different client socket sessions. Main thread/message queue also accepts all of messages from other threads/message queues.
  3. All of requests, which can be quickly processed no matter whether they are from either same or different clients, are processed with the main thread/message queue.
  4. Main thread/message queue creates and kills all of worker threads/message queues, and posts related messages (requests) from the main thread/queue to each of worker threads/message queues for processing.
  5. Main thread/message does decryption and authentication for internet/intranet security.

In regards to worker threads/message queues, they are created for processing one request (one method) or different requests (different methods). All of these requests are lengthy actions. In regards to how many threads/message queues are created, it depends on if a lengthy action request is already called and how your code defines dependency relationships among different lengthy action requests. If no lengthy action requests are called, no thread/message queue is created by the main thread/message. If all of lengthy action requests are dependent on each other, one thread/message queue is created only at most. If some of these lengthy actions are grouped according to dependency, the number of threads/queues are created according to your defined structures at most. Besides, SocketPro has a feature to automatically kill idle threads/message queues for releasing resources and reducing thread context switch. This short article just gives you basic ideas. For details, UDAParts will show you how to code with tutorial samples. However, these basic rules are very important. From the view of clients, all of requests from one socket or different socket connections can be processed in parallel.

Usually, a server application is difficult to be created because of using threads. Data synchronization and dead lock must be considered and carefully planned. SocketPro solves these problems for you. In most cases, you will not have to create any thread/message queue at all. Additionally, SocketPro uses the main thread/message queue to route various messages to different threads/queues, and your code uses these messages to process and return results to clients.

How does SocketPro handle synchronization of socket? A socket has two channels (sending and receiving) as show in the figure 1. Receiving and sending channels can run independently. There must be some ways to synchronize them separately. Otherwise, receiving and sending data could be damaged because of multiple threads or not efficient. SocketPro handles this problem very well. Simply you just can't damage receiving and sending data with SocketPro.

What work do you need to do? Your code just needs to do following kind of jobs.

  1. Define class and method ids, and tell SocketPro what requests are lengthy actions and what requests are quick actions, and set up one (at most cases) or more (at extreme cases) structures.
  2. Code functions to process your requests.

That is all! No more!

In short, SocketPro is able to process multiple requests in batch from a client and send multiple results in batch back to the client for efficient use of network, while the client is sending another batch of requests. In order to speed up processing, all of requests are assigned into different threads/message queues for parallel processing according to SocketPro specific rules. SocketPro provides mechanism to eliminate side effects with threads, such as data synchronization, dead lock and messy coding logical, for reducing the complexity of developing various server side services. In comparison with other technologies, SocketPro doesn't have any intermediate object, which benefits SocketPro somewhat in performance. However, the most important fact is that SocketPro is written on pattern 2 but other technologies on pattern 1. 

Client side development with C/C++, Java, DotNet, VB, Perl and others

Currently, SocketPro is written from winsock 2 using its specific socket functions. By default, a client socket runs in non-blocking mode using pattern2. A window client application can easily create multiple socket connections to a server, and all of these connections run in parallel for obtaining different services from a server without creating one thread. If possible, you should use this feature to speed up your client application. Here is an example. Suppose that your client application needs to process file exchange and also to update data into a backend database through a SocketPro-based server, you could open two socket connections to the middle tier, use one connection for handling accessing file, and the other for updating data with non-blocking mode. If necessary, you could switch socket to blocking mode for simple coding logical. However, it is highly recommended that your window application use non-blocking mode for the best performance as much as possible. It is very simple to use non-blocking/asynchronous mode in window platforms (not Win CE), as shown from samples with SocketPro package. Particularly, SocketPro also lets a client socket configure its server peer socket like enabling/disabling Nagle algorithm, setting socket receiving and sending buffers and setting other socket optional parameters, etc. This feature can further improves your network computation.

Socket is created for moving a stream of binary data across machines with different platforms. Both client and server can run with any platforms, such as Window, UNIX, Macintosh, Linux, and others. Additionally, the development tools can be any language like C/C++, Java, DotNet, VB, Perl and others able to handle binary data. The independence of socket application is excellent in comparison with other technologies.

Conclusions

A socket-based software component, SocketPro, is created for helping software developers quickly and easily create super client and server applications. All of these application will have following HUGE advantages:

  • Fast:

    Your client software components should ALWAYS and absolutely beat all of components written from COM, Corba and Java Bean/RMI in speed. The focus here is the words "ALWAYS" and "speed".

  • Non-blocking (asynchronous):

    Your client software components make it possible that all of client graphic user interfaces could be NEVER, NEVER, ...... blocked and frozen with no need of threads no matter what calls are sent from a client to a server. If you use the common technologies, COM, Corba and Java Bean/RMI, for a real project, you may have to use threads for preventing client graphic user interfaces from being dead because of long time delay of an internet/intranet call. The problems such as data synchronization and mess in coding logical, which naturally come with use of threads, could be avoided if you use SocketPro.

  • Switchable between non-blocking and blocking mode:

    All of client function calls, which lead to data movement over internet, can be switched between blocking and non-blocking modes at your will. This advantage dramatically simplifies the client side development.

  • Multiple sessions to a server:

    Your client applications are able to create multiple sessions to a server. Each of sessions does its own job, runs independently and in parallel, and doesn't block others without help of threads.

  • Cross-platform development:

    Your client applications can communicate with all of socket-based server applications running on all of platforms, Windows, UNIX, Linux, windows, Mac, and others. The server applications don't have to be written from SocketPro.
Other advantages includes:
  • Fast connection to a server,
  • Quick initialization of a class object,
  • Simple installation and security setup,
  • Simple to learn and use, and no complicatedconcepts are involved,
  • Stable if you understand socket and follow its rule.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Yuancai (Charlie) Ye
Web Developer
United States United States
Yuancai (Charlie) Ye, an experienced software engineer, lives in Atlanta, Georgia. He is an expert at OLEDB consumer and created a powerful data accessing libarary at the site http://www.udaparts.com. He has been working at SocketPro written from batching, asynchrony and parallel computation for more than three years. Visual C++, C# and ASP.NET are his favorite development environments.

Comments and Discussions

 
GeneralSocketPro updated with doc and more samples PinmemberYuancai (Charlie) Ye5-Apr-02 5:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140922.1 | Last Updated 24 Feb 2002
Article Copyright 2002 by Yuancai (Charlie) Ye
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid