A good simple example of multi-threaded socket server

Source: Internet
Author: User

I have no intention of seeing a multi-threaded socket server example on the Internet. I think it is very good. In particular, the thread pool is simple and efficient. Although jdk1.5 has already brought its own thread pool package, this code is a good example for learning socket and multithreading.

The following code is a simple arrangement of the example and adds comments.

[Code 1] pooledconnectionhandler: background processing class

Package server;

Import java. Io. bufferedreader;
Import java. Io. filenotfoundexception;
Import java. Io. filereader;
Import java. Io. ioexception;
Import java. Io. inputstreamreader;
Import java. Io. printwriter;
Import java.net. Socket;
Import java. util. Collections list;
Import java. util. List;

/**
* <PRE>
* Pooledconnectionhandler implements the runnable interface, which is used to process socket connections from the server.
. This class maintains a global Chained List (static) called "connection pool", which is created when the class is loaded.
*
* When the run () method of this class is called, it first checks whether there is a client connection to be processed in the "connection pool". If
* If no (probably because the request has not arrived), the wait () method is called to wait, while the other static method processrequest is negative.
* It is responsible for receiving client requests and adding them to the end of the "connection pool", and notifying all waiting threads.
* Competing resources (requests) in the form of "mutex". When a thread first obtains the object lock and obtains a connection, the lock is released.
* Then process the request in your own thread. Each thread does not affect each other.
*
* Note that one method of this class: the first method of processrequest is a static method, because
* The method is only a notification role, so it does not need to be at the object level. Set its modifier to static as a combination
.
*
* When operating the global resource "connection pool", whether it is adding a request to the pool or retrieving a request from the pool,
* Synchronized {} must be added to key statement blocks to prevent multiple threads from competing with the same statement block at the same time.
* Resource, or another thread tries to read the resource before the resource is added.
*
* The last note is the wait () and policyall () methods. The call of the wait () method is sent to the thread for creation.
* Completed, but before the request arrives, the thread does not hold a lock on the list, and the yyall () method invokes all waits.
* Threads, all waiting threads will compete for locks. At this time, only one thread may detect that the pool is not empty and enter the pool to request resources.
* Source.
* </PRE>
*/
Public class pooledconnectionhandler
Implements runnable {

/** The Client Connection of socket.
*/
Protected socket connection;

/** The request pool.
*/
Protected static list pool =
New partition list ();

/**
* Instantiates a new pooled connection handler.
*/
Public pooledconnectionhandler (){
}

/*
* (Non-javadoc)
*
* @ See java. Lang. runnable # Run ()
*/
Public void run (){
While (true ){
// Because multiple threads may simultaneously fetch sockets from the pool for processing.
// So we need to synchronize to prevent the same request from being processed multiple times.
Synchronized (pool ){
While (pool. isempty ()){
Try {
Pool. Wait (); // wait if no request arrives
} Catch (interruptedexception e ){
E. printstacktrace ();
}
}
// Fetch a socket from the pool and prepare for processing
Connection = (socket) pool. Remove (0 );
}
// After the socket is obtained, no synchronization is required because connection is the object.
// Level attributes, which are processed internally by the thread and do not involve access to public resources
Handleconnection ();
}
}

/**
* Process request, append socket to pool and every y all waitting thread
*
* @ Param requesttohandle the request to handle
*/
Public static
Void processrequest (socket requesttohandle ){
// Another thread may be added to the pool when a request is sent.
// The socket is being obtained from the pool, so synchronization is required here.
Synchronized (pool ){
// Add requests from the client to the end of the Request queue
Pool. Add (pool. Size (), requesttohandle );
// Notify other waiting threads of new requests,
// At this time, all threads in the wait status will be awakened
Pool. policyall ();
}
}

/**
* Handle connection.
*/
Public void handleconnection (){
Try {
Printwriter streamwriter = new printwriter (connection
. Getoutputstream ());
Bufferedreader streamreader = new bufferedreader (
New inputstreamreader (connection. getinputstream ()));

String filetoread = streamreader. Readline ();
Bufferedreader filereader = new bufferedreader (New filereader (
Filetoread ));

String line = NULL;
While (line = filereader. Readline ())! =
Null)
Streamwriter. println (line );

Filereader. Close ();
Streamwriter. Close ();
Streamreader. Close ();
} Catch (filenotfoundexception e ){
System. Out. println ("");
} Catch (ioexception e ){
System. Out. println ("" + E );
}
}
}

[Code 2] pooledremotefileserver: a multi-threaded server that creates a thread pool and waits for client connection requests.

Package server;

Import java. Io. ioexception;
Import java.net. bindexception;
Import java.net. serversocket;
Import java.net. Socket;

/**
* <PRE>
* Pooledremotefileserver is a multi-threaded, pooled socket server. It can be deployed on the specified port
* Listens to connection requests from clients and limits the number of connections allowed at the same time.
*
* On the server side, when the server is started, a specified number of backend processing instances are created. These instances actually implement
* Runnable interfaces are called immediately after they are created. They constantly monitor connections from clients.
*
* After a thread is created, the server listens to the specified port. Once a client is connected
* The connection is handed over to the backend waiting thread for processing, and then immediately returns to continue listening on the port. In this case, the background thread
.
* </PRE>
*/
Public class pooledremotefileserver {

/** The max connections.
*/
Protected int maxconnections;

/** The listen port.
*/
Protected int listenport;

/** The server socket.
*/
Protected serversocket;

/**
* Instantiates a new pooled remote file server.
*
* @ Param alistenport the listen Port
* @ Param maxconnections the max connections
*/
Public pooledremotefileserver (INT alistenport,
Int maxconnections ){
Listenport = alistenport; // listener Port
This. maxconnections = maxconnections; // maximum number of simultaneous connections
}

/**
* Initialization pool: Creates a runnable instance each time and then creates a thread object.
*/
Public void setuphandlers (){
For (INT I = 0; I <maxconnections; I ++ ){
Pooledconnectionhandler currenthandler = new pooledconnectionhandler ();
// After the thread starts, it will always monitor the socket queue in polling mode.
// Monitor whether new client requests have arrived.
// Origin. If not, wait until the request arrives.
New thread (currenthandler, "handler" + I). Start ();
}
}

/**
* Receive client connection
*/
Public void acceptconnections (){
Try {
Serversocket Server = new serversocket (listenport, 5 );
Socket incomingconnection = NULL;
While (true ){
Incomingconnection = server. Accept ();
Handleconnection (incomingconnection );
}
} Catch (bindexception be ){
System. Out. println ("");
} Catch (ioexception IOE ){
System. Out. println ("" + listenport );
}
}

/**
* Process socket requests in the pool
*
* @ Param connectiontohandle the connection to handle
*/
Protected void handleconnection (socket connectiontohandle ){
Pooledconnectionhandler. processrequest (connectiontohandle );
}

Public static
Void main (string ARGs []) {
Pooledremotefileserver Server = new pooledremotefileserver (1001, 3 );
// Initialize the thread pool
Server. setuphandlers ();
// Start the request waiting for arrival on the specified port
Server. acceptconnections ();
}
}

The essence of this example is in the pooledconnectionhandler class. It first creates a public global "thread pool" (linklist) and then starts the thread monitoring thread pool, at the same time, after receiving the client request, the server adds the request to the "Thread Pool". These two actions are asynchronous and cannot be read during addition, during reading, addition is not allowed (controlled by the synchronized keyword), and multiple threads do not affect each other, because the connection attribute is object-level.

In this example, we can also learn which variables must be set as global (static) and which must be set as object-level in the case of multithreading: that is, resources accessed by multiple threads must be set to global, and attributes related to the thread processing status and results must be set to object-level to prevent mutual interference.

Second, in the case of multithreading, which methods can be set to static without thread security issues, and which methods cannot be set to static methods: if the methods belong to the control flow, notifications, distributed, can generally be set to static. Because these methods generally do not require multiple, one is enough. Just as if only one controller is enough. The business logic implementation method cannot be set to static, because the static method cannot reference object variables (non-static variables ), however, the business logic usually requires different processing for different users, so it is almost certain that object variables will definitely appear.

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.