Datagram Packet FTP application - java

I write a FTP application using UDP Datagram Protocol , and I need the client side read from file 100 character and send it in 5 parts , 20 characters in each part , when I run my program I get this error :
Exception in thread "main" java.lang.IllegalArgumentException: illegal length or offset. I want the server get each line in five parts but sort it accordingly.
this is my code :
import java.net.*;
import java.io.*;
public class FTPClient
{
public static void main(String[] args)
{
final int SIZE=100;
DatagramSocket skt= null;
DatagramPacket pkt = null;
BufferedReader read= null;
int port = 3131;
try
{
skt=new DatagramSocket(2121);
read= new BufferedReader(new FileReader("input.txt"));
String line = read.readLine();
byte[] lineByte = new byte[SIZE];
lineByte = line.getBytes();
InetAddress add = InetAddress.getByName("localhost");
for(int i=0;i<100;i+=20)
{
pkt = new DatagramPacket(lineByte,i,20,add,port);
skt.send(pkt);
}
}
catch(IOException e)
{
System.out.println(e.getMessage()); }
finally
{
skt.close();
// read.close();
}
}
}

Your code with comments at problem areas. If you still have problems resolving the issues after reading my comments, just add a comment and I will explain more
public static void main(String[] args) {
final int SIZE = 100;
DatagramSocket skt = null;
DatagramPacket pkt = null;
BufferedReader read = null;
int port = 3131;
try {
skt = new DatagramSocket(2121);
read = new BufferedReader(new FileReader("input.txt"));
String line = read.readLine(); // how long is the line?
byte[] lineByte = new byte[SIZE]; // this is a redundant assignment
lineByte = line.getBytes(); // now the length of the lineBytes is "unknown"
InetAddress add = InetAddress.getByName("localhost");
for (int i = 0; i < 100; i += 20) { // you should check the length of lineBytes instead of 100
pkt = new DatagramPacket(lineByte, i, 20, add, port);
skt.send(pkt);
}
}
catch (IOException e) {
System.out.println(e.getMessage());
}
finally {
skt.close();
// read.close();
}
}

Related

Why is my TCP system faster than UDP one?

