Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

Use of free SocketPro package for creating super client and server applications

, 23 Feb 2002
A set of socket libraries for writing distributed computing applications over the internet
socketpro.zip
netdemo
ClientComponents
MultiSvsSample
SvrComponents
bin
include
lib
Samples
client
DnsSvs
GetHTML
InternetIO
MultiSvsSample
SpeedTest
res
DResolver
Svr
NormalApp
NTSvs
help
trash
SecureSocket
SafeSocket
DNSResolver.exe
GetHtml.exe
IONet.exe
MultipleSvs.exe
MultiSvs.exe
MultiSvsClient.exe
NetBaseR.dll
SafeSocket.exe
SecureSocket.exe
SpeedTest.exe
ClientSocket.dll
DResolver.dll
SBroker.dll
SockFile.dll
fundamental.gif
patterns.gif
NetBaseR.lib
DNSResolver
DNSResolver.vbp
DNSResolver.vbw
frmDNSResolver.frm
frmDNSResolver.frx
frmChatClient.frm
frmChatClient.frx
GETHTML.vbp
GETHTML.vbw
iIO.frm
IONet
IONet.vbp
IONet.vbw
frmMultiSvs.frm
frmMultiSvs.frx
MultiSvs.vbp
MultiSvs.vbw
SafeSocket.vbp
SafeSocket.vbw
SecureSocket.frm
SpeedTest.ico
SpeedTest.aps
SpeedTest.clw
SpeedTest.dsp
SpeedTest.dsw
dlldata.obj
DNS.rgs
DResolver.aps
DResolver.def
DResolver.dsp
DResolver.dsw
DResolver.opt
DResolver.plg
DResolver.tlb
DResolverps.def
DResolverps.exp
DResolverps.lib
DResolverps.mk
DResolver_i.obj
DResolver_p.obj
MultipleSvs.dsp
MultipleSvs.dsw
MultiSvs.dsp
MultiSvs.dsw
MultiSvs.rgs
MultiSvs.tlb
MultiSvsps.def
MultiSvsps.mk
dlldata.obj
SafeSocket.aps
SafeSocket.dsp
SafeSocket.dsw
SafeSocket.plg
SafeSocket.rgs
SafeSocket.tlb
SafeSocketps.def
SafeSocketps.dll
SafeSocketps.exp
SafeSocketps.lib
SafeSocketps.mk
SafeSocket_i.obj
SafeSocket_p.obj
SPassword.rgs
MultipleSvs.exe
MultiSvs.exe
NetBaseR.dll
SafeSocket.exe
<html>

<head>
<title>Client development guide using SocketPro client components</title>
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
</head>

<body>

<p align="center"><strong><font size="4">Fundamentals about data communication using
socket with </font>SocketPro</strong></p>

<ol>
  <li>Purpose<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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 <a href="mailto:yekerui@yahoo.com">yekerui@yahoo.com</a>.<br>
    &nbsp;&nbsp; </li>
  <li>Two data communication patterns using socket<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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 <a href="http://tangentsoft.net/wskfaq/">site</a>.
    <br>
    <br>
    <img src="fundamental.gif" width="725" height="394" alt="Patterns.bmp (287910 bytes)"><br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Figure 1. Two patterns of communication between
    a server and a client using socket.<br>
    &nbsp;&nbsp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pattern 1:&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pattern 2:&nbsp;&nbsp;&nbsp; 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. <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pattern 2 has following advantages over pattern
    1:<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A.&nbsp;&nbsp;&nbsp; Efficient data movement
    over network:&nbsp;&nbsp;&nbsp; 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,&nbsp; 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</a> 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B.&nbsp;&nbsp;&nbsp; Client graphic user
    interfaces never frozen:&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C.&nbsp;&nbsp;&nbsp; Coding logical:
    &nbsp;&nbsp;&nbsp; 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.&nbsp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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 (For
    example, execute command netstat -s from DOS, and look at output data). 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.&nbsp; <br>
    &nbsp;&nbsp; </li>
  <li>Server side development with SocketPro<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A.&nbsp;&nbsp;&nbsp; How much time a server
    application needs to process a request from a client.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B.&nbsp;&nbsp;&nbsp; What dependency
    relationships among different requests<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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:<br>
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A.&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B.&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C.&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D.&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E.&nbsp;&nbsp;&nbsp; Main thread/message does
    decryption and authentication for internet/intranet security.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; What work do you need to do? Your code just
    needs to do following kind of jobs.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A.&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B.&nbsp;&nbsp;&nbsp; Code functions to process
    your requests.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; That is all! No more!<br>
    <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.&nbsp; <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
  <li>Client side development with C/C++, Java, DotNet, VB, Perl and others<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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. <br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
  <li>Conclusions<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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:<ul>
      <li>Fast:<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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 &quot;ALWAYS&quot; and &quot;speed&quot;. </li>
      <li>Non-blocking (asynchronous):<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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. </li>
      <li>Switchable between non-blocking and blocking mode:<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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. </li>
      <li>Multiple sessions to a server:<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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. </li>
      <li>Cross-platform development:<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 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.
      </li>
      <li>Other advantages includes:<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Fast connection to a server,<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Quick initialization of a class object,<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Simple installation and security setup,<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Simple to learn and use, and no complicated
        concepts are involved.<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Stable if you understand socket and follow its
        rule. </li>
    </ul>
    <p>If you need us to do something for you, give us your message using email <a
    href="yekerui@yahoo.com">yekerui@yahoo.com</a>. Service is available now!</p>
  </li>
</ol>
</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.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