Sending textfile from client to server and then back to client - java

I need some help from you guys. I'm new at networking and try to send a text file from a client to a server, and then back to the client again.
The code below works fine for the first step, sending the text file from client to server. The server receives the file, and adds something to it (not in this code).
Then my problem starts: How can I make the server send the text file back to client again, and have client receive it?
I really don't know how to do this. And also, can you tell me if I need to add a while loop to my code, if I want to send files back and forth many times?
Thanks
Client (Starts with sending a text file to server)
public class TClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 11111);
InputStream in = new FileInputStream("send.txt");
OutputStream out = socket.getOutputStream();
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
in.close();
}
}
Server (starts with receiving a text file from client)
public class TServer {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(11111);
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("receive.txt");
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
in.close();
}
}

Related

Problem with client-server application on java

Good day, I'm a beginner developer and I'm trying to write a client-server application. My application should work like this, it checks if the file has been modified and if so, it is sent to the server, the question is how to organize this?
I did it through the socket, but if I get a deadlock, I will be grateful for any comments, I attach the code further
Server
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket;
Socket client;
BufferedInputStream clientInputStream;
ByteArrayOutputStream byteArrayOutputStream;
StringBuilder fileName;
byte[] mass;
{
fileName = new StringBuilder("this.txt"); // give name for file
serverSocket = new ServerSocket(5000); // open server in 5000 port
mass = new byte[1]; // create new buffer array
client = serverSocket.accept(); // waiting connect
clientInputStream = new BufferedInputStream(client.getInputStream()); // to accept byte's array
byteArrayOutputStream = new ByteArrayOutputStream(); // to write byte array in file
}
{
BufferedOutputStream bufferedOutputStream;
int bytesRead;
// FIXME: 02.07.2022 первый файл
do {
byteArrayOutputStream.write(mass, 0, mass.length); // write by one byte in array
bytesRead = clientInputStream.read(mass, 0, mass.length);
} while (bytesRead != -1);
FileOutputStream writer = new FileOutputStream(fileName.toString()); // stream for file write
bufferedOutputStream = new BufferedOutputStream(writer);
bufferedOutputStream.write(byteArrayOutputStream.toByteArray(), 0, byteArrayOutputStream.toByteArray().length); // write file
System.out.println("first f");
bufferedOutputStream.flush();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
bufferedWriter.write("success"); // if file send success then write string in socket and send to client
}
{
serverSocket.close();
client.close();
clientInputStream.close();
byteArrayOutputStream.close();
}
}
}
And Client
import java.io.*;
import java.net.Socket;
public class Client {
private final static String serverIP = "192.168.0.47"; // server ip address
private final static int serverPort = 5000; // server port address
private final static String fileOutput = "first.txt"; // first file to send
private final static String fileOutput1 = "second.txt"; // second file to send
public static void main(String[] args) throws IOException, InterruptedException{
Socket client = new Socket(serverIP,serverPort); // make new connect with my server
BufferedInputStream inputFile = new BufferedInputStream(new FileInputStream(fileOutput)); // convert file to array bytes
// FIXME: 02.07.2022 first file
BufferedOutputStream clientSocketOutputWriter = new BufferedOutputStream(client.getOutputStream()); // this is the stream to send to the socket
byte[] massByte = inputFile.readAllBytes(); // this going on convert file to array bytes
clientSocketOutputWriter.write(massByte,0, massByte.length); // send array bytes to server
System.out.println("first file send");
//----------------if i remove this two string, program begin work successfully but i can't send several file because this beging deadlock
// BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// String s = bufferedReader.readLine();
//----------------
System.out.println("the end");
clientSocketOutputWriter.close();
client.close();
inputFile.close();
}
}
If the TCP connection isn't closed,The variable bytesRead will never be -1 because the code clientInputStream.read(mass, 0, mass.length); keeps executing and waiting for data.If you want to send a file,you should send its length first then you can call byte[] data=clientInputStream.readNBytes(its length),or put its data into a object and use ObjectInputStream and ObjectOutputStream to send the object.
The variable bytesRead isn't -1 means the server cannot leave the loop,so the server cannot put the data which it has just received into a file.Just use writer.write(mass); instead of byteArrayOutputStream.write(mass, 0, mass.length);,write the data to the file directly then stop running the program can solve the problem too.