I have two (client - server - client) system. First one uses TCP and second one uses UDP. It is interesting that my TCP using system is faster than UDP using one when transferring files in size 5-6 mb. Does problem occurs because of my coding mistakes or can that happen?
TCP Client
try {
socket = new Socket("localhost", 7755);
} catch (Exception e) {
System.out.println(e.getMessage().toString());
}
out = new PrintWriter(socket.getOutputStream(), true);
int i = 0;
while (file.hasNext()) {
String line = file.nextLine();
if (!line.isEmpty()) {
out.println(line);
}
i++;
}
TCP Server
try {
serverSocketA = new ServerSocket(7755);
serverSocketB = new ServerSocket(7760);
} catch (Exception e) {
System.out.println("Port error!");
}
System.out.println("Server is ready...");
clientSocketA = serverSocketA.accept();
clientSocketB = serverSocketB.accept();
PrintWriter out = new PrintWriter(clientSocketB.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocketA.getInputStream()));
while((dataFromClientA = in.readLine()) != null) {
out.println(dataFromClientA);
}
UDP Server
private static byte[] buf = new byte[6];
static Scanner file;
public static void main(String[] args) throws IOException{
long startTime = System.currentTimeMillis();
socket = new DatagramSocket();
address = InetAddress.getByName("localhost");
file = new Scanner(new File("sentfile.txt"));
DatagramPacket packet;
while (file.hasNext()) {
String line = file.nextLine();
if (!line.isEmpty()) {
buf = line.getBytes();
packet = new DatagramPacket(buf, buf.length, address, 7765);
socket.send(packet);
}
}
UDP Client
private static byte[] buffer = new byte[6];
private static byte[] buffer2 = new byte[6];
private static boolean running;
static PrintWriter writer;
public static void main(String[] args) throws IOException {
udpSocketB = new DatagramSocket();
address = InetAddress.getByName("localhost");
udpSocketA = new DatagramSocket(7765);
running = true;
DatagramPacket packet;
while(running) {
packet = new DatagramPacket(buffer, buffer.length);
udpSocketA.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buffer, buffer.length, address, port);
String received = new String(packet.getData(), 0, packet.getLength());
DatagramPacket packetToB;
buffer2 = received.getBytes();
packetToB = new DatagramPacket(buffer2, buffer2.length, address, 7770);
udpSocketB.send(packetToB);
if (received.equals("end")) {
running = false;
continue;
}
}
I just add client1 and server codes and rest is similar. What could be the reason?
When you write over a TCP socket, it will coalesce bytes if possible into an MTU of data of around ~1500 bytes making the overhead of the packet header relatively small.
When you write each line in its own UDP packet it has an overhead for each line, possibly more than the actual data sent.
Note: in neither case do you need to read a line at a time. You can read say a byte[] of 1 KB at a time and print that.
public class TCPClient {
public static void main(String[] args) throws IOException {
try (Socket socket = new Socket("localhost", 7755);
FileInputStream fis = new FileInputStream(args[0])) {
byte[] bytes = new byte[1024];
OutputStream out = socket.getOutputStream();
for (int len; (len = fis.read(bytes)) > 0; ) {
out.write(bytes, 0, len);
}
}
}
}
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(7755);
System.out.println("Server is ready...");
try (Socket socket = serverSocket.accept()) {
byte[] bytes = new byte[1024];
for (int len; (len = socket.getInputStream().read(bytes)) > 0; )
System.out.write(bytes, 0, len);
}
}
}
You can do the same thing with UDP, transfering 1 KB at a time and get a similar throughput.
NOTE: UDP is lossy, so you might lose packets, or get them out of order.
TCP has been heavily optimized by some of the greatest networking experts in the world. It's specifically designed for sending streams of data over IP networks as quickly and efficiently as possible. It's tied into the kernel and they are heavily optimized as a unit on most modern platforms. You're not going to outperform it unless it does something that you don't need and you can obtain a significant benefit from not doing that thing.

Multicast a file to a group of users

I have a problem to send a file to a group of users. Users could receive the file was sent from server but the file would not be saved if it is less than 8kb.
Here is the code:
MulticastSocketServer
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class MulticastSocketServer{
public static void main(String[] args) {
String fileName;
String address = "235.0.0.1";
int port = 2222;
Scanner in = new Scanner(System.in);
System.out.print("Please enter file name : ");
fileName = in.next();
try (DatagramSocket serverSocket = new DatagramSocket()) {
InetAddress addr = InetAddress.getByName(address);
BufferedReader br = new BufferedReader(new FileReader(fileName + ".txt"));
DatagramPacket fn = new DatagramPacket(fileName.getBytes(),fileName.getBytes().length, addr, port);
serverSocket.send(fn);
DatagramPacket msgPacket = null;
String txt = "";
while((txt = br.readLine())!=null){
msgPacket = new DatagramPacket(txt.getBytes(),txt.getBytes().length, addr, port);
serverSocket.send(msgPacket);
System.out.println(txt);
}
}catch (IOException ex) {ex.printStackTrace();}
}
}
MulticastSocketClient
import java.io.*;
import java.net.*;
public class MulticastSocketClient {
public static void main(String[] args) throws UnknownHostException {
int port = 2222;
String address = "235.0.0.1";
InetAddress addr = InetAddress.getByName(address);
byte[] buf = new byte[64];
byte[] buf2 = null ;
try (MulticastSocket clientSocket = new MulticastSocket(port)){
clientSocket.joinGroup(addr);
DatagramPacket fn = new DatagramPacket(buf, buf.length);
clientSocket.receive(fn);
String name = new String(buf, 0, buf.length);
String fileName = name.trim();
try(PrintWriter pw = new PrintWriter(new FileWriter(fileName+"2.txt"))){
while (true) {
buf2 = new byte [1024];
DatagramPacket msgPacket = new DatagramPacket(buf2, buf2.length);
clientSocket.receive(msgPacket);
String msg = new String(buf2,0,buf2.length);
String txt = msg.trim();
pw.println(txt);
System.out.println(txt);
}
}catch(FileNotFoundException ex){ex.printStackTrace();}
} catch (IOException ex) {ex.printStackTrace();}
}
}
You're never exiting the while (true) loop, because you don't have any mechanism for transmitting end of stream, so you're never closing the PrintWriter, so it isn't flushing its final buffer, so any file < 4096 chars won't get flushed at all, so it will be zero length.
However your code has much worse problems that this. You are assuming:
the filename fits into 1024 characters
every line of the input file fits into 1024 bytes
the filename is received first
all the content packets are received
all the content packets are received in order
all the content packets are received exactly once
the length of every datagram is 1024
the data is text, not binary, and can be converted losslessly to a String
You're using UDP. That means that most of these assumptions are invalid.

Filtering URL content in a self written proxy using Java

I need to code some proxy server for an assignment in my university. It should be able to display the content of some simple web page given by our professor.
Additionally it should filter the URL and the URL content, and block the web page if one of these contain one of the words in my "bad" array.
My question is, how can I perform this filtering in Java.
Code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ProxyServer{
//Crate the Port the user wants the proxy to be on
static Scanner sc = new Scanner(System.in);
public static final int portNumber = sc.nextInt();
public static void main(String[] args) {
ProxyServer proxyServer = new ProxyServer();
proxyServer.start();
}
public void start() {
System.out.println("Starting the SimpleProxyServer ...");
try {
String bad[]= new String[4];
bad[0]= "Spongebob";
bad[1]= "Britney Spears";
bad[2]= "Norrköping";
bad[3]= "Paris Hilton";
ServerSocket serverSocket = new ServerSocket(ProxyServer.portNumber);
System.out.println(serverSocket);
byte[] buffer= new byte [1000000] ;
while (true) {
Socket clientSocket = serverSocket.accept();
InputStream inputstream = clientSocket.getInputStream();
System.out.println(" DAS PASSIERT VOR DEM BROWSER REQUEST:");
int n = inputstream.read(buffer);
String browserRequest = new String(buffer,0,n);
System.out.println("Das ist der Browserrequest: "+browserRequest);
System.out.println("Das ist der Erste Abschnitt");
int start = browserRequest.indexOf("Host: ") + 6;
int end = browserRequest.indexOf('\n', start);
String host = browserRequest.substring(start, end - 1);
System.out.println("Connecting to host " + host);
Socket hostSocket = new Socket(host, 80); //I can change the host over here
OutputStream HostOutputStream = hostSocket.getOutputStream();
PrintWriter writer= new PrintWriter (HostOutputStream);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream));
String Input= null;
while (((Input= reader.readLine())!= null)){
writer.write(Input);
writer.flush();
System.out.println("Empfangen vom Client: "+Input);
}
// for (int i=0; i<4;i++){
// if (inString.contains(bad[i])){
// System.out.println("Bye Idiot");
// break;
// }
// }
System.out.println("Forwarding request to server");
HostOutputStream.write(buffer, 0, n);// but then the buffer that is fetched from the client remains same
HostOutputStream.flush();
InputStream HostInputstream = hostSocket.getInputStream();
OutputStream ClientGetOutput = clientSocket.getOutputStream();
System.out.println("Forwarding request from server");
do {
n = HostInputstream.read(buffer);
String inhalt= HostInputstream.toString();
System.out.println("das ist der inhalt vom HOST: "+ inhalt);
String vomHost = new String(buffer,0,n);
System.out.println("Vom Host\n\n"+vomHost);
// for(int i=0;i<n;i++){
// System.out.print(buffer[i]);
// }
System.out.println("Receiving " + n + " bytes");
if (n > 0) {
ClientGetOutput.write(buffer, 0, n);
}
} while (HostInputstream.read(buffer)!= -1);//n>0
ClientGetOutput.flush();
hostSocket.close();
clientSocket.close();
System.out.println("End of communication");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

How to make sure that the file passed using java.net is as it was before transmission

I'm studying java.net and trying to transmit som file. here is the sender code
public static final FilesGetter filesGetter = new FilesGetter();
public static Socket s;
public static File[] files;
public static void main(String args[]) throws Exception{
s = new Socket("localhost", 3128);
while (true){
try{
files = filesGetter.getFilesList("/etc/dlp/templates/");
Socket s = new Socket("localhost", 3128);
args[0] = args[0]+"\n"+s.getInetAddress().getHostAddress()
+":"+s.getLocalPort();
if (files != null){
for (int i = 0; i < files.length; i++){
InputStream is = new FileInputStream(files[i]);
byte[] message = IOUtils.toByteArray(is);
s.getOutputStream().write(message);
byte buf[] = new byte[64*1024];
int r = s.getInputStream().read(buf);
String data = new String(buf, 0, r);
System.out.println(data);
}
}
} catch(Exception e){
System.out.println("init error: "+e);
}
}
}
And here is the receiver code:
public class Consumer extends Thread{
public static Socket s;
public String customerId;
int num;
public static final Filter filter = new Filter();
public MimeParser mimeParser = new MimeParser(true);
public Consumer(int num, final Socket s, final String customerId){
this.num = num;
this.s = s;
this.customerId = customerId;
setDaemon(true);
setPriority(NORM_PRIORITY);
start();
}
public static void receive(final String customerId){
try {
int i = 0;
ServerSocket server = new ServerSocket(3128, 0, InetAddress.getByName("localhost"));
System.out.println("server started");
while (true){
new Consumer(i, server.accept(), customerId);
i++;
}
} catch (Exception e){
e.printStackTrace();
}
}
public void run(){
try {
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
byte buf[] = new byte[64*1024];
int r = is.read(buf);
if (r < 0)
return;
ByteArrayInputStream bais = new ByteArrayInputStream(buf, 0, r);
MessageInfo mi = mimeParser.parseMessages(bais);
filter.getMessageAcceptability(mi.getPlainText(), customerId);
s.close();
} catch (Exception e){
System.out.println("init error: " + e);
}
}
}
I'm not sure of data integrity because processing of data on the server-side is not fully successful and don't know if I need to look for mistakes in the processing code(which worked well when I've been Using rabbitmq) or in client-server code. I also don't know what buffer size must be chosen.
At the sender side you can send as much as you want, 64*1024 it's OK, the send method will loop until all the data has been delivery. But at the receiver it could be that read returns before the whole file has been read, you must loop reading until the other side closes the socket.
In these cases it's better to send, in advance, an integer indicating how much data you are going to send, the receiver will loops until that much bytes are read.
For example:
int ret=0;
int offset=0;
int BUFF_LEN=64*1024;
byte[] buffer = new byte[BUFF_LEN];
while ((ret = is.read(buffer, offset, BUFF_LEN - offset)) > 0)
{
offset+=ret;
// just in case the file is bigger that the buffer size
if (offset >= BUFF_LEN) break;
}
You need to compute a checksum like SHA-1 on both the sender and the receiver's side. When they match, you can assume that there was no transmission error. Your question is really more of a protocol question.
A much simpler and more practical solution than to implement your own integrity checks would be to use the SSL protocol. That will provide you with integrity checked transmissions.

Streaming an array over TCP in Java

I am trying to stream an array of strings accross a network. I can send a single string but once I try sending an array of strings I run into problems. I did some research and came up fix which works without errors in the IDE, but then the program crashes when I run it externally. I have narrowed it down to an infinite loop that I have accidently created. I will pastebin all the code as there is too much to put up on here.
Here is the summary of what I am trying to achieve...
Open text file
Read in line by line (each line into a separate string inside of an
array)
Once file read is complete, start streaming each individual string
Have a for loop on the recieve end placing the strings back into
another array
And finally, on the server side, break up each part of the string
into 5 different strings
Here is my client class:
public class Transfers {
public int port = 1223;
//public String Ip = LoginForm.IP;
//public String ip = null;
public static Socket login = null;
public static Socket sock = null;
public static PrintWriter outStream = null;
private static BufferedReader inStream = null;
private static boolean ON = false;
public static String authorize = null;
public static boolean connected = true;
public static void transfers(String IP, int port, String content) throws UnknownHostException, IOException {
try {
login = new Socket(IP, port);
//System.out.println("Connected for streaming");
outStream = new PrintWriter(login.getOutputStream(), true);
outStream.println(content);
} catch (UnknownHostException ex) {
Logger.getLogger(Transfers.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Transfers.class.getName()).log(Level.SEVERE, null, ex);
login.close();
}
}
public static String[] recieveArray(String IP) throws UnknownHostException, IOException {
String[] farray = null;
sock = new Socket(IP, 1224);
inStream = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String count = inStream.readLine();
int counter = Integer.parseInt(count);
System.out.println("counter");
for (int i = 0; i < counter; i++) {
inStream = new BufferedReader(new InputStreamReader(sock.getInputStream()));
farray[i] = inStream.readLine();
System.out.println(farray[i]);
}
return farray;
}
}
Here is my server class:
public class Specials {
private static ServerSocket server = null;
private static Socket client = null;
private static PrintWriter outStream = null;
private static BufferedReader inStream = null;
private static boolean ServerOn = true;
public static String message = "";
public static String command = null;
static public InetAddress IP = null;
public static String status = null;
private static String file = "accounts.dat";
private static int counter;
public static void arraysend(String filename) throws FileNotFoundException, IOException {
counter = 0;
FileInputStream fstream = new FileInputStream("AppData/" + filename);
String strLine;
String[] filearray;
try (DataInputStream in = new DataInputStream(fstream)) {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
filearray = new String[1000];
for (int j = 0; j < 10; j++) {
filearray[j] = br.readLine();
counter++;
}
in.close();
}
try {
server = new ServerSocket(1224);
client = server.accept();
IP = client.getInetAddress();
outStream = new PrintWriter(client.getOutputStream(), true);
filearray[0] = Integer.toString(counter);
outStream.println(filearray[0]);
for (int i = 1; i < counter; i++) {
outStream = new PrintWriter(client.getOutputStream(), true);
outStream.println(filearray[i]);
}
client.close();
server.close();
} catch (IOException ex1) {
Logger.getLogger(Specials.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
I do not get any error messages, The application just crashes. I am including pastebins of my code below for convenience.
Client code
Server code
Any help would be appreciated, thanks.
c
There's so many issues with this code I am not sure where to start. Here is a (non-exhaustive) list:
You are using static modifiers for your class variables and
methods. They do not serve any purpose being defined this way and
and make debugging miserable. Remove them all.
Create only those class variables that are actually required in order
to maintain state. Currently most of the variables you declare at a
class level could actually be declared within the methods that use
them.
In your client side recieveArray method you are reinitializing your
buffered reader during every iteration of the receive loop. This is
most likely leading to missing data since you will be trashing some
data that had been buffered in the previous reader (and no longer
available from the socket input stream).
In your client side recieveArray method, you are reading up to
count strings, but on your server side you send count - 1
strings, because you are storing the count in the first element of
the array you had previously filled.
This code:
for (int j = 0; j < 10; j++) {
filearray[j] = br.readLine();
counter++;
}
for (int i = 1; i < counter; i++) {
outStream = new PrintWriter(client.getOutputStream(), true);
outStream.println(filearray[i]);
}
In the code I posted above (server side) you are also recreating the
output stream to the client in every iteration of the send loop.
Fix all those problems and retest, then come ask followup questions if need be.
see your code in Transfers class you are intialize farray array with null
.and also you are using this in for loop
inStream = new BufferedReader(new InputStreamReader(sock.getInputStream()));
and in Specials class you again use in for
outStream = new PrintWriter(client.getOutputStream(), true);

Categories

Resources