Starting from:
$30

$24

TP5:SocketogrammingPr-TCP Solution

Objectives:




Acquire first-handaboutexperiencehowto develop an application-layer Learn to identify and avoid common pitfalls in network app Learn socket programming in Java: TCP







Prerequisites:




Lectures 3, 4 and 5







How to compile and run a Java program (your IDE might have




javac filename.java




java filename




Basic knowledge of Java programming. If some mechanis,youmays orfi help and examples in:







JavautorTials,in particularI/OutorTtheialandDataInputStreamtutorials.




A Java Socket Programutorialming T







Note: The example codes below are.ouYformustillustrationtakecare ofonlycompilin successful yourself.




Goal




In this TP you will be given a whichsimpleyouJavawillapplication,havetoconvert applicationForthis., weTP will be .using TCP

In this document we will:




First give a brief description of (thattheoriginalrunson Javaone machineapplic







Then, we describe how the application (Clientshould-lookServerin applicitsfi




Finally, we will provide a series whichofstepsyou (milestones)canfollowto reac







Original Application




The following application receives input from the user through




If the user inputs (whichavalidisfilenamelocated in the same foldertheapplicatasthe prints certain useful statistics Then,about the applicaticontentsonf waitsthefilef new filename.




Otherwise, if the user enters an empty filename (ithe.e.applicatio,simply




In particular, the application printsaboutthe followingthecontentsstatsof the file:




The length of the file, in bytes







The number ferentofdif unique words that exist in the document




a list of words and how many times these words appeared in




The following snippet, demonstrates an exampleThefirstruntime,of the appluse "ppap.txt",andthe application prints word-occurrenceInthis case,stats theabout"p in the same folder as theTheJavasecondapplicationtime,the. user inputs nothi terminates.










Enter a file name: ppap.txt




The file has length: 219 bytes

There are 10 unique words in the document




4 apple: 5 have: 4



4 intro: 1



3
pen: 10

pineapple: 5

uh: 3

verse: 3

Enter a file name:

(The program terminates)










Here is the source code for the application, which you will ha







// package ch.epfl.compnet;




import java.util.*;




import java.io.*;




public class WordCounter {




private static FileInputStream getFileReader(String filename) { FileInputStream fis = null;

boolean fileExists = true;




try {




fis = new FileInputStream(filename);




} catch (FileNotFoundException e) { fileExists = false;

}




return fis;




}




private static int getFileLength(String filename) { File file = new File(filename);

int length = (int) file.length();




return length;




}




private static Map<String, Integer getOccurrences(String filename) { Map<String, Integer occurrences = new TreeMap<String, Integer();




String delimiter_regexp = "[^a-zA-Z]+"; FileInputStream fis = getFileReader(filename);




Scanner fileScan = new Scanner(fis).useDelimiter(delimiter_regexp);




String word;




while(fileScan.hasNext()){




word = fileScan.next();




word = word.toLowerCase();

Integer oldCount = occurrences.get(word);




if ( oldCount == null ) {




oldCount = 0;




}




occurrences.put(word, oldCount + 1);




}




fileScan.close();




return occurrences;




}




private static void printMap(Map<String, Integer occurrences) { int num_values = occurrences.size();




System.out.println("There are " + num_values + " unique words in the document \




for (String key: occurrences.keySet()) {




String word = key.toString();




String times = occurrences.get(key).toString();




System.out.println(word + ": " + times);




}




}




private static void printFileStats(String filename) { int length = getFileLength(filename);

Map<String, Integer occurrences = getOccurrences(filename);




System.out.println("The file has length: " + length + " bytes"); printMap(occurrences);

}




public static void main(String args[]) throws Exception {




BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in) boolean repeatFlag;




do {




System.out.print("Enter a file name: ");




String filename = inFromUser.readLine();




if (filename.length() 0) {




printFileStats(filename);




repeatFlag = true;




} else {




repeatFlag = false;




}




} while(repeatFlag == true);




}




}







Client-Server application




For this exercise you will createTCPServer.javatwo andfilesTCPClientnamed.java.




Your goal is to convert the single-host applicationandconvert thatittowas Cg applicationInparticular,. you need tothepartitionoperations of the client and th




Client:




The client is responsible for reading input from the user







Every time the user inputhes aclientnewfilenreadsme,the file contents the server







Then, the client waits until the server returns its respon When the response from the serverthe arrivesclient prints(statistics),theresult Then, the client prompts the user for a new filename to sen Whenever the user entersthean clientempty input,needs to notify the serv completeThen,. the client terminates its.. connection to the se










// package ch.epfl.compnet;




import java.io.*;




import java.net.*;




import java.util.*;




public class TCPClient {




private static FileInputStream getFileReader(String filename) { FileInputStream fis = null;

boolean fileExists = true;




try {




fis = new FileInputStream(filename);




} catch (FileNotFoundException e) {




fileExists = false;




}




return fis;




}




private static int getFileLength(String filename) { File file = new File(filename);

int length = (int) file.length();




return length;




}




private static void printHashMap(Map<String, Integer occurrences) { for (String name: occurrences.keySet()) {

String key = name.toString();




String value = occurrences.get(name).toString();




System.out.println(key + " " + value);




}




}




public static void main(String argv[]) {




//@TODO




}




}




Server:




The server waits for connections from clients at port 6789 When a client theconnects,server waits to receive the file contents Once the server finishes itreceivingprocessestheitsfile,contents and trans client.







Then, without closing the serverconnection,waits for new input from t If, at any themoment,client notifies the server that they havetheno server terminates its connection to the client.




The server never terminates, since it may have to serve ad







package ch.epfl.compnet; import java.util.*;
import java.io.*;







import java.net.*;










public class TCPServer {




private static Map<String, Integer getOccurrences(String message) { Map<String, Integer occurrences = new TreeMap<String, Integer();




String delimiter_regexp = "[^a-zA-Z]+";




Scanner fileScan = new Scanner(message).useDelimiter(delimiter_regexp);




while(fileScan.hasNext()){




String word = fileScan.next();




word = word.toLowerCase();




Integer oldCount = occurrences.get(word);




if ( oldCount == null ) {




oldCount = 0;




}




occurrences.put(word, oldCount + 1);




}




fileScan.close();




return occurrences;




}




public static void main(String args[]) {




//@TODO




}




}




Milestones




Do nottry to implement everythingInstead, atryonceto.structure your applicThis will make it easier for you to test,andyouravoidcodenastymore surprisesthooughlyw becomes more complex later on.




1. ryT to get one file-transfer done right, first.




For this, you assume that the itcliewantsonlyto trhansmitone. fileto the serv




When the client finishes transmitting theOncefile,thetheserverclientfinishewill file,it will print the file contents and also shut down.







//TCPClient.java




private static boolean sendFile(DataOutputStream os, String filename) throws IOExceptio boolean retval;




if (filename.isEmpty()) {




retval = false;




...




} else {




retval = true;




// Send the file itself




FileInputStream fis = getFileReader(filename);




...




}

return retval;







}




//TCPServer.java




private static void handleConnection(Socket connectionSocket) { DataInputStream inFromClient = null;

DataOutputStream outToClient = null;




Open the input-output streams



...




Read the file contents into message byte[] bytearray = ...
...




Call the response handler



send_response(outToClient, message);




}




2. ryT to think of a way to allowtransmitthe multiplecient ,fileseventoiftheit si completelyectcorr.




For this, you can assume thatisneversome allowedcharacterto show up insideThus, tha client can use the "|" character to signal file boundaries.







//TCPClient.java




private static boolean sendFile(DataOutputStream os, String filename) throws IOExceptio boolean retval;




if (filename.isEmpty()) {




retval = false;




...




} else {




retval = true;




Send the file itself



...




Send the special character



...




}




return retval;




}




//TCPServer.java




private static void handleConnection(Socket connectionSocket) { DataInputStream inFromClient = null;

DataOutputStream outToClient = null;




Open the input-output streams



...




Read the file contents into message byte[] bytearray = ...
...




Process the special character



...




// Call the response handler

send_response(outToClient, message);







}




3. ryT to make theespondserverwithr only a part of the(e.guseful.,informat only 5 words)







If you can anticipate how much informati,yonurtoclientexpectwillfromknowthe much to read.










//TCPClient.java




private static void handleResponse(DataInputStream inFromServer) throws IOException { int num_values = 5;




System.out.println("There are " + num_values + " unique words in the document \n");




for (int i = 0; i < num_values; i++) {




Read the length of the word int length = ...



Allocate a big enough buffer for the word byte[] bytearray = new byte[length];



Actually read the word and convert it to a string



...




String word = new String(bytearray);




Read the number of occurrences



int times = ...




System.out.println(word + ": " + times);




}




}




//TCPServer.java




private static void send_response(DataOutputStream outToClient, String message) throw // Perform word-occurrence stats

Map<String, Integer occurrences = ...




int num_values = 5;




for (String key: occurrences.keySet()) {




String word = key.toString();




int times = occurrences.get(key);




Send the length of the word first



...




Then, send the actual word



...




Finally, send the number of times the word appears



...




Break when already sent 5 words



...




}




}







Extend your-clientsrvercommunicationsothatthe server can transmit i words.
The server program needs to abouttransmitall informationwordsencounterednotjustin 5thew




To avoid a "deadlock"you situation,needtothink of a way to make the clien should read.










//TCPClient.java




private static void handleResponse(DataInputStream inFromServer) throws IOException { int num_values = ...;

...




}




//TCPServer.java




private static void send_response(DataOutputStream outToClient, String message) throw




// Perform word-occurrence stats




Map<String, Integer occurrences = ...




Send the number of words int num_values = ...
...




}







5. Find a way to terminate the connection.




Once the client no longer requires anythingbothfromthetheserverserverand(e should be able to termi(andatenotgracefullyjustthe client).







//TCPClient.java




public static void main(String argv[]) {




Socket clientSocket = null;




BufferedReader inFromUser = null;




DataOutputStream outToServer = null;




DataInputStream inFromServer = null;







Boolean repeatFlag;




try {




Connect to the local server at 6789 clientSocket = ...



inFromUser = ...




outToServer = ...




inFromServer = ...




System.out.println("Connected to server");




do {




System.out.print("Enter a file name: ");




String filename = inFromUser.readLine();




sendfile will notify us whether this is the final file or not repeatFlag = sendFile(outToServer, filename);
if (repeatFlag == true) {




If we didn't send a file,



we don't need to wait for a response



handleResponse(inFromServer);




}

} while(repeatFlag == true); } catch (IOException ioex) {




System.out.println("Failed to process request : " + ioex.getMessage());




} finally {




Close all input/output/sockets



...




}




}




//TCPServer.java




private static void handleConnection(Socket connectionSocket) { DataInputStream inFromClient = null;

DataOutputStream outToClient = null;




try {




Open the input-output streams inFromClient = ...
outToClient = ...




This variable controls when the loop should terminate boolean repeatFlag = true;



do {




Read the length of the file int length = ...
System.out.println("The file has length: " + length + " bytes");




if (length == 0) {




Terminate the connection repeatFlag = false;
} else {




Read the file contents into message byte[] bytearray = new byte[length];
...




String message = new String(bytearray); System.out.println(message);




Call the response handler



send_response(outToClient, message);




}




} while (repeatFlag == true); } catch (IOException ioex) {




System.out.println("Failed to handle connection : " + ioex.getMessage());




} finally {




Close all input/output/sockets



...




}




}




6. Make client-server communicationeliantspecialless rcharacters.




Make it so that yournolongerprotocolrelies on special charactersYouto needsig devise proper headers for every file transmitted.







//TCPClient.java




private static boolean sendFile(DataOutputStream os, String filename) throws IOExceptio boolean retval;




if (filename.isEmpty()) {




retval = false;




os.writeInt(0);




} else {

retval = true;







Send the file length int length = ...
System.out.println("The file has length: " + length + " bytes");




...




Send the file itself



...




}




return retval;




}




//TCPServer.java




private static void handleConnection(Socket connectionSocket) { DataInputStream inFromClient = null;

DataOutputStream outToClient = null;




try {




Open the input-output streams inFromClient = ...
outToClient = ...




This variable controls when the loop should terminate boolean repeatFlag = true;



do {




System.out.println("Waiting to receive a file...");




Read the length of the file int length = ...
System.out.println("The file has length: " + length + " bytes");




if (length == 0) {




Terminate the connection



...




} else {




Read the file contents into message byte[] bytearray = new byte[length];
...




Call the response handler



send_response(outToClient, message);




}




} while (...);




} catch (IOException ioex) {




...




} finally {




Close all input/output/sockets



...




}




}




(Optional) 7. The server should disconnespondctclients. that t




Currently your server only allows one client to be active at a




What if a single maliciousconnects clienttoyour server and never does a What if a client only manages to transmit a few bits befor




Your server should be able to free its resourcesTdothis,tobeyouusedneedby to make reads non-blocking.







//TCPServer.java




private static void handleConnection(Socket connectionSocket) { DataInputStream inFromClient = null;

DataOutputStream outToClient = null;




try {




// Set reads to timeout after 50 seconds (50000 milliseconds)




...




Open the input-output streams inFromClient = ...
outToClient = ...




...




} catch (IOException ioex) {




...




} finally {




Close all input/output/sockets



...




}




}




(Optional/Advanced)8.Make your server able to serve multiple cl




If you have implemented everything,your servercorrectlywillsoonlyfar be able up timeNew. clients will haveandtowaitqueueforupthe currently-active clien

If you feel comfortable with threads, you can try.Eachimplementingthreadwi a separate client connection.







//MultiThreadServer.java




import java.util.*;




import java.io.*;




import java.net.*;







public class MultiThreadServer {




public static void main(String args[]) {




ServerSocket welcomeSocket = null;




Socket connectionSocket = null;




try {




Create a socket that listens to port 6789 welcomeSocket = ...



while(true) {




try {




Get a new connection connectionSocket = ...



Start a new thread for the accepted connection



...




} catch (IOException ioex) {}




}




} catch (IOException ioex) {




System.out.println("Failed to open welcomeSocket : " + ioex.getMessage());




} finally {




Close inputs/outputs/sockets



...




}

}




}




class RequestHandler implements Runnable {




Socket socket;




public RequestHandler(Socket socket) {




this.socket = socket;




}




...




public void run() {




...




}




}




Hints




1. eatingCr socketeams. str




In Java, to write and read youdataneedto/frtomfirstasocket,obtain references streamsof theSocket object of the Youconnectionwilluse. the input stream to re and the output stream to send data to other host.




You can read more about the availableJava streaI/OutorialT.Twomoptionspairs atof theclass find of particular use for this project are the following:

BufferedReader/BufferedWriter (for text data)







DataInputStream/DataOutputStream (for binary data)







2. Blocking operations




If your client/server tries to readthe htosto muchwill frompermanentlysocket,bloc transmits enough information.




To avoid unnecessaryextremelyrouble,imporitanthais you plan out you protocol, in adv Try to create a sequence diagramwhateachabouthostexactlyexpects from the oth connection.




Most importantly, you need to makethe suretwo endsthat of the willcommunevericationget s for each other at the sameNeedlesspoint,tothisinsaytimewould. lead in a "deadloc

Note that for your application you need to account for 3 commu




The server







The client




The user that inputs filenames on the client console







3. Figuring out the right format for your messages.




This is very strongly related to what has already been stated




When sending messages, theusingboundariesTCP of theseSincemessagescommunicatiogetlos way thing,you need to make sure that your messages do not get mis

That is ,toifsayyou use a TCP socket to transmitastwo"Hello"seprateandthme"Gssaoot may interpret this as one single mesThisage:is because"HelloGoodbye"alldata. tran gets "serialized"intosingle byte-stream.

Thus, you need to constructin ayourway messagessuchthat you can deserializ original messagesForinstance,. if you know that the character you"|" can transmit "Hello|Goodbye"tomakethe remote end understandferentthat messagesInthosethiar case, the role of "|" .is that of a delimiter




If there is no character that can act youas aneeddelimitertothinkforaboutyour construct headers forThen,your themessagesheaders. can be used by the ot messages.

More products