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 email@example.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.
Figure 1. Two patterns of communication between a server and a client using
- 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
- 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
- Efficient data movement
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, <a
href="http://tangentsoft.net/wskfaq/intermediate.html#nagle-desc">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.
- 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.
- 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.
- 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.
- 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
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:
- 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.
- 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.
- 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.
- 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
- 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.
- 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.
- Code functions to process
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.
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:
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
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