190 likes | 210 Views
Learn how to create a server and handle multiple client connections using non-blocking I/O. Follow step-by-step instructions for setting up sockets, handling client requests, and establishing communication. Implement server protocols and connection handling for efficient client-server interactions.
E N D
System Programming Practical session 11 • Multiple clients server • Non-Blocking I/O
Server steps for single client (reminder) • Creating a ServerSocket. • int listenPort = 4444; • ServerSocket serverSocket=newServerSocket(listenPort); • Waiting for a client. • Socket clientSocket=serverSocket.accept(); • Once connection is established, creating input and output streams. • BufferedReader in=newBufferedReader( • newInputStreamReader(clientSocket.getInputStream(),"UTF-8")); • OutputStreamWriterout=newOutputStreamWriter( • clientSocket.getOutputStream(),"UTF-8"); • Communicating. • Closing connection.
Server steps for handling multiple clients • Creating a ServerSocket. • Waiting for a client. • Once connection is established: • Creating input and output streams. • Communicating. While(true){ } Create a new thread that performs: ConnectionHandler
Server classes – EchoServer example • EchoProtocol • - Defines how to respond to each received message • ConnectionHandler (Implements Runnable) • - Handle single connection • MultipleClientProtocolServer • Handle all connections, using ConnectionHandler thread per connection.
interfaceServerProtocol{ • StringprocessMessage(Stringmsg); • booleanisEnd(Stringmsg); • } • classEchoProtocolimplementsServerProtocol{ • privateintcounter; • publicEchoProtocol(){ • counter=0; • } • publicStringprocessMessage(Stringmsg){ • counter++; • if(isEnd(msg)){ • returnnewString("Ok,byebye..."); • }else{ • returnnewString(counter+".Received\""+msg); } • } • publicbooleanisEnd(Stringmsg){ • returnmsg.equals("bye"); • } • }
classConnectionHandlerimplementsRunnable{ • privateBufferedReaderin; • privatePrintWriterout; • SocketclientSocket; • ServerProtocolprotocol; • publicConnectionHandler(SocketacceptedSocket,ServerProtocolp){ • in=null; • out=null; • clientSocket=acceptedSocket; • protocol=p; • System.out.println("Acceptedconnectionfromclient"); • System.out.println("Theclientisfrom:"+ • acceptedSocket.getInetAddress()+":"+ • acceptedSocket.getPort()); • 14. } • // continued on next slide
publicvoidrun(){ • Stringmsg; • try{ • this.initialize(); • }catch(IOExceptione){ • System.out.println("ErrorininitializingI/O"); • } • try{ • this.process(); • }catch(IOExceptione){ • System.out.println("ErrorinI/O"); • } • System.out.println("Connectionclosed-byebye..."); • this.close(); • } • // continued on next slide
//Startslistening • publicvoidinitialize()throwsIOException{ • //InitializeI/O • in=newBufferedReader(newInputStreamReader( • clientSocket.getInputStream())); • out=newPrintWriter( • clientSocket.getOutputStream(),true); • System.out.println("I/Oinitialized"); • } • // continued on next slide
publicvoidprocess()throwsIOException{ • Stringmsg; • while((msg=in.readLine())!=null){ • System.out.println("Received\""+msg+ • "\"fromclient"); • Stringresponse=protocol.processMessage(msg); • if(response!=null){ • out.println(response); • } • if(protocol.isEnd(msg)){ • break; • } • } • } • // continued on next slide
//Closestheconnection • publicvoidclose(){ • try{ • if(in!=null){ • in.close(); • } • if(out!=null){ • out.close(); • } • clientSocket.close(); • }catch(IOExceptione){ • System.out.println("ExceptioninclosingI/O"); • } • } • } • // end of ConnectionHandler
classMultipleClientProtocolServerimplementsRunnable{ • ServerSocketserverSocket; • intlistenPort; • publicMultipleClientProtocolServer( • intport,ServerProtocolp){ • serverSocket=null; • listenPort=port; • } • \\ continued on next slide
publicvoidrun(){ • try{ • serverSocket=newServerSocket(listenPort); • System.out.println("Listening..."); • }catch(IOExceptione){ • System.out.println("Cannotlistenon"+listenPort); • } • while(true){ • try{ • ConnectionHandlernewConnection=newConnectionHandler( • serverSocket.accept(),newEchoProtocol()); • newThread(newConnection).start(); • }catch(IOExceptione){ • System.out.println("Failed toaccepton“+listenPort); • } • } • } \\ continued on next slide
publicstaticvoidmain(String[]args)throwsIOException{ • intport=Integer.decode(args[0]).intValue(); • MultipleClientProtocolServerserver=new MultipleClientProtocolServer(port,newEchoProtocol()); • ThreadserverThread=newThread(server); • serverThread.start(); • try{ • serverThread.join(); • }catch(InterruptedExceptione){ • System.out.println("Serverstopped"); • } • } • } \\ end of MultipleClientProtocolServer
Non-Blocking I\O How a single thread can read from several channels? ConnectionHandler Channel 1 Buffer 1 Buffer 2 Channel 2
Channels Channels wrap sockets, and allow non-blocking I/O. read(), write() , accept() can be non blocking. Setting up a non-blocking ServerSocketChannel listening on a specific port. int port = 9999; ServerSocketChannel ssChannel = serverSocketChannel.open(); ssChannel.configureBlocking(false); ssChannel.socket().bind(new InetSocketAddress(port));
Buffers ByteBuffer are buffers that hold bytes. Channels know how to read and write to buffers. Creating a Buffer final int NUM_OF_BYTES = 1024; ByteBuffer buf = ByteBuffer.allocate(NUM_OF_BYTES); From Channel to Buffer and back numBytesRead = _socketChannel.read(buf1); numBytesWritten = _socketChannel.write(buf2); • Return –1 if channel is closed. • Update position marker of the buffer.
Buffer Position Marker Initial state: buffer position After read of “something” s o m e t h i n g buffer position Buffer.flip(); s o m e t h i n g buffer position
Message Tokenizer Accumulates characters in a buffer. Allows returning next complete message – A message terminating with a certain string (e.g., “\n”.) • Methods: • publicsynchronizedvoidaddBytes(ByteBufferbytes); • publicsynchronizedbooleanhasMessage(); • publicsynchronizedStringnextMessage()