import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.HashSet; public class Client extends Thread { public static void main(String[] args) throws IOException, InterruptedException { int listenPort = 9009; String group = "public"; if(args.length>=1) //can change group with first command line argument group=args[0]; if(args.length==2) //can change port with second command line argument listenPort=Integer.parseInt(args[1]); String server = "garyc.me:9009"; ServerSocket ss= new ServerSocket(listenPort); ss.setSoTimeout(10000); //only wait this many milliseconds for incoming connection System.out.println("Listening on port "+listenPort+". Please forward this port if necessary.\nNew files will show up in the 'incoming' directory"); File incoming = new File("incoming"); incoming.mkdir(); //create incoming dir File temp = new File("temp"); temp.mkdir(); //create temp dir File outgoing = new File("outgoing"); //create outgoing dir outgoing.mkdir(); System.out.println("Place files in the 'outgoing' directory to send"); Socket serverSocket = new Socket(server.split(":")[0],Integer.parseInt(server.split(":")[1])); OutputStream serverOutputStream = serverSocket.getOutputStream(); InputStream serverInputStream = serverSocket.getInputStream(); serverOutputStream.write(("version:1;port:"+listenPort+";group:"+group+";").getBytes()); String stats=""; boolean idle = true; while (true){ while(serverInputStream.available()>0){ String[] serverData = readData(serverInputStream); if(serverData[0].equals("stats")){ if(!stats.equals(serverData[1])){ stats=serverData[1]; String[] parts = stats.split(","); System.out.println("Currenly "+parts[1]+" users online in the '"+group+"' group ("+parts[0]+" globally)"); } } } ///////////////////// Sender Part ///////////////////////// File[] list = outgoing.listFiles(); //search outgoing directory for any files if(list.length>0){ //found file to send idle = false; serverOutputStream.write("status:busy;".getBytes()); //inform server we are busy serverOutputStream.flush(); File file=list[0]; //get the first file in the list HashSet sentTo = new HashSet(); //list hosts we sent this file to already int sentCount = 0; //number of times file was successfully sent if(file.isDirectory()) //trying to send directory System.out.println("\""+file.getName()+"\" is a directory. Skipping."); else //is actually a file while(true){ //stop when we run out of hosts to send to while(serverInputStream.available()>0) //drain server connection serverInputStream.read(); serverOutputStream.write(("get:readyList;").getBytes()); String[] serverData = readData(serverInputStream); String host=null; if(serverData[0].equals("readyList") && serverData.length==2){ //server sent readyList String[] hosts = serverData[1].split(","); for(int i=0;i0){ //if we sent this file to at least one host System.out.println("Sent file "+file.getName()+" to "+sentCount+" clients"); break; //go on to next file } //didnt send file break; //try again later } sentTo.add(host); System.out.print("Sending file "+file.getName()+" to "+host.split("-")[0]+"..."); Socket s; boolean error=false; try{ s = new Socket(host.split("-")[0],Integer.parseInt(host.split("-")[1])); s.setSoTimeout(5000); sendFile(file , s.getOutputStream()); s.close(); }catch(Exception e){ System.out.println("Connection error or duplicate file"); error=true; } if(!error){ System.out.println("Success!"); sentCount++; } } if(sentTo.size()>0){ //if we actually attempted to send file File sent=new File("sent"); sent.mkdir(); File dest = new File(sent, file.getName()); if(dest.exists()) //overwrite exitsing file dest.delete(); dest = new File(sent, file.getName()); file.renameTo(dest); }else{ //everyone is busy sleep((int)(Math.random()*5000)); //wait a random amount of time } }else if (!idle){ System.out.println ("Done."); System.out.println("Place files in the \"outgoing\" directory to send"); idle=true; serverOutputStream.write(("get:stats;").getBytes()); } ///////////////////// Receiver Part ///////////////////////// serverOutputStream.write("status:ready;get:stats;".getBytes()); //inform server we are ready and want user stats serverOutputStream.flush(); Socket s; try{ s = ss.accept(); //this blocks while waiting for incoming connection }catch(java.net.SocketTimeoutException e){ //timeout continue; } serverOutputStream.write("status:busy;".getBytes()); //inform server we are busy serverOutputStream.flush(); BufferedInputStream in = new BufferedInputStream(s.getInputStream()); //input from sender should look like: //file:[file name]:[file size];[raw data] String[] input = readData(in); if(input[0].equals("file")){ String filename=input[1]; //read filename from stream filename=filename.replace('/', '_'); //replace potentially dangerous characters filename=filename.replace('\\', '_'); int size=Integer.parseInt(input[2]); File dest = new File (incoming, filename); System.out.print("Receiving file "+filename+" ("+size/1024+" KB) from "+s.getInetAddress().getHostAddress()+"..."); if(dest.exists()){ //overwrite exitsing file System.out.println("already have file!"); in.close(); s.close(); continue; } File file = new File (temp, filename); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); for(int i=0;ibigbuff.length){ in.read(bigbuff); out.write(bigbuff); wrote += bigbuff.length; } if (file.length() - wrote >buff.length){ in.read(buff); out.write(buff); wrote += buff.length; } out.write(in.read()); wrote++; } } catch (IOException e) { in.close(); out.write('0'); } in.close(); out.flush(); out.close(); } //read a colon-separated "command" from input stream public static String[] readData(InputStream in) throws IOException{ String out=""; char c = ' '; while(true){ //forever c = (char)in.read(); //read a character from input stream if(c==';') //stop when semicolon found break; out += c; } return out.split(":"); } }