Solving "socket is closed" exception while copying file from server to client and vice versa

I'm doing simple Client-Server applications which copying file from client to server and vice versa. I'm using Sockets of course. Apps shows Client menu with some options to choose: 1. Make Copy on sever 2. Get fileCopy from Server etc.
The issue is when I'm choosing first option, I can't do second one. I read about this exception, but i have no idea how to solve this problem. I'm looking forward for your ideas.
There is part of clientside code:
public Client(String host, int port) {
try {
s = new Socket(host, port);
System.out.println("Witaj w programie");
boolean finished = false;
Scanner sc = new Scanner(System.in);
while(!finished){
System.out.println("\n\n1.Zrob kopie zapasowa pliku");
System.out.println("2. Przywroc kopie");
System.out.println("0.Zakoncz");
char c = sc.nextLine().charAt(0);
switch(c){
case '1':
this.sendMessage(1);
makeCopy(s);
//s.close();
break; ...
sendMessage method code:
public void sendMessage(int message_id) throws IOException{
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
oos.writeInt(message_id);
oos.flush();
}
and makeCopy method code:
private void makeCopy(Socket clientSock) throws IOException {
File file = new File("D:\\klient\\doKopii.bmp");
DataOutputStream dos = new DataOutputStream(clientSock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
dos.write(buffer);
}
fis.close();
dos.close();
}
Download copy from Server code:
private void saveFile(Socket clientSock) throws IOException {
//DataInputStream dis = new DataInputStream(clientSock.getInputStream());
FileOutputStream fos = new FileOutputStream("D:\\klient\\przywroconaKopia.bmp");
File zSerwera = new File("D:\\serwer\\kopiaPliku.bmp");
byte[] buffer = new byte[4096];
int filesize = (int)zSerwera.length();
int read = 0;
int totalRead = 0;
int remaining = filesize;
while((read = ois.read(buffer, 0, Math.min(buffer.length, remaining))) > 0) {
totalRead += read;
remaining -= read;
System.out.println("read " + totalRead + " bytes.");
fos.write(buffer, 0, read);
}
//fos.close();
//ois.close();
}
I am aware of that this does not work because of DataOutputStream closing which means socket is also closed. I deleted this line, but after choosing one option then second (when first one has done), application just freezes.
oos = new ObjectOutputStream(s.getOutputStream());
ois = new ObjectInputStream(s.getInputStream());
public void sendMessage(int message_id) throws IOException{
oos.writeInt(message_id);
}
make oos and ois as instance variables and make sure that they are instantiated only for one single time.
why you have to get a dataoutput stream seperately you can send byte array in same objectoutputstream
private void makeCopy(Socket clientSock) throws IOException {
File file = new File("D:\\klient\\doKopii.bmp");
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[4096];
while (fis.read(buffer) > 0) {
oos.write(buffer);
}
}
this is not very good coding practise bt maybe u should try this approach
There are several problems here.
You need to send the file length ahead of the file, and read exactly that many bytes at the receiver, as shown in this answer.
Don't mix stream types, and don't keep creating new streams. Use the same ObjectInputStream/ObjectOutputStream pair for the life of the socket, at both ends.

Concurrency Issue Using Multithreading in Java

I have written a code for Server and Client in Java. Clients are able to download the files from the server and the server should also be able to provide files to clients Concurrently.
For this purpose I have used multithreading in Server.
It is working perfectly fine for one client but while using threads for every client it seems to be not working properly in my Code.
As the files are not getting downloaded correctly, are corrupt and are of varying sizes for different clients.
After accepting from a client, I am creating a new Thread for serving it the file
Code for server -
public static void send(String pathname) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException
{
try
{
System.out.println("....");
byte[] buf = new byte[1024];
OutputStream os = sock.getOutputStream();
//PrintWriter writer = new PrintWriter(os);
System.out.println("...11.");
BufferedOutputStream out = new BufferedOutputStream(os, 1024);
int i=0;
System.out.println("hi1");
File fp = new File(pathname);
System.out.println("hi2");
RandomAccessFile ra = new RandomAccessFile(fp,"r");
System.out.println("hi3");
long bytecount=1024;
////////////////
while((i=ra.read(buf, 0, 1024)) != -1)
{
System.out.println("hi");
bytecount += 1024;
System.out.println("hi6");
out.write(buf, 0, i);
System.out.println("hi7");
out.flush();
}
System.out.println("bye");
//os.flush();
//out.close();
ra.close();
//sock.close();
}
catch(IOException ex)
{
}
}
And code for client for file receiving is
public void run() {
try{
byte[] b = new byte[1024];
int len = 0;
long bytcount = 1024;
File fp = new File(path);
RandomAccessFile ra=new RandomAccessFile(fp,"rw");
ra.seek(0);
InputStream is = sock.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(is));
while ((len = is.read(b, 0, 1024)) != -1) {
bytcount = bytcount + 1024;
//decrypt
ra.write(b, 0, len);
}
//is.close();
//ra.close();
//sock.close();
}
catch(IOException ex){
ex.printStackTrace();
}
// throw new UnsupportedOperationException("Not supported yet.");
}
}
I am not getting out what's wrong here. Please help
Many many thanx in advance
send is static, which suggests to me that you have only one socket, named sock, or the following would not compile.
public static void send(String pathname) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException
{
try
{
System.out.println("....");
byte[] buf = new byte[1024];
OutputStream os = sock.getOutputStream();
//PrintWriter writer = new PrintWriter(os);
System.out.println("...11.");
If that is the case, it's hard to see how delivery to >1 client will be reliable. You will surely need one socket per client to perform concurrent deliveries? More code is needed to be sure of this, but it looks like the design of socket handling may need to be revised.
Your first problem is that you are using an OutputStream on the server and a Reader on the client. the client should be using InputStreams, not Readers.

Sending file from one client to another client using socket in java

Hello everyone ,
I am trying to develop the application for transfering/sending the file like SKYPE works.So I am using socket for transfering file from one computer(client) to another computer(client) .I am able to transfer file from one client to server using this. code.But when I try to send the same file from server to second client.It is transfering with 0 byte also give socket close exception so I try to create new socket object at client side.So Now the Exception not coming but file not transfering to client.After debugging I found that the file is successfully sent to client by server but at client side socket is not able to read the data and waiting for data.I can’t find any better solution.If anyone knows anything about this Please tell me.If you have any other solution for file transfer than also tell me.Thanks in advance
Below is my code
Server code:
public class ChatServer
{
serversocket = new ServerSocket(1436);
thread = new Thread(this);
thread.start();
/*************Thread Implementation***************/
public void run()
{
/*********Accepting all the client connections and create a seperate thread******/
while(thread != null)
{
try
{
/********Accepting the Server Connections***********/
socket = serversocket.accept();
/******* Create a Seperate Thread for that each client**************/
chatcommunication = new ChatCommunication(this,socket);
thread.sleep(THREAD_SLEEP_TIME);
}
catch(InterruptedException _INExc) { ExitServer(); }
catch(IOException _IOExc) { ExitServer(); }
}
}
protected void SendGroupFile(Socket ClientSocket, String FileName,String GroupName,String UserName) throws IOException
{
try
{
// receive file from Client
byte [] mybytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(Filepath);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =is.read(mybytearray, current, (mybytearray.length-current));
System.out.println("Reading Bytes server"+bytesRead);
if(bytesRead >= 0)
current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray,0,current);
bos.flush();
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/***** Function To Send a File to Client **********/
protected void SendGroupFileClient(Socket ClientSocket, String FileName,String GroupName,String UserName)
{
try {
int m_userListSize = userarraylist.size();
clientobject = GetClientObject(GroupName);
if(clientobject != null)
for(G_ILoop = 0; G_ILoop < m_userListSize; G_ILoop++)
{
clientobject = (ClientObject) userarraylist.get(G_ILoop);
if((clientobject.getGroupName().equals(GroupName)) && (!(clientobject.getUserName().equals(UserName))))
{
{
File myFile = new File (Filepath);
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = socket.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
os.close();
}
}catch(IOException _IOExc)
{
_IOExc.printStackTrace();
}
}
}
ChatCommunication .java
public class ChatCommunication implements Runnable,CommonSettings
{
Thread thread;
Socket socket;
DataInputStream inputstream;
String RFC;
ChatServer Parent;
/********Initialize the Socket to the Client***********/
ChatCommunication(ChatServer chatserver,Socket clientsocket)
{
Parent = chatserver;
socket = clientsocket;
try
{
inputstream = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}catch(IOException _IOExc) { }
thread = new Thread(this);
thread.start();
}
public void run()
{
while(thread != null)
{
try {
RFC = inputstream.readLine();
if(RFC.startsWith("FILEGRUP"))
{
Parent.SendGroupFile(socket,RFC.substring(9,RFC.indexOf("!")),RFC.substring(RFC.indexOf("!")+1,RFC.indexOf("*")),RFC.substring(RFC.indexOf("*")+1));
}
if(RFC.startsWith("FILEGET"))
{
Parent.SendGroupFileClient(socket,RFC.substring(8,RFC.indexOf("!")),RFC.substring(RFC.indexOf("!")+1,RFC.indexOf("*")),RFC.substring(RFC.indexOf("*")+1));
}
}catch(Exception _Exc)
{
Parent.RemoveUserWhenException(socket);QuitConnection();
}
}
}
Client code
class Client extends JFrame
{
ServerName="192.168.1.103";
ServerPort=1436;
Client()
{
socket = new Socket(ServerName,ServerPort);
SendGroupFileToServer(Filepath,SelectedGroup);
}
/*******Function To Send File To Server and receiving the file ***********/
protected void SendGroupFileToServer(String FileName, String ToGroup)
{
try {
dataoutputstream.writeBytes(FileName.concat("!").concat(ToUser)+"\r\n");
//send file to sever
File myFile = new File (FileName.substring(9));
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = socket.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
os.close();
System.out.println("File successfully Sended to server");
}catch(IOException _IoExc) { QuitConnection(QUIT_TYPE_DEFAULT);}
try {
socket1 = new Socket(ServerName,ServerPort); //Creating new Socket
dataoutputstream = new DataOutputStream(socket1.getOutputStream());
dataoutputstream.writeBytes("FILEGET"+FileName.concat("!").concat(ToGroup+"*"+UserName)+"\r\n"); //sending string to server
} catch (IOException e1) {
e1.printStackTrace();
}
// receive file sended by server
byte [] mybytearray = new byte [filesize];
InputStream is;
try {
is = socket1.getInputStream();
FileOutputStream fos = new FileOutputStream(Filepath);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead; //up to this working fine
do {
bytesRead =is.read(mybytearray, current, (mybytearray.length-current)); //not reading the file data sent by server just waiting and not go ahead
if(bytesRead >= 0)
current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray,0,current);
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
There are so many problems here that it is difficult to know where to start.
The thread.sleep() in the accept() loop is literally a waste of time. It serves no useful purpose except possibly to throttle the rate at which clients are accepted. If that wasn't your intention, don't do it.
All you are doing when you catch an exception is exiting the server without even printing the exception message. So when something goes wrong, as it is here, you can't possibly know what it was. Don't do that.
readLine() returns null at EOS, on which you must close the socket, stop reading, and exit the thread. You aren't testing that, and you are therefore omitting all three of those required steps. Don't do that.
You are constructing a DataInputStream around a BufferedInputStream for use when reading commands, but you aren't passing it to the methods that process those commands. You are just passing the socket. You are therefore losing data. Don't do that. Every part of the program must use the same input stream or reader for the socket.
You are reading the entire file into memory. This (a) assumes the file size fits into an int; (b) does not scale to large files; (c) wastes space, and (d) adds latency. Don't do that.
You are ignoring the result of the read() into that buffer and assuming it was filled. You can't do that. The correct way to copy streams in Java is shown below. This works with a buffer of any size, e.g. 8192, for an input of any length, and doesn't require you to buffer the entire input into memory. You can use this loop at both the client when sending the file and at the server when receiving it.
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Similarly to (4) above, you are using a DataOutputStream around a BufferedOutputStream for some things and the socket output stream directly for others. Don't do that. All parts of the program must the same output stream or writer for the socket.
You don't need to flush() before close(); it happens automatically.
For some reason after sending the file you are creating a new connection and sending another command. You aren't even closing the connection afterwards. The server will have no easy way of knowing that this connection and this command referred to the file just sent in the code above. It is also redundant, as the receipt of the final EOS tells the server that the file has been sent successfully. Don't do this. If you need to send more information with the file, send it first, before the file, on the same connection.
The reference you cite exhibits many of the above issues. Make an effort to find a reputable starting point.
This is the solution. Please Apply this logic to your code.
I am able to send a file from server to client and client to server.
Check the following code to send the file from Client to Server. It is working great.
If you have any issues let me know.
Server Side Code:
public class ServerRecieveFile {
public static void main(String[] args) throws IOException {// TODO Auto-enerated method stub int filesize=1022386;
int bytesRead; int currentTot= ;
ServerSocket serverSocket=new ServerSocket(15123);
Socket socket=rverSocket.accept();
byte [] bytearray = new byte [filesize];
InputStream is=socket.getInputStream();
File copyFileName=new File("c:/Files Sockets/2.txt");
FileOutputStream fos = new FileOutputStream(copyFileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(bytearray,0,bytearray.length);
currentTot = bytesRead;
do {
bytesRead =is.read(bytearray, currentTot, (bytearray.length-currentTot)); if(bytesRead >= 0)
currentTot += bytesRead;
} while(bytesRead > -1);
bos.write(bytearray, 0 , currentTot);
bos.flush();
bos.close();
socket.close();
}
}
Client Side code:
public class ClientSendFile {
public static void main(String[] args) throws UnknownHostException, IOException {// TODO Auto-generated method stub
Client client=new Client();
Socket socket = new Socket(InetAddress.getLocalHost(),15123);
System.out.println("Accepted connection : " + socket);
File transferFile = new File ("c:/Files Sockets/1.txt");
byte [] bytearray = new byte (int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray,0,bytearray.length);
OutputStream os = socket.getOutputStream();
System.out.println("Sending Files...");
os.write(bytearray,0,bytearray.length);
os.flush();
socket.close();
System.out.println("File transfer complete");
}
}

Java DataInputStream length

I am creating a file server application for school assignment. What I currently have is a simple Client class that sends an image through TCP and a Server class that receives it and writes it to the file.
this is my client code
import java.io.*;
import java.net.*;
class Client {
public static void main(String args[]) throws Exception {
long start = System.currentTimeMillis();
Socket clientSocket = new Socket("127.0.0.1", 6789);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
File file = new File("hot.jpg");
FileInputStream fin = new FileInputStream(file);
byte sendData[] = new byte[(int)file.length()];
fin.read(sendData);
outToServer.write(sendData, 0, sendData.length);
clientSocket.close();
long end = System.currentTimeMillis();
System.out.println("Took " + (end - start) + "ms");
}
}
and this is my server code.
import java.io.*;
import java.net.*;
class Server {
public static void main(String args[]) throws Exception {
ServerSocket serverSocket = new ServerSocket(6789);
Socket connectionSocket = serverSocket.accept();
DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());
byte[] receivedData = new byte[61500]; // <- THIS NUMBER
for(int i = 0; i < receivedData.length; i++)
receivedData[i] = dis.readByte();
connectionSocket.close();
serverSocket.close();
FileOutputStream fos = new FileOutputStream("received.jpg");
fos.write(receivedData);
fos.close();
}
}
My question is how to get the size of the file that is being sent. If you check the Server code you'll see that I've hardcoded the number i.e. 61500 at the moment. How can I retrieve this number dynamically?
Or, am I doing this the wrong way? What an alternative solution would be?
Add one "length field" before sending the file. (Note that since you read the file to memory the maximum size of the file can be ~2GB.)
Before sending the file write the length of the file:
outToServer.writeInt(sendData.length);
And when receiving read the length first and use it as a length:
int dataLength = dis.readInt()
byte[] receivedData = new byte[dataLength];
A better way would be not to read the file into memory first but to transfer it directly from the FileInputStream - then you could transfer bigger files!
If you know the length, using readFully() is much more efficient than reading a byte at a time.
In this case, you don't need to know the length, you can write the loop to read/write as much data as you get.
InputStream is = connectionSocket.getInputStream();
byte[] bytes = new byte[8192];
int len;
while((len = is.read(bytes)) > 0)
fos.write(bytes, 0, len);
You can avoid reading the whole file into memory by copying the data as you read it.
FileInputStream fis = new FileInputStream(filename);
OutputStream os = socket.getOutputStream();
byte[] bytes = new byte[8192];
int len;
while((len = fis.read(bytes)) > 0)
os.write(bytes, 0, len);
You can use Apache IOUtils.copy() to perform the copy from one stream to another if you wish.
This approach has the advantage that the file can be any size (greater than 2 GB). Using an array is limited to 2 GB (and uses more memory)

Categories

Resources