Java Socket Close Connection After Reading for a Specific Time
8. Customer-server programming with sockets
This lecture presents the customer-server architecture with respect to network applications. We will focus on the communication using sockets and some new Java two facilities similar channels and selectors.
8.1. The client-server architecture
The customer-server architecture is a way of building computer systems. It consists in splitting the system into ii categories of programs: clients and severs.
A client is a programme or a process which connects to some other programme (the server) and lets information technology conduct out a specific task. In particular information technology might require supplying some data from the server.
A server is a plan or a process which provides services for clients. For instance, it might supply some data or a event of processing data to clients.
A communication (between a server and a customer) requires establishing specific rules (a language in which programs talk to each other). These rules are defined by the protocols.
A protocol is a linguistic communication of communication among programs; in particular between a client and a server.
8.two. Sockets
A fundamental notion for exchanging information through the network is a socket.
A socket is one end-point of a two-way communication link between ii programs running on the network
Usually, communication using sockets is based on the TCP or the UDP protocol.
TCP (Transmission Control Protocol) is a connexion-based protocol that provides a reliable menstruum of data betwixt ii computers. It guarantees that the sent data are not lost and arrive in the proper social club to the receiver.
UDP (User Datagram Protocol) is a protocol that sends independent packets of information, called datagrams, from i reckoner to some other with no guarantees most inflow. UDP is not connection-based like TCP. Datagrams may go far to the receiver in an arbitrary order, some of them might be lost.
Identification of hosts in the network is made using IP (Internet Protocol) addresses. An IP address is a 32-flake number (or a 128-chip for IPv6) typically represented using the dot annotation as a sequence of four (or eight) numbers separated with dots (e.g. 192.33.71.12). A human being-friendly identification of hosts involves DNS (Domain Proper name Service) which gives them names like: "edu.pjwstk.edu.pl".
Such an identification is not plenty for inter-process communication, as there may be several processes running on a host. TCP and UDP protocols use ports for delivering data to a receiver. A port is identified by a xvi-fleck number.
In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the result of registering the server with the operating arrangement to receive all data destined for that port. A client can and then talk with the server at the server's port.
The source: Java Tutorial
In datagram-based advice such as UDP, the datagram packet contains the port number of its destination. Thanks to this the packets are routed to the appropriate application.
The source: Java Tutorial
The following lecture focuses on the TCP (connectedness-based) sockets.
A typical interaction between a customer and a server is based on the following model.
- The server binds a socket to a specific port number and starts waiting for clients.
- A client initializes a connection with the service specified by its host proper name and port number.
- The server accepts the connection fabricated by the client and creates a new socket for communicating with it.
- From the point of view of the client information technology is (commonly) the socket which was used to initialize the connection.
So we use two types of sockets in Java:
- server sockets (the class
ServerSocket
) - used by servers, - client sockets (the grade
Socket
) - used by clients; servers employ it too for advice with clients.
8.iii. Clients. Protocols and ports
Programming a client communicating with a server is quite unproblematic in Java. It involves the post-obit steps:
- creating a socket,
- obtaining streams associated with the socket,
- sending requests to the server by means of the output stream,
- receiving server responses from the input stream,
- closing streams,
- closing the socket.
try { � // create a socket � String serverHost = ... ; // server hostname or IP adress � int serverPort = ... ; � � �// server port number � Socket socket = new Socket(serverHost, serverPort) � � // get the streams � OutputStream sockOut = socket.getOutputStream(); � InputStream �sockIn = socket.getInputStream(); � // Communicate: � � // send a request to the server � sockOut.write(...); � � ... � // become the response � sockIn.read(...); � �... � // communication completed // close streams and the socket � sockOut.close(); � sockIn.close(); � socket.shut();� } catch (UnknownHostException exc) { � � // unknown host } take hold of (SocketException exc) { � � // socket-related exceptions } grab (IOException exc) { � � // input-output exceptions }
The key issue related to the client-server advice is the protocol. Each server may employ its ain protocol. Nevertheless, there exist Internet services which utilize the well known, standard protocols. Here are some of them:
- HTTP (Hypertext Transfer Protocol) - used for accessing spider web pages
- FTP (File Transfer Protocol) - used for transferring files
- SMTP (Unproblematic Mail Transfer Protocol) - used for sending mail
- POP3 (Post Office Protocol) - getting mail from a server
- IMAP (Internet Message Access Protocol) - getting mail from a server
- TELNET - admission to remote hosts
- TIME �- get the current time from a host
- DAYTIME - become data and time
- NTP (Network Time Protocol) - for getting the exact time
- NNTP (Network News Transfer Protocol) - newsgroups support
- IRC - Internet Relay Conversation - internet chat
- ECHO - the echo server
- DICT - the lexicon service
All the standard protocols and services are specified in the series of RFC (Request For Comments) documents. They use the well known port numbers for communication. Some of them are reserved (numbers 0-1023) and nosotros cannot use these numbers for our own purposes. The port numbers 1024-49151 are registered (assigned to some well known services). We are allowed to use them, simply information technology is possible that the required port number is already in use on the machine. The ports with numbers 49152-65535 are dynamic (or individual) ones. We may utilize them freely for our purposes.
Standard services are assigned to the standard port numbers by the IANA agency. The mapping may be found here. The table beneath presents some of them.
Port number | Protocol |
---|---|
7 | ECHO |
20 | FTP -- Data |
21 | FTP -- Commands |
22 | SSH Remote Login Protocol |
23 | Telnet |
25 | Simple Postal service Transfer Protocol (SMTP) |
37 | Time |
lxx | Gopher |
80 | HTTP |
110 | POP3 |
119 | Newsgroup (NNTP) |
123 | Network Fourth dimension Protocol (NTP) |
143 | Internet Mail Access Protocol (IMAP) |
194 | Internet Relay Chat (IRC) |
443 | HTTPS (TSL/SSL based HTTP) |
989 | FTPS (based on TSL/SSL) - data |
990 | FTPS (based on TSL/SSL) - commands |
992 | Telnets (TSL/SSL based Telnet) |
993 | IMAPS (TSL/SSL based IMAP4) |
994 | IRCS (TSL/SSL based IRC) |
995 | POP3S (TSL/SSL based POP3) |
2628 | DICT |
Let us take a await at a unproblematic instance of the DAYTIME client. The server sends the electric current appointment and fourth dimension to the client and so closes the connection. The response format is not specified by the RFC, only the server supplies the syntax data.
import java.net.*; import java.io.*; grade DateTime { public static void chief(String[] args) { String host = zero; int port = 13; try { host = args[0]; // hostname // create the socket Socket socket = new Socket(host, port); // Get the socket's input stream and // decorate information technology with a decoder and a buffer BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); // Get the server'south response (appointment and time) String line; while ((line = br.readLine()) != nil) { System.out.println(line); } // Shut streams and the socket br.close(); socket.close(); } catch (UnknownHostException exc) { Arrangement.out.println("Unknown host: " + host); } catch (Exception exc) { exc.printStackTrace(); } } }
Here is a sample output of the program (nosotros pass a hostname as the argument):
java DateTime time.nist.gov 52943 03-ten-31 22:06:50 00 0 0 223.2 UTC(NIST) *
For the explanation of the syntax of the output visit www.time.nist.gov.
eight.4. Addressing and exceptions occurring when connecting to a server
A socket may exist created based on the host proper noun or host IP:
Socket socket = new Socket("time.nist.gov", thirteen); Socket socket = new Socket("192.43.244.18", 13);The higher up constructors non only create the socket but they also connect to the specified server. The server may not be available and when it is - it may reject the asking. Also the time limit for the response may be exceeded. Such situations are signalled by exceptions.
The following program demonstrates it. Nosotros endeavour to connect to various Repeat servers. An Repeat server gets a text from a client and sends it back to him. Such servers were oftentimes used for testing. Nowadays well-nigh of them are blocked for security reasons.
import java.io.*; import java.cyberspace.*; public class EchoClient { final static int ECHO_PORT = seven; private Socket sck; individual PrintWriter out; private BufferedReader in; public EchoClient() {} public void connect(String host) throws UnknownHostException, IOException { sck = new Socket(host, ECHO_PORT); in = new BufferedReader ( new InputStreamReader(sck.getInputStream())); out = new PrintWriter ( new OutputStreamWriter(sck.getOutputStream()), true); Organization.out.println("Connected to the: " + sck.getInetAddress() ); } public void echoMsg(String msg) throws IOException { out.println(msg); String response = in.readLine(); System.out.println("Client: " + msg); Organization.out.println("Server: " + response); } public void disconnect() throws IOException { in.close(); out.close(); sck.close(); } public static void main(Cord[] args) { Cord[] hosts = { "aeneas.mit.edu", "cs.toronto.edu", "cs.utah.edu", "web.mit.edu", "bedrock.ibm.com", "somethin" }; int i = 0; EchoClient ec = new EchoClient(); for (; i<hosts.length; i++) { try { ec.connect(hosts[i]); ec.echoMsg("Howdy!"); ec.disconnect(); } catch(UnknownHostException exc) { System.out.println("Unknown host: " + hosts[i]); } catch(IOException exc) { Organisation.out.println(hosts[i] + " - " + exc); } } } }
The programme prints the following message:
aeneas.mit.edu - coffee.net.ConnectException: Connectedness refused: connect cs.toronto.edu - java.internet.ConnectException: Connexion refused: connect cs.utah.edu - java.net.ConnectException: Connection timed out: connect web.mit.edu - java.net.ConnectException: Connection timed out: connect boulder.ibm.com - java.net.ConnectException: Connection timed out: connect Unknown host: somethin
There is another way of creating sockets and using internet addresses. It involves the classes InetAddress
and InetSocketAddress
. An InetAddress
object represents an IP address. We may obtain information technology by calling the post-obit static methods:
-
InetAddres InetAddress.getByName(host_name)
- returns the IP address of the given host, -
InetAddress[] InetAddress.getAllByName(host_name)
- return an assortment of IP addresses of the given host.
An InetAddress
object may exist passed to the Socket
constructor:
Cord host = "time.nist.gov"; int port = thirteen; try { // create the address InetAddress inetadr = InetAddress.getByName(host); // create the socket Socket socket = new Socket(inetadr, port); .... }
The class InetSocketAddress
represents pairs [IP address, port number]. It is used for deferring connection to the server when creating the socket.
Fist, we create an unconnected socket and appropriate addresses:
��� Socket socket = new Socket(); ��� InetAdress inetadr = InetAddress.getByName(host); ��� InetSocketAddress conadr = new InetSocketAddress(inetadr, port);So, at a called bespeak of time we may connect to the server:
��� socket.connect(conadr);The following programme demonstrates this technique.
public static void main(Cord[] args) { String host = "time.nist.gov"; int port = 13; Socket socket = new Socket(); // create an unconnected socket try { // create addresses InetAddress inetadr = InetAddress.getByName(host); InetSocketAddress conadr = new InetSocketAddress(inetadr, port); // connect to the server socket.connect(conadr); // go the reader provided with the buffer BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); // get the server response Cord line; while ((line = br.readLine()) != null) { System.out.println(line); } // close the stream and the socket br.close(); socket.close(); } catch (UnknownHostException exc) { System.out.println("Unknown host: " + host); } catch (Exception exc) { exc.printStackTrace(); } }
8.five.�Setting timeouts
The second statement to the method connect(..)
is the connection timeout specified in milliseconds. Permit the states write in the previous example:
socket.connect(conadr, 100);In such a example, if the connection is not established within 100 milliseconds then the exception
SocketTimeoutException
will be raised. The following message appears at the command line coffee.net.SocketTimeoutException: connect timed out
Another timeout may occur while reading from a socket. Its value may be set with the socket method setSoTimeout(...)
.
The adjacent sample program demonstrates the fact, that after establishing the connection with the server its responses are too deadening resulting in raising the exception SocketTimeoutException
.
endeavour { // create addresses InetAddress inetadr = InetAddress.getByName(host); InetSocketAddress conadr = new InetSocketAddress(inetadr, port); // connect to the server // specify the conenction timeout socket.connect(conadr, 200); // go the buffered reader BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); // set the read timeout socket.setSoTimeout(50); // read data from the server String line; while ((line = br.readLine()) != null) { Organization.out.println(line); } // cloas the stream and the socket br.shut(); socket.shut(); } grab (UnknownHostException exc) { System.out.println("Unknown host: " + host); } catch (Exception exc) { exc.printStackTrace(); } }
java.net.SocketTimeoutException: Read timed out ��� ��� at java.net.SocketInputStream.socketRead0(Native Method) ��� ��� at coffee.net.SocketInputStream.read(SocketInputStream.java:129) ��� ��� at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:408) ��� ��� at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:450) ��� ��� at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:182) ��� ��� at java.io.InputStreamReader.read(InputStreamReader.coffee:167) ��� ��� at coffee.io.BufferedReader.fill(BufferedReader.java:136) ��� ��� at coffee.io.BufferedReader.readLine(BufferedReader.java:299) ��� ��� at coffee.io.BufferedReader.readLine(BufferedReader.java:362) ��� ��� at DateTime.main(DateTime.java:36)
8.6. Other attributes of sockets
The class Socket
supplies several methods for getting information almost the country of the socket. The following program invokes getters from this form to nowadays a socket's attributes.
import java.net.*; import java.io.*; import java.lang.reverberate.*; class DateTime { public static void master(Cord[] args) { String host = "fourth dimension.nist.gov"; int port = xiii; Socket socket = new Socket(); endeavor { // create addresses InetAddress inetadr = InetAddress.getByName(host); InetSocketAddress conadr = new InetSocketAddress(inetadr, port); // connect to the server // set the connect timeout socket.connect(conadr, 200); // go the buffered reader BufferedReader br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ); // set read timeout socket.setSoTimeout(200); // study socket's state written report(socket); // get server response String line; while ((line = br.readLine()) != null) { System.out.println(line); } // close the stream and the socket br.shut(); socket.close(); } catch (UnknownHostException exc) { System.out.println("Unknown host: " + host); } catch (Exception exc) { exc.printStackTrace(); } } // Dynamically invoke the methods of the class Socket static void report(Socket southward) throws Exception { Method[] methods = (java.net.Socket.class).getMethods(); Object[] args = {}; for (int i=0; i<methods.length; i++) { String name = methods[i].getName(); if ((name.startsWith("become") || name.startsWith("is")) && !name.equals("getChannel") && !proper name.equals("getInputStream") && !name.equals("getOutputStream")) { System.out.println(name + "() = " + methods[i].invoke(s, args)); } } } }
The program prints:
getPort() = 13 isClosed() = fake getInetAddress() = time.nist.gov/192.43.244.eighteen getKeepAlive() = false getLocalAddress() = /61.120.87.131 getLocalPort() = 1178 getLocalSocketAddress() = /61.120.87.131:1178 getOOBInline() = fake getReceiveBufferSize() = 8192 getRemoteSocketAddress() = fourth dimension.nist.gov/192.43.244.xviii:13 getReuseAddress() = false getSendBufferSize() = 8192 getSoLinger() = -1 getSoTimeout() = 200 getTcpNoDelay() = false getTrafficClass() = 0 isBound() = true isConnected() = true isInputShutdown() = false isOutputShutdown() = faux getClass() = class java.internet.Socket 52944 03-xi-01 00:36:14 00 0 0 913.v UTC(NIST) *
8.7. The SMTP client
Let us consider some avant-garde, real life examples. We begin with the SMTP (Simple Mail Transfer Protocol) client.
The client sends requests to the server. The server responds with lines of data. Each line is preceded by the numeric lawmaking which specifies the consequence of processing the asking. The code is followed by a human readable comment.
The client connects to an SMTP server at the port 25. The response code 220 denotes a successful connection. Now the client may introduce himself with the command HELO (or EHLO in ESMTP protocol) The server responds with the code 250 to report success or with fault codes.
The control MAIL sent past the client initializes sending post. It should be followed by the control RCPT for specifying recipients. The server accepts them with the code 250. Now the customer is able to ship the message body using the command DATA. The server's response 354 specifies that information technology is ready to receive the data.
End of information is marked with the line containing a single dot, i.eastward. the sequence: <CR><LF>.<CR><LF>
. The server confirms it with the lawmaking 250. The client now closes the connection with the control QUIT.
The following sample program sends e-mails whose content is read from files. The method doRequest(String,int)
sends a asking to the server. It writes it to the output stream associated with the socket. And then it calls the method readResponse(int)
which gets the server's response.
Both methods display messages at the command prompt to make the dialog between the client and the server visible.
import java.io.*; import java.net.*; public class EmailClient { Socket smtpSocket = null; PrintWriter sockOut = goose egg; InputStream sockIn = zero; public void connect(String server, String myDomain) { endeavour { smtpSocket = new Socket(server, 25); sockOut = new PrintWriter( new OutputStreamWriter(smtpSocket.getOutputStream(), "UTF-8"), truthful); sockIn = smtpSocket.getInputStream(); // Is the connectedness established? // Read the server response and // check whether it is 220. readResponse(220); // Introduce ourselves to the server // If he accepts us he returns 250 doRequest("HELO " + myDomain, 250); } catch (UnknownHostException e) { Organization.err.println("Unknown host: " + server); cleanExit(1); } catch (IOException exc) { System.err.println(exc); cleanExit(2); } } // Sending east-mail public void send(String from, String to, String fname) { try { // Initialize // The lawmaking 250 means OK doRequest("MAIL FROM:<" + from + ">", 250); // Specify the recipient // The code 250 means OK doRequest("RCPT TO:<" + to + ">", 250); // Ship data // The response 354 ways the server is ready for receiving data doRequest("Data", 354); // At present nosotros write the data to the socket's output stream // First the headers: sockOut.println("From: " + from); sockOut.println("To: " + to); // Read the mail service contents from the file // We alter each line consisting of a single dot into double dots // because a single dot specifies the terminate of message BufferedReader br = new BufferedReader( new FileReader(fname)); String line; while ((line = br.readLine()) != zero) { if (line.equals(".")) line += "."; sockOut.println(line); } // The sequence CRLF.CRLF denotes the stop of bulletin // The second CRLF is added in the doRequest by println doRequest("\r\n.", 250); } catch (IOException east) { System.err.println(e); cleanExit(2); } } // Close the connection public void closeConnection() { try { doRequest("QUIT", 221); } take hold of (Exception exc) { System.err.println(exc); } cleanExit(0); } private void doRequest(String req, int checkCode) throws IOException { sockOut.println(req); System.out.println("Customer: " + req); readResponse(checkCode); } // Note: we should not use buffering and the method readLine(), // every bit we exercise not know how many lines the server returns // and the invocation of readLine is a blocking one // Nosotros assume that each response fits into 10000 bytes private void readResponse(int checkCode) throws IOException { byte[] readBytes = new byte[10000]; int num = sockIn.read(readBytes); String resp = new Cord(readBytes, 0, num); Organisation.out.println("Server: " + resp); if (!resp.startsWith(String.valueOf(checkCode))) throw new IOException("Unexpected response from the server"); } private void cleanExit(int code) { attempt { sockIn.close(); sockOut.shut(); smtpSocket.shut(); } grab (Exception exc) {} System.exit(code); } public static void master(String[] args) { String server = "mail.somemailer.cyberspace"; Cord myDomain = "62.125.12.111"; Cord from = "me@somemailer.net"; String to = "you@anywhere"; EmailClient email = new EmailClient(); email.connect(server, myDomain); e-mail.send(from, to, "mail1"); email.ship(from, to, "mail2"); electronic mail.closeConnection(); } }
Here is a sample output of the program.
Server: 220 postal service.somemailer.internet ESMTP Customer: HELO 62.125.12.111 � � � Server: 250 mail3.somemailer.net Client: Mail service FROM:<me@somemailer.cyberspace> Server: 250 Ok Client: RCPT TO:<someone@anywhere> Server: 250 Ok Client: DATA Server: 354 Terminate information with <CR><LF>.<CR><LF> Client: . Server: 250 Ok: queued as 28F372E815A Client: MAIL FROM:<me@somemailer.net> Server: 250 Ok Customer: RCPT TO:<someone@anywhere> Server: 250 Ok Client: Data Server: 354 Terminate data with <CR><LF>.<CR><LF> Customer: . Server: 250 Ok: queued as 8FA212E81EC Client: QUIT Server: 221 Bye
The certificate RFC0821 defines the SMTP protocol. Its extended version - ESMTP - is divers by the RFC1869.
8.eight. Servers
Servers deliver services to clients. Operation of a server consists in:
- creating a
ServerSocket
, - bounden it to an accost,
- waiting for clients,
- when accepting a connection from a customer the server creates another socket for exchanging data with the client.
����� Cord host = ...;� // hostname ����� int port = ...;���� // port number ����� InetSocketAddress isa = new InetSocketAddress(host, port); ����� // create the server socket ����� ServerSocket serverSock =� new ServerSocket(); ����� // bind the socket to the address ����� serverSock.bind(isa); � ����� // In the loop: // listen for clients, take connections and handle requests ����� ����� boolean serverIsRunning = true; � // set up to false by another thread ������������������������������������� � �// when endmost the server ����� while (serverIsRunning) {� ������� // accept the connection ������� // and create the communication socket ������� Socket connexion = serverSock.accept(); ������� // handle customer'southward request ������� // using the streams associated with the socket ������� // ... ������� // when the piece of work is washed - ������� // close the streams and the socket ������� // ... ������� connexion.close() ������� ���� } ���� ���� // shut the server socket ���� serverSock.close();
When creating an InetSocketAddress
, we must specify the host (by its hostname or IP) and the port number. If the server is running on the local car we may pass "localhost" as its hostname or "127.0.0.1" as its accost.
The method bind(...)
binds the server socket to the given address. The method accept(...)
listens for a connection to be made to this socket. It blocks the thread until a connection is made past a customer. It returns a new Socket
for communicating with the customer.
If nosotros desire to implement a service, we must first ascertain the protocol - the language in which clients talk to the server. As an example we present the telephone book server. The server holds the map which assembly persons with their phone numbers.
import java.util.*; import java.io.*; public form PhoneDirectory { private Map pbMap = new HashMap(); public PhoneDirectory(String fileName) { // Initial content of the phone book // is read from the file // storing lines of the form: name phone_number try { BufferedReader br = new BufferedReader( new FileReader(fileName)); String line; while ((line = br.readLine()) != null) { String[] info = line.split(" +", 2); pbMap.put(info[0], info[i]); } } grab (Exception exc) { exc.printStackTrace(); System.get out(1); } } // Returns the phone number of the given person public Cord getPhoneNumber(Cord proper noun) { return (String) pbMap.get(proper noun); } // Adds a new entry to the book // The result: // - true - the entry was added // - false - the entry was non added // (the book associates another number with the given person) public boolean addPhoneNumber(String name, String num) { if (pbMap.containsKey(name)) render fake; pbMap.put(proper name, num); return true; } // Replaces the phone number of the given person // The result: // - true (success) // - false (failure - the given person does non exist) public boolean replacePhoneNumber(String proper name, Cord num) { if (!pbMap.containsKey(proper noun)) return false; pbMap.put(name, num); return true; } }
The server handles clients' requests:
-
get proper name
- give the phone number of the specified person, -
add name number
- add together the entry to the book, -
replace name number
- replace the phone number of the given person with the specified one, -
cheerio
- end of session
The server responds to each request with a line containing a numeric value representing the result of the operation. Additionally, the response to the get
asking is accompanied by another line containing the phone number. We set the following response codes:
-
0
- OK -
i
- invalid asking (a syntax error) -
two
- number not found -
3
- mistake inadd
request: attempt to add an existing person -
4
- mistake insupercede
request: attempt to specify a new number for non-existing person
import coffee.net.*; import java.io.*; import java.util.regex.*; public class PhoneBookServer { private PhoneDirectory pd = null; // the map associating names and numbers individual ServerSocket ss = null; individual BufferedReader in = naught; // socket streams private PrintWriter out = cypher; // for communicating with the client public PhoneBookServer(PhoneDirectory pd, ServerSocket ss) { this.pd = pd; this.ss = ss; System.out.println("Server started"); System.out.println("on port: " + ss.getLocalPort()); System.out.println("bind address: " + ss.getInetAddress()); serviceConnections(); // listen to connections } // The method listens for connections made past clients. // After accepting a connection it creates a new Socket // and calls the method serviceRequest to handle the request private void serviceConnections() { boolean serverRunning = truthful; // the server is running continously while (serverRunning) { try { Socket conn = ss.accept(); // listens and accepts connections Organisation.out.println("Connection established"); serviceRequests(conn); // handle the request } take hold of (Exception exc) { exc.printStackTrace(); } } // close the cosket try { ss.close(); } catch (Exception exc) {} } // the blueprint for parsing requests private static Design reqPatt = Pattern.compile(" +", three); // Server letters. // The respective codes are indices of the assortment. private static String msg[] = { "Ok", "Invalid request", "Not found", "Couldn't add - entry already exists", "Couldn't supercede not-existing entry", }; // Handling client's asking private void serviceRequests(Socket connectedness) throws IOException { try { in = new BufferedReader( // create the streams new InputStreamReader( connection.getInputStream())); out = new PrintWriter( connectedness.getOutputStream(), true); // Parse the request for (String line; (line = in.readLine()) != null; ) { Cord resp; // reply String[] req = reqPatt.split(line, 3); String cmd = req[0]; // control if (cmd.equals("bye")) { // end of message writeResp(0, null); suspension; } else if (cmd.equals("get")) { // get the number if (req.length != 2) writeResp(1, zero); else { String phNum = (String) pd.getPhoneNumber(req[1]); if (phNum == null) writeResp(2, null); else writeResp(0, phNum); } } else if (cmd.equals("add")) { // add a number if (req.length != 3) writeResp(one, null); else { boolean added = pd.addPhoneNumber(req[1], req[2]); if (added) writeResp(0, null); else writeResp(iii, nix); } } else if (cmd.equals("replace")) { // modify the number if (req.length != 3) writeResp(ane, nil); else { boolean replaced = pd.replacePhoneNumber(req[ane], req[2]); if (replaced) writeResp(0, null); else writeResp(4, null); } } else writeResp(1, null); // invalid request } } catch (Exception exc) { exc.printStackTrace(); } finally { attempt { // close the streams in.close(); // and the socket out.close(); connection.shut(); connection = null; } catch (Exception exc) { } } } // Pass the response to the customer private void writeResp(int rc, String addMsg) throws IOException { out.println(rc + " " + msg[rc]); if (addMsg != goose egg) out.println(addMsg); } public static void main(Cord[] args) { PhoneDirectory pd = zilch; ServerSocket ss = cipher; endeavour { String phdFileName = args[0]; String host = args[one]; int port = Integer.parseInt(args[2]); pd = new PhoneDirectory(phdFileName); // create the map (read data from the file) InetSocketAddress isa = new InetSocketAddress(host, port); ss = new ServerSocket(); // create the server socket ss.bind(isa); // and bind it to the accost } grab(Exception exc) { exc.printStackTrace(); Arrangement.go out(ane); } new PhoneBookServer(pd, ss); } }
Below we see a sample client for this service. It performs some tests.
import java.internet.*; import java.io.*; public form PhoneBookClient { private Socket sock = naught; private PrintWriter out = cypher; private BufferedReader in = aught; public PhoneBookClient(String host, int port) { try { sock = new Socket(host, port); out = new PrintWriter(sock.getOutputStream(), true); in = new BufferedReader( new InputStreamReader( sock.getInputStream())); makeRequest("get Kermit"); makeRequest("get Piggy"); makeRequest("add together Gonzo 77777"); makeRequest("add Gonzo"); makeRequest("get Gonzo"); makeRequest("add together Gonzo 333333"); makeRequest("replace Gonzo 333333"); makeRequest("supplant Piggy 202020"); makeRequest("get Gonzo"); makeRequest("add"); makeRequest(""); makeRequest("goodbye"); in.close(); out.close(); sock.close(); } catch (UnknownHostException e) { System.err.println("Unknown host: "+host); System.exit(2); } catch (IOException e) { Arrangement.err.println("I/O error for"); Organisation.exit(3); } catch (Exception exc) { exc.printStackTrace(); System.exit(four); } } individual boolean makeRequest(String req) throws IOException { System.out.println("Asking: " + req); out.println(req); Cord resp = in.readLine(); System.out.println(resp); boolean ok = resp.startsWith("0"); if (req.startsWith("go") && ok) System.out.println(in.readLine()); return ok; } public static void main(String[] args) { new PhoneBookClient(args[0], Integer.parseInt(args[1])); } }
We showtime the server from the control line as follows:
>coffee PhoneBookServer Volume.txt localhost 2300 Server started at port: 2300 bind address: localhost/127.0.0.1
We have chosen the port 2300. All the clients must use this port when connecting to the server. The client is started from the command line too:
>java PhoneBookClient localhost 2300
The client makes a connection to the server. Its method accept()
accepts the connection and the plan displays the message:
Connexion established
Since that moment the interaction of the customer and the server begins. The client sends requests and the server responds appropriately. The client plan displays each step of the interaction.
Request: go Kermit 0 Ok 171717 Request: get Piggy 2 Non establish Request: add Gonzo 77777 0 Ok Request: add Gonzo 1 Invalid request Asking: get Gonzo 0 Ok 77777 Asking: add together Gonzo 333333 3 Couldn't add - entry already exists Request: supplant Gonzo 333333 0 Ok Request: replace Piggy 202020 4 Couldn't supervene upon non-existing entry Asking: get Gonzo 0 Ok 333333 Asking: add together ane Invalid request Request: i Invalid request Request: cheerio 0 Ok
The presented phone server has an of import drawback: information technology is not suited for handling multiple requests at the aforementioned time. Subsequently accepting a connexion from a customer it starts treatment the requests made by that client. Therefore, no other client can admission the server until the previous 1 terminates.
8.9. Multithreaded servers
The standard solution to the above problem is to handle each customer'southward requests in a separate thread. The main thread accepts connections made by clients. Afterward accepting a connection information technology starts another thread for interacting with the customer.
In the modified version of the phone book server the course RequestHandler
(extending Thread
) handles clients' requests. First, permit united states of america have a expect at the main function of the server.
import java.net.*; import java.io.*; public class PhoneBookServerMT2 { private PhoneDirectory pd = null; private ServerSocket ss = cipher; public PhoneBookServerMT2(PhoneDirectory pd,ServerSocket ss) { this.pd = pd; this.ss = ss; System.out.println("Server started"); System.out.println("listening on port: " + ss.getLocalPort()); Organisation.out.println("demark to address: " + ss.getInetAddress()); serviceConnections(); } individual void serviceConnections() { boolean serverRunning = true; while (serverRunning) { try { Socket conn = ss.accept(); System.out.println("Connectedness established"); // first the handler thread new RequestHandler(pd, conn).start(); } take hold of (Exception exc) { exc.printStackTrace(); } } attempt { ss.shut(); } catch (Exception exc) {} } //... }
An here is the handler class RequestHandler
:
import java.net.*; import coffee.io.*; import coffee.util.regex.*; class RequestHandler extends Thread { private PhoneDirectory pd = null; individual Socket connection = null; private BufferedReader in = null; private PrintWriter out = goose egg; private static Pattern reqPatt = Pattern.compile(" +", 3); private static String msg[] = { "Ok", "Invalid asking", "Not constitute", "Couldn't add - entry already exists", "Couldn't replace not-existing entry", }; public RequestHandler(PhoneDirectory pd, Socket connectedness) { this.pd = pd; this.connection = connection; try { in = new BufferedReader( new InputStreamReader( connexion.getInputStream())); out = new PrintWriter( connection.getOutputStream(), true); } take hold of (Exception exc) { exc.printStackTrace(); try { connexion.shut(); } take hold of(Exception e) {} return; } } public void run() { try { for (Cord line; (line = in.readLine()) != null; ) { String resp; String[] req = reqPatt.split(line, 3); String cmd = req[0]; if (cmd.equals("bye")) { writeResp(0, null); break; } else if (cmd.equals("get")) { if (req.length != two) writeResp(1, nix); else { String phNum = (Cord) pd.getPhoneNumber(req[1]); if (phNum == null) writeResp(2, null); else writeResp(0, phNum); } } else if (cmd.equals("add")) { if (req.length != iii) writeResp(1, cypher); else { boolean added = pd.addPhoneNumber(req[1], req[two]); if (added) writeResp(0, null); else writeResp(three, nix); } } else if (cmd.equals("replace")) { if (req.length != 3) writeResp(1, naught); else { boolean replaced = pd.replacePhoneNumber(req[1], req[2]); if (replaced) writeResp(0, nil); else writeResp(4, nix); } } else writeResp(1, null); } } catch (Exception exc) { exc.printStackTrace(); } finally { try { // when closing a socket connectedness.shut(); // the associated streams connexion = null; // are closed automatically } catch (Exception exc) { } } } private void writeResp(int rc, String addMsg) throws IOException { out.println(rc + " " + msg[rc]); if (addMsg != aught) out.println(addMsg); } }
As nosotros encounter, the code for handling requests made by clients is placed in the method run()
. When the customer sends "cheerio" or the socket input stream is closed this method terminates causing the thread to finish.
viii.10. Exercises
Modify the phone book server, so that:
- a person may exist identified past first name or last name,
- a client may call up the postal address of the specified person,
- e-mail address is also stored,
- a client may send an e-mail to the specified person.
pattersonwaris1961.blogspot.com
Source: https://edux.pjwstk.edu.pl/mat/268/lec/lect8/lecture8.html
0 Response to "Java Socket Close Connection After Reading for a Specific Time"
Post a Comment