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.
Related
I'm creating File Transfer program that will transfer a file to client. But when I transferred the file, It missing the first letter of every lines. What's wrong with my code?
I'm pretty new at java so I don't know what to do next. I've tried changing byte size but no help. What should I do?
Server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
class Server {
public static void main(String[] args) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket serverSocket = null;
Scanner scan = new Scanner(System.in);
String fileSend;
System.out.print("Type the path to the file to send >> ");
fileSend = scan.nextLine();
try {
serverSocket = new ServerSocket(5467);
} catch (Exception e) {
System.out.println("Could not bind to port 5467, Maybe address is already is use or you need to run as administrator");
return;
}
System.out.println("Listening on port 5467");
System.out.println("Waiting for the connection...");
while (true) {
File FileSend = null;
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
System.out.println("Accepted connection : " + socket);
InputStream in = socket.getInputStream();
DataInputStream dataIn = new DataInputStream(in);
String login = dataIn.readUTF();
String password = dataIn.readUTF();
String result = "You credential is ";
if (login.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b") && password.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b13d0b73358bfa8978dfaaf180565bcfecd3dc0631cda525920865145fb3fa131")) {
result += "correct";
} else {
result += "incorrect";
}
DataOutputStream dataOut = new DataOutputStream(out);
try {
dataOut.writeUTF(result);
} catch (FileNotFoundException e) {
System.out.println("No such file or directory");
}
finally
{
FileSend = new File(fileSend);
byte[] FileByteArray = new byte[(int) FileSend.length()];
try {
fis = new FileInputStream(FileSend);
}
catch (FileNotFoundException e) {
System.out.println("No such file or directory");
return;
}
bis = new BufferedInputStream(fis);
File myFile = new File (fileSend);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = socket.getOutputStream();
System.out.println("Sending " + fileSend + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
}
}
}
Client.java
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Client {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
Socket socket = null;
String PlainLogin;
String FileOut;
String PlainPassword;
Scanner scan = new Scanner(System.in);
System.out.print("What is the IP address of the server >> ");
String host = scan.nextLine();
try {
socket = new Socket(host, 5467);
} catch (ConnectException | NullPointerException e) {
System.out.println("Connection Refused, Have you run the server first?");
return;
}
OutputStream out = socket.getOutputStream();
DataOutputStream dataOut = new DataOutputStream(out);
InputStream is = socket.getInputStream();
System.out.println("Connection Established");
System.out.println("Credential Required, Please login");
System.out.print("Type your username >> ");
PlainLogin = scan.next();
System.out.print("Type your password >> ");
PlainPassword = scan.next();
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashInBytes = md.digest(PlainLogin.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hashInBytes) {
sb.append(String.format("%02x", b));
}
String HashedLogin = sb.toString();
byte[] hashInBytesP = md.digest(PlainPassword.getBytes(StandardCharsets.UTF_8));
for (byte b : hashInBytesP) {
sb.append(String.format("%02x", b));
}
String HashedPassword = sb.toString();
dataOut.writeUTF(HashedLogin);
dataOut.writeUTF(HashedPassword);
InputStream in = socket.getInputStream();
DataInputStream dataIn = new DataInputStream(in);
String str = dataIn.readUTF();
if (str == "Your credential is incorrect") {
System.out.println(str);
return;
} else {
System.out.print("Type any file name you want >> ");
scan.nextLine();
FileOut = scan.nextLine();
OutputStream output = new FileOutputStream(FileOut);
byte[] mybytearray = new byte[1024];
is.read(mybytearray, 0, mybytearray.length);
int bytesRead;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) > 0) {
output.write(buffer, 0, bytesRead);
}
output.close();
socket.close();
dataIn.close();
System.out.println("Done");
return;
}
}
}
I expect it to show full text like "Java", but it only show "ava"
File is Serializable, so I would suggest you should simply try to send it directly via ObjectOutputStream / ObjectInputStream.
For example on Server side :
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
...
out.writeObject(yourFileObject);
And on Client :
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
...
File receivedFile = null;
try {
receivedFile = (File) in.readObject();
}
catch (IOException e) {
...
}
I'm not entirely sure why this happens exactly, but you shouldn't be using DataInputStream which "lets an application read primitive Java data types", but an InputStreamReader which "is a bridge from byte streams to character streams".
Also, you can wrap that reader into a BufferedReader which lets you read line by line, and you'll end up with something like
try (BufferedReader reader=new BufferedReader(new InputStreamReader(inStream, UTF8));
PrintWriter writer = new PrintWriter(file)) {
reader.lines().forEach(writer::println);
}
for an upload, or
try (PrintWriter writer = new PrintWriter(outStream)) {
Files.lines().forEach(writer::println);
}
for download.
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.
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();
}
}
I am trying to send binary files over TCP. The server is written in Python and the client in Java.
Server:
import socket;
TCP_IP = '127.0.0.1'
TCP_PORT = 5001;
BUFFER_SIZE = 1024;
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
except:
"Can not bind server on port: "+ str(TCP_PORT) +"\n";
while 1:
print("Wait for connections!!!\n");
conn, addr = s.accept();
print("Receive a new connection!!!\n");
# presentation of client
data = conn.recv(BUFFER_SIZE);
if not data:
conn.close();
print("Lost connection!!!");
continue;
# respond to client
conn.sendall("Hello 1\n");
# receive new request
data = conn.recv(BUFFER_SIZE);
if not data:
continue;
conn.sendall("OK\n");
f = open('testImage.jpg', "rb");
dataRaw = f.read();
f.close();
fileSize = len(dataRaw); #sys.getsizeof(dataRaw);
# send file size
conn.send(str(fileSize) + "\n");
conn.send(dataRaw);
conn.sendall("OK\n");
Client
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class mainTestReceiveFile
{
public static void main(String[] args) throws Exception
{
String usr2ConnectDefault = "127.0.0.1";
int port2ConnectDefault = 5001;
Socket socket;
BufferedReader in;
PrintWriter out;
socket = new Socket(usr2ConnectDefault, port2ConnectDefault);
System.out.println("Connected to server...sending echo string");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
// say hello to server
out.println("Hello");
// read hello from server
String readString = in.readLine();
System.out.println(readString);
out.println("ReadFile");
// verify if request is OK
readString = in.readLine();
if(readString.compareToIgnoreCase("OK") == 0)
System.out.println("Receive new file!!!");
else
{
socket.close();
return;
}
// get size of file
readString = in.readLine();
int sizeOfFile = Integer.parseInt(readString);
//InputStream is = socket.getInputStream();
byte[] fileData = new byte[sizeOfFile];
for(int i = 0; i < sizeOfFile; i++)
{
fileData[i] = (byte)in.read();
}
// save file to disk
FileOutputStream fos = new FileOutputStream("fileImage.jpg");
try
{
fos.write(fileData);
}
finally {
fos.close();
}
// verify if request is OK
readString = in.readLine();
if(readString.compareToIgnoreCase("OK") == 0)
System.out.println("New file received!!!");
else
{
socket.close();
return;
}
socket.close();
}
}
I am trying to send for example one image. In the client side, the image received has the same size (file size and number of pixels) but the data is corrupted.
I have written the following two codes for finding GCD of two numbers. (via UDP Server)
GCD_UDPClient.java
import java.io.*;
import java.net.*;
class GCD_UDPClient
{
public static void main(String args[]) throws Exception
{
BufferedReader InFromUser = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket ClientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] SendData = new byte[1024];
byte[] ReceiveData = new byte[1024];
System.out.print("First Number: ");
String input1 = InFromUser.readLine();
System.out.print("Second Number: ");
String input2 = InFromUser.readLine();
String Input = input1 + ' ' +input2;
SendData = Input.getBytes();
DatagramPacket SendPacket = new DatagramPacket(SendData, SendData.length, IPAddress, 9836);
ClientSocket.send(SendPacket);
DatagramPacket ReceivePacket = new DatagramPacket(ReceiveData, ReceiveData.length);
ClientSocket.receive(ReceivePacket);
String ModifiedInput = new String(ReceivePacket.getData());
System.out.println("GCD From Server: " +ModifiedInput);
ClientSocket.close();
}
}
GCD_UDPServer.java
import java.io.*;
import java.net.*;
#SuppressWarnings("unused")
class GCD_UDPServer
{
#SuppressWarnings("resource")
public static void main(String args[]) throws Exception
{
DatagramSocket ServerSocket = new DatagramSocket(9836);
byte[] ReceiveData = new byte[1024];
byte[] SendData = new byte[1024];
while(true)
{
DatagramPacket ReceivePacket = new DatagramPacket(ReceiveData, ReceiveData.length);
ServerSocket.receive(ReceivePacket);
String input = new String(ReceivePacket.getData());
InetAddress IPAddress = ReceivePacket.getAddress();
int port = ReceivePacket.getPort();
int ar[] = new int[2],i=0;
for (String Number: input.split(" ", 2))
{
ar[i] = Integer.parseInt(Number);
i=i+1;
}
String Answer = Integer.toString(calculategcd(ar[0],ar[1]));
SendData = Answer.getBytes();
DatagramPacket SendPacket = new DatagramPacket(SendData, SendData.length, IPAddress, port);
ServerSocket.send(SendPacket);
}
}
public static int calculategcd(int a, int b)
{
if(b%a == 0)
return a;
else
return calculategcd(b%a,a);
}
}
ClientSocket.receive(ReceivePacket); doesn't seem to work properly, any clues why? Full codes are posted only for clarity.
Output given by the above codes:
First Number: 5
Second Number: 25
[waits indefinitely]
Output Required:
First Number: 5
Second Number: 25
GCD From Server: 5
You are sending 1024 bytes to the server, and you placed your data in a String like "5 25". When you receive the data you split it and you will have "5", and "25" followed by the other bytes in your buffer. Either you use Number.trim() to throw away those extra bytes, or you send a smaller packet (if that is possible).
I had a test , the GCD_UDPServer.java have a exception like
Exception in thread "main" java.lang.NumberFormatException: For input string: "12"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at GCD_UDPServer.main(GCD_UDPServer.java:24)
and simply change line 24
ar[i] = Integer.parseInt(Number);
to
ar[i] = Integer.parseInt(Number.trim());
and it works properly.