In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "Socket combines thread pool how to achieve client-side and server-side communication demo", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "Socket thread pool how to achieve client-server communication demo" it!
1. Requirements
You can use Socket and ServiceSocket and other API
Write an example of TCP communication between client and server
Server processing tasks need to be handled asynchronously
Because the processing capacity of the server is very weak, only 5 requests can be processed at the same time. When the sixth request arrives at the server, the server needs to return a clear error message: the server is too busy. Please try again later.
The requirement is relatively simple, and the only complication lies in the fourth point. We need to control the number of requests from the client. First of all, we need to confirm that we cannot control the number of requests sent by the client, so we can only modify it from the server, such as limiting the flow from the server.
Some students may quickly think that we should use the backlog property of ServerSocket and set it to 5, but we mentioned in the previous chapter that backlog does not accurately represent the limited number of client connections, and we also require the server to return a specific error message. Even if backlog takes effect, it will only return a fixed error message, not our customized error message.
If we think about it, the thread pool seems to be able to do this. We can set the coreSize and maxSize of the thread pool to 4 and the queue size to 1, so that every time the server receives a request, it will first judge whether there is any data in the queue in the thread pool. If so, it means that the current server is about to process the fifth request. The current request is the sixth request and should be rejected.
Just as the addition of the thread pool can also satisfy the third point, the tasks on the server side can be executed asynchronously.
2. Client code
The code on the client is relatively simple. You can request data directly from the server. The code is as follows:
Public class SocketClient {private static final Integer SIZE = 1024 Private static final ThreadPoolExecutor socketPoll = new ThreadPoolExecutor (50,50,365L, TimeUnit.DAYS New LinkedBlockingQueue (400) @ Test public void test () throws InterruptedException {/ / emulate the client to send 6 messages for (int I = 0; I) to the server at the same time
< 6; i++) { socketPoll.submit(() ->{send ("localhost", 7007, "nihao");} Thread.sleep (1000000000);} / * * send tcp * * @ param domainName domain name * @ param port port * @ param content send content * / public static String send (String domainName, int port, String content) {log.info ("client starts running"); Socket socket = null OutputStream outputStream = null; InputStreamReader isr = null; BufferedReader br = null; InputStream is = null; StringBuffer response = null; try {if (StringUtils.isBlank (domainName)) {return null;} / / No-parameter constructor initializes Socket. The default underlying protocol is TCP socket = new Socket (); socket.setReuseAddress (true) / / the client is ready to connect to the server, setting a timeout of 10 seconds socket.connect (new InetSocketAddress (domainName, port), 10000); log.info ("TCPClient successfully establishes a connection with the server"); / / preparing to send a message to the server outputStream = socket.getOutputStream (); / / setting UTF code to prevent garbled byte [] bytes = content.getBytes (Charset.forName ("UTF-8")) / / output bytecode segmentWrite (bytes, outputStream); / / close output socket.shutdownOutput (); log.info ("TCPClient send content is {}", content); / / wait for the server to return socket.setSoTimeout (50000); / / No data has been obtained for 50 seconds. Directly disconnect / / get the server return stream is = socket.getInputStream () Isr = new InputStreamReader (is); br = new BufferedReader (isr); / / read the return value response = segmentRead (br) from the stream; / / close the input stream socket.shutdownInput (); / / close various streams and sockets close (socket, outputStream, isr, br, is); log.info ("TCPClient receives {}", response) Return response.toString ();} catch (ConnectException e) {log.error ("TCPClient-send socket connection failure", e); throw new RuntimeException ("socket connection failure");} catch (Exception e) {log.error ("TCPClient-send unkown errror", e); throw new RuntimeException ("socket connection failure");} finally {try {close (socket, outputStream, isr, br, is) } catch (Exception e) {/ / do nothing}} / * close various streams * * @ param socket * @ param outputStream * @ param isr * @ param br * @ param is * @ throws IOException * / public static void close (Socket socket, OutputStream outputStream, InputStreamReader isr, BufferedReader br InputStream is) throws IOException {if (null! = socket & &! socket.isClosed ()) {try {socket.shutdownOutput () } catch (Exception e) {} try {socket.shutdownInput ();} catch (Exception e) {} try {socket.close ();} catch (Exception e) {}} if (null! = outputStream) {outputStream.close ();} if (null! = br) {br.close () } if (null! = isr) {isr.close ();} if (null! = is) {is.close ();}} / * segmented reading * * @ param br * @ throws IOException * / public static StringBuffer segmentRead (BufferedReader br) throws IOException {StringBuffer sb = new StringBuffer (); String line While ((line = br.readLine ())! = null) {sb.append (line);} return sb;} / * write * * @ param bytes * @ param outputStream * @ throws IOException * / public static void segmentWrite (byte [] bytes, OutputStream outputStream) throws IOException {int length = bytes.length; int start, end = 0; for (int I = 0; end! = bytes.length) SIZE; end +) {start = I = = 0? 0: I * SIZE; end = length > SIZE? Start + SIZE: bytes.length; length-= SIZE; outputStream.write (bytes, start, end-start); outputStream.flush ();}}
We also use the thread pool in the client code, mainly in order to concurrently simulate the client to send six requests at a time, according to the expectation that the server will return specific error messages to the client when dealing with the sixth request.
The main method of the above code is the send method, which mainly deals with data sent by the server and the response from the server.
3. Server code
The logic of the server is divided into two parts. the first part is to control the number of requests of the client, reject the new request when it exceeds the capacity of the server, and put the new request when the capability of the server can respond. The second part is the execution logic of the server task.
3.1.Control the thread pool of public class SocketServiceStart {/ * server for client request Two functions * 1: let tasks on the server side be executed asynchronously * 2: manage the number of requests on the server side that can be processed at the same time * / private static final ThreadPoolExecutor collectPoll = new ThreadPoolExecutor (4,4,365L TimeUnit.DAYS, new LinkedBlockingQueue (1)) @ Test public void test () {start ();} / * * start the server * / public static final void start () {log.info ("SocketServiceStart server starts to start") When try {/ / backlog serviceSocket handles blocking, the maximum number of connections that can be created by the client exceeds the number of client connections / / when the thread pool capacity is full, we want to block the client connection / / ServerSocket serverSocket = new ServerSocket as far as possible; / / initialize the server ServerSocket serverSocket = new ServerSocket (); serverSocket.setReuseAddress (true) / / serverSocket.bind (new InetSocketAddress (InetAddress.getLocalHost (). GetHostAddress (), 80)); serverSocket.bind (new InetSocketAddress ("localhost", 7007)); log.info ("SocketServiceStart server started successfully") / / spin to keep the client picking up the client's request. If the client has no request for the time being, it will block while (true) {/ / accept the client's request Socket socket = serverSocket.accept () / / if there is data in the queue, the server has reached the limit of concurrent processing. You need to return meaningful information from the client if (collectPoll.getQueue (). Size () > = 1) {log.info ("the SocketServiceStart server has the highest processing capacity and needs to control the client's request"); / / return the processing result to the client rejectRequest (socket) Continue;} try {/ / asynchronously process tasks submitted by the client collectPoll.submit (new SocketService (socket));} catch (Exception e) {socket.close ();} catch (Exception e) {log.error ("SocketServiceStart-start error", e); throw new RuntimeException (e) } catch (Throwable e) {log.error ("SocketServiceStart-start error", e); throw new RuntimeException (e);}} / / returns a specific error code to the client public static void rejectRequest (Socket socket) throws IOException {OutputStream outputStream = null; try {outputStream = socket.getOutputStream () Byte [] bytes = "the server is too busy, please try again later ~" .getBytes (Charset.forName ("UTF-8")); SocketClient.segmentWrite (bytes, outputStream); socket.shutdownOutput ();} finally {/ / close stream SocketClient.close (socket,outputStream,null,null,null);}
We use collectPoll.getQueue (). Size () > = 1 to determine whether the current server has reached the processing limit. If a task is queued in the queue, the current server is overloaded and the new request should be rejected. If there is no data in the queue, the server can accept new requests.
The above code comments are detailed, so it is not cumbersome to say.
3.2. Processing logic of server tasks
The processing logic of the server is relatively simple, the main steps are: read the input from the Socket of the client, process it, and return the response to the client.
We use the thread to sleep for 2 seconds to simulate the server processing logic. The code is as follows:
Public class SocketService implements Runnable {private Socket socket; public SocketService () {} public SocketService (Socket socket) {this.socket = socket;} @ Override public void run () {log.info ("SocketService server task starts execution"); OutputStream outputStream = null; InputStream is = null; InputStreamReader isr = null; BufferedReader br = null; try {/ / accept message socket.setSoTimeout (10000) / / No data has been obtained in 10 seconds. Directly disconnect is = socket.getInputStream (); isr = new InputStreamReader (is, "UTF-8"); br = new BufferedReader (isr); StringBuffer sb = SocketClient.segmentRead (br); socket.shutdownInput (); log.info ("SocketService accept info is {}", sb.toString ()); / / Server processing simulation server processing time Thread.sleep (2000) String response = sb.toString (); / / return the processing result to the client outputStream = socket.getOutputStream (); byte [] bytes = response.getBytes (Charset.forName ("UTF-8")); SocketClient.segmentWrite (bytes, outputStream); socket.shutdownOutput (); / / close stream SocketClient.close (socket,outputStream,isr,br,is); log.info ("SocketService server task execution completed") } catch (IOException e) {log.error ("SocketService IOException", e);} catch (Exception e) {log.error ("SocketService Exception", e);} finally {try {SocketClient.close (socket,outputStream,isr,br,is);} catch (IOException e) {log.error ("SocketService IOException", e);} 4, Test
When testing, we must first start the server, and then start the client. First, we start the server, and print the log as follows:
Then we start the client and print the log as follows:
Finally, let's take a look at the server's running log:
From the above running results, we can see that the results are in line with our expectations. At the request peak, the server can concurrently process 5 requests, and the rest of the requests can be rejected with the correct prompt.
At this point, I believe you have a deeper understanding of "Socket combined with thread pool how to achieve client-server communication demo", might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.