Sockets, sent pdf file always arrives zero bytes size - java

I'm sending a pdf file from android tablet client to Java app running on Windows 7. The file always arrives as a size of zero bytes. what is the problem here?
Before the pdf file was sent from client to server, the size of the file as long value is sent from client to server, this size is correct and always arrives to the server. For the pdf file, I'm using for this test the size is 566718 bytes.
How can I get the pdf file to arrive as the correct size?
Server code
public class Server {
ServerSocket serverSocket;
Socket socket;
boolean runner = true;
Server() throws IOException{
serverRunner();
System.out.println("server constructor started");
} // Server() constructor
public void serverRunner() throws IOException {
System.out.println("serverrunner started");
try {
serverSocket = new ServerSocket(6789, 100);
runner = true;
while (runner) {
socket = serverSocket.accept();
MultiThreader multi = new MultiThreader(socket);
Thread t = new Thread(multi);
t.start();
} // while runner
} catch (IOException ex) {
}
} // serverRunner()
} // class Server
public class MultiThreader implements Runnable {
Socket socket;
public int fileSizeFromClient;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
public MultiThreader(Socket socket){
System.out.println("print out from multithreader class");
this.socket = socket;
} // multiThreader
#Override
public void run() {
System.out.println("multi threader started");
// action #1 read file from client =====================================
// transfer.pdf read this file sent from android device to this computer
int bufferSize = 0;
try {
bis = new BufferedInputStream(socket.getInputStream());
dis = new DataInputStream(bis);
fileSizeFromClient = dis.readInt();
System.out.println("file size from client is " + fileSizeFromClient);
File fileDirectory = new File("C:/DOWNLOAD/");
if (!fileDirectory.exists()) {
fileDirectory.mkdir();
}
File file = new File("C:/DOWNLOAD/transfer.pdf");
file.createNewFile();
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
dos = new DataOutputStream(bos);
byte[] buffer = new byte[fileSizeFromClient];
int totalBytesRead = 0;
while(totalBytesRead < fileSizeFromClient){
int bytesRemaining = fileSizeFromClient = totalBytesRead;
int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
if(bytesRead == -1) {
break;
} else {
dos.write(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
}
} // while
} catch (IOException ex) {
Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
// socket.close();
} catch (IOException ex) {
Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
}
}
} // run
} // MultiThreader
client code
public class MainActivity extends Activity implements Runnable {
TextView textViewOne;
Button buttonOne;
Socket socket;
private String serverIP = "192.XXX.X.X";
FileInputStream fis;
FileOutputStream fos;
private File file;
DataInputStream dis;
DataOutputStream dos;
BufferedInputStream bis;
BufferedOutputStream bos;
long length;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewOne = (TextView) findViewById(R.id.textView1);
buttonOne = (Button) findViewById(R.id.button1);
buttonOne.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Thread myThread = new Thread(MainActivity.this);
myThread.start();
}
});
} // oncreate
#Override
public void run() {
MainActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
textViewOne.setText("run method started");
}
});
try {
socket = new Socket(InetAddress.getByName(serverIP), 6789);
if (socket == null) {
return;
} else {
MainActivity.this.runOnUiThread(new Runnable(){
#Override
public void run() {
textViewOne.setText("connected");
}
});
}
file = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "transfer.pdf");
length = file.length();
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
bos = new BufferedOutputStream(socket.getOutputStream());
dos = new DataOutputStream(bos);
dos.writeInt((int) length); // sends the length as number bytes is file size
int count = 0;
byte[] buffer = new byte[(int) length];
while ((count = bis.read(buffer)) > 0)
{
bos.write(buffer, 0, count);
}
bos.flush();
bis.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} // mainactivity

This is the problem, I believe.
int bytesRemaining = fileSizeFromClient = totalBytesRead;
That's doing two assignments, so you're assigning 0 to fileSizeFromClient immediately, and exiting the loop.
You meant:
int bytesRemaining = fileSizeFromClient - totalBytesRead;
That's a pretty subtle typo, and you were unlucky that it's a typo which still resulted in valid code :(
Given that you're closing the socket immediately anyway though, it's not clear why you're sending the file size first. Your code could be simpler if you just had the same "copy from an input stream to an output stream until the input runs out of data" at both the client and the server, just from a FileInputStream to a Socket's OutputStream at the client, and the Socket's InputStream to a FileOutputStream (possibly with a buffering wrapper) at the server.
I'd also recommend closing all streams - if you're using Java 7, you can do this simply using a try-with-resources statement; in earlier versions you should close streams in finally blocks.

- By rule of thumb, always close the Streams after writing/reading to and from it.
- Close the Stream at Server side.
- Use Socket with InputStream and Scanner for hassle free data transfer between socket. (Thats what i felt, experimenting with sockets.)

Related

Android SDK, Output Stream from client to server doesn't work

So I was just seeing if I could build a dead simple chat application, and im facing a problem... I have the server running on my pc and the client on my phone, Once the client has connected to my pc I can then go to my pc and write as many messages as I want and they will appear on my phone (client), but when I try to send a message from my phone it will only send one message then no more, any ideas?
Server:
static OutputStream out;
static InputStream in;
String name = "Server";
public static void main(String args[]){
System.out.println("Server On");
//Server
new Thread(new Runnable(){
#Override
public void run(){
new Main().start();
}}).start();
//Scanner for text input
new Main().scrnn();
}
public void scrnn(){
Scanner lol = new Scanner(System.in);
if(lol.hasNext()){
try {
out.write((name + ": " +lol.nextLine().toString()).getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
scrnn();
}
public void start(){
try{
ServerSocket sok = new ServerSocket(42069);
while(true){
Socket sk = sok.accept();
in = sk.getInputStream();
out = sk.getOutputStream();
byte[] buffer = new byte[1024];
in.read(buffer);
String recievedData = new String(buffer);
System.out.println(recievedData);
out.write(recievedData.getBytes());
}
}catch(Exception e){
e.printStackTrace();
}
}
And the client:(android phone)
OutputStream out;
InputStream in;
Socket sk;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new Object[]{"Thanks for using Monsterchat"};
Button button = (Button)findViewById(R.id.buttonSend);
listView = (ListView) findViewById(R.id.listView);
new Thread(new Runnable() {
#Override
public void run() {
try {
sk = new Socket("10.0.0.9", 42069);
sk.setKeepAlive(true);
out = sk.getOutputStream();
in = sk.getInputStream();
//This will send fine but if you look at the button onclick it wont send that :(
out.write((name + " Joined the group!").getBytes());
//This is how i can send constant messages from the server though
listenForData();
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
try {
out.write("succ".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
}
public void listenForData() throws Exception{
byte[] buffer = new byte[1024];
in.read(buffer);
final String recievedData = new String(buffer);
runOnUiThread(new Runnable() {
#Override
public void run() {
//Update listView with new message
buildList(recievedData);
}
});
//Repeat
listenForData();
}
Sorry there's a lot of code, and also nothing gets output in the logcat that looks wrong
while(true){
Socket sk = sok.accept();
in = sk.getInputStream();
out = sk.getOutputStream();
Dr byte[] buffer = new byte[1024];
in.read(buffer);
String recievedData = new String(buffer);
System.out.println(recievedData);
out.write(recievedData.getBytes());
That loop is wrong. After one received message the server drops sk and will go waiting for a new client.
You better try;
Socket sk = sok.accept();
in = sk.getInputStream();
out = sk.getOutputStream();
byte[] buffer = new byte[1024];
while(true){
int nread = in.read(buffer);
String recievedData = new String(buffer, 0, nread);
System.out.println(recievedData);
out.write(recievedData.getBytes());

Android copy file from internal storage to external

I am trying to Copy file from internal memory card to external memory card
By googling i found this answer
try {
InputStream in = new FileInputStream("/storage/sdcard1/bluetooth/file7.zip"); // Memory card path
File myFile = new File("/storage/sdcard/"); //
OutputStream out = new FileOutputStream(myFile);
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
session.showToast("file copied sucessfully");
} catch (FileNotFoundException e) {
showToast(e.getMessage());
e.printStackTrace();
} catch (IOException e) {
showToast(e.getMessage());
e.printStackTrace();
}
its work for internal move to internal or external storage to external
but cross transferring do not work its throws an error Erofs read only file system
Try some thing like this:
new FileAsyncTask().execute(files);
and
// AsyncTask for Background Process
private class FileAsyncTask extends AsyncTask<ArrayList<String>, Void, Void> {
ArrayList<String> files;
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ActivityName.this, "Your Title", "Loading...");
}
#Override
protected Void doInBackground(ArrayList<String>... params) {
files = params[0];
for (int i = 0; i < files.size(); i++) {
copyFileToSDCard(files.get(i));
} return null;
}
#Override
protected void onPostExecute(Void result) {
dialog.dismiss();
}
}
// Function to copy file to the SDCard
public void copyFileToSDCard(String fileFrom){
AssetManager is = this.getAssets();
InputStream fis;
try {
fis = is.open(fileFrom);
FileOutputStream fos;
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory()+"/MyProject", fileFrom));
byte[] b = new byte[8];
int i;
while ((i = fis.read(b)) != -1) {
fos.write(b, 0, i);
}
fos.flush();
fos.close();
fis.close();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
public static boolean copyFile(String from, String to) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(from);
if (oldfile.exists()) {
InputStream inStream = new FileInputStream(from);
FileOutputStream fs = new FileOutputStream(to);
byte[] buffer = new byte[1444];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
fs.write(buffer, 0, byteread);
}
inStream.close();
fs.close();
}
return true;
} catch (Exception e) {
return false;
}
}
Try this, Replace this line:
File myFile = new File("/storage/sdcard/");
with:
ContextWrapper cw = new ContextWrapper(getApplicationContext());
// path to /data/data/yourapp/app_data/imageDir
File myFile = cw.getDir("imageDir", Context.MODE_PRIVATE);
Check this link, may be helpfull: click here

How to accept multiple socket connection at Java server

I'm trying to implement a client-server pair in Android using standard Java sockets. So far, I've successfully implemented one to one client-server connection. Now, I'm modifying my server side code to accept multiple client connection. I've taken help from here. I'm creating a serverSocket and wait for client connection in an infinite while loop. Once the client side socked is accepted, I run a new thread to handle that client and then again wait for new connection. Unfortunately, the program keeps crashing for some unknown reason! The logcat simply says- "error opening trace file: No such file or directory". The file path is correct (it was working fine in older implementation). Can anyone suggest what am I doing wrong? Is it related to missing manifest permission? Here is what I've done so far:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent launchFileManager = new Intent(getBaseContext(),
FileChooserActivity.class);
startActivityForResult(launchFileManager, REQUEST_CODE); //receives files
//fileArray has been populated here
Button btn=(Button)findViewById(R.id.dispFilesid);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
initializeServer();
}
});
}
private void initializeServer() {
boolean listening = true;
try {
serversocket = new ServerSocket(4444);
} catch (IOException e) {
e.printStackTrace();
Log.d("Listen failed", "Listening to port 4444 failed");
}
while (listening) {
try {
socket = serversocket.accept();
Thread Clienttrd = new Thread(new Runnable() {
#Override
public void run() {
try {
OutputStream myos=socket.getOutputStream();
myos.write(filepathNameArray.size()); //send file count
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!fileArray.isEmpty()) {
for (int i = 0; i < filepathNameArray.size(); i++){
copyFile(fileArray.get(i), fileArray.get(i).getName().toString());
//mtv.setText(fileArray.get(i).getName().toString());
}
}
}
});
Clienttrd.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The intent for FileChooserActivity returns an ArrayList containing a list of file URIs. These URIs are then wrapped around files and written over DataOutputStream of Socket object.
Please help. Any insight would be appreciated! Thanks in advance!
Finally solved the problem. This might help others who land on this page in future. The problem: I was using the same thread for accepting and handling the client connection. So, the server could not become free for listening other incoming connections. I wrote a separate ConnectionHandler class for handling client connection:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Thread trd = new Thread(new Runnable() {
#Override
public void run() {
try {
serversocket = new ServerSocket(4444);
} catch (IOException e) {
e.printStackTrace();
Log.d("Listen failed",
"Listening to port 4444 failed");
}
while (listening) {
try {
socket = serversocket.accept();
Runnable connectionHandler = new ConnectionHandler(
socket, fileArray, filepathNameArray);
new Thread(connectionHandler).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
trd.start();
}
});
ConnectionHandler (This solved my issue):
public class ConnectionHandler implements Runnable {
private Socket socket=null;
private ArrayList<File> fileArray=null;
ArrayList<String> filepathNameArray=null;
public ConnectionHandler(Socket socket, ArrayList<File> fileArray, ArrayList<String> filepathNameArray) {
super();
this.socket = socket;
this.fileArray=fileArray;
this.filepathNameArray=filepathNameArray;
}
#Override
public void run() {
try {
OutputStream myos=socket.getOutputStream();
myos.write(filepathNameArray.size()); //send file count
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!fileArray.isEmpty()) {
for (int i = 0; i < filepathNameArray.size(); i++){
copyFile(fileArray.get(i), fileArray.get(i).getName().toString());
//mtv.setText(fileArray.get(i).getName().toString());
}
}
}
private void copyFile(File file, String name) {
FileInputStream fis;
long filesize = file.length();
try {
fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
#SuppressWarnings("resource")
DataInputStream dis = new DataInputStream(bis);
byte[] mybytearray = new byte[16384];
OutputStream os;
if (socket != null) {
os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(name); // filename is also sent to client
dos.writeLong(filesize); // file size is also sent to client
long z = filesize;
int n = 0;
while ((z > 0)
&& (n = dis.read(mybytearray, 0,
(int) Math.min(mybytearray.length, z))) != -1) {
dos.write(mybytearray, 0, n);
dos.flush();
z -= n;
}
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

android: FileOutputStream Doesn't work

I try to make TCP-Sock program, and this is simple file recv program.
and now, i get some problem.
i think my client program's FileOutputStream class doesn't work.
below code is what i've made.
package kr.ac.cbnu.incping.tcp_cloud;
public class DownActivity extends Activity {
public static int contentNum;
public static String body=new String();
public static String fName=new String();
public static int fSize;
public static synchronized String getFilePath(String userID, String fName)
{
String sdcard = Environment.getExternalStorageState();
File file = null;
if ( !sdcard.equals(Environment.MEDIA_MOUNTED))
{
// SDcard isn't mount
file = Environment.getRootDirectory();
}
else
{
// SDcard is mount
file = Environment.getExternalStorageDirectory();
}
String dir = file.getAbsolutePath() + String.format("/tcp_cloud/%s",userID);
String path = file.getAbsolutePath() + String.format("/tcp_cloud/%s/%s",userID,fName);
file = new File(dir);
if ( !file.exists() )
{
// Make directory if dir doesn't exist
file.mkdirs();
}
// return File Path;
return path;
}
public void connect()
{
try{
Socket socket=new Socket(MainActivity.servIP, MainActivity.servPort);
DataOutputStream dos;
DataInputStream dis;
dis=new DataInputStream(socket.getInputStream());
dos=new DataOutputStream(socket.getOutputStream());
byte[]flag=new byte[3];
byte[]num=new byte[1];
byte[]uID=new byte[17];
String path=new String();
path=getFilePath(LoginActivity.usrName,fName);
File f=new File(path);
flag="05".getBytes("EUC_KR");
num=Integer.toHexString(contentNum).getBytes("EUC_KR");
uID=LoginActivity.usrName.getBytes("EUC_KR");
dos.write(flag);
dos.flush();
dos.write(num);
dos.flush();
dos.write(uID);
dos.flush();
FileOutputStream fos=new FileOutputStream(f);
Toast.makeText(getApplicationContext(),path,Toast.LENGTH_LONG).show();
BufferedOutputStream bos=new BufferedOutputStream(fos);
dos=new DataOutputStream(bos);
int len;
int size = 512;
byte[] data = new byte[size];
while ((len = dis.read(data,0,size))!=-1)
{
dos.write(data);
}
dos.flush();
Toast.makeText(getApplicationContext(),path+" saved",Toast.LENGTH_LONG).show();
dos.close();
bos.close();
fos.close();
dos.close();
dis.close();
socket.close();
}catch (Exception e){
e.printStackTrace();
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_down);
String title=new String();
if(contentNum==0)
title=LoginActivity.title1;
else if(contentNum==1)
title=LoginActivity.title2;
else if(contentNum==2)
title=LoginActivity.title3;
else if(contentNum==3)
title=LoginActivity.title4;
else if(contentNum==4)
title=LoginActivity.title5;
TextView bodytit=(TextView) findViewById(R.id.bodyTitle);
TextView bodydat=(TextView) findViewById(R.id.bodyBody);
Button filedat=(Button) findViewById(R.id.filename);
bodytit.setText(title);
bodydat.setText(body);
filedat.setText(fName+"(size: "+fSize+")");
filedat.setOnClickListener(new OnClickListener(){
public void onClick(View v){
connect();
}
});
}}
and this code is troubled code
FileOutputStream fos=new FileOutputStream(f);
Toast.makeText(getApplicationContext(),path,Toast.LENGTH_LONG).show();
BufferedOutputStream bos=new BufferedOutputStream(fos);
dos=new DataOutputStream(bos);
toast message is just prob message. when placed toast above of the FOS, toast working well.
but toast isn't working in that position
i can't solve this problem. please, somebody help me..T.T
*i'm not english language area's person. so my english isn't nice sentence. i'm sorry about that;)
In my case FileOutputStream and OutputStreamWriter is not works.
So I was changed File classes to this.
FileWriter fileOut = new FileWriter(fileFullPath, false);
String jsonString = new Gson().toJson(json);
fileOut.write(jsonString);
fileOut.close();

Socket - Address already in use

I'm new to Socketand I try to code an Server and Client on the same application just to see how it work.
Code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button)this.findViewById(R.id.bouton1)).setOnClickListener(this);
}
public void onClick(View v) {
TCPServer server = new TCPServer();
TCPClient client = new TCPClient();
server.start();
client.start();
}
public class TCPServer extends Thread {
#Override public void run() {
try {
ServerSocket s = new ServerSocket(8080,0,InetAddress.getLocalHost());
Socket cli = s.accept();
byte[] b = new byte[512];
int n;
InputStream is = cli.getInputStream();
while((n=is.read(b))>0){
Log.d("TCPServer",new String(b));
if(new String(b).contains("\r\n\r\n"))break;
b = new byte[512];
}
OutputStream os = cli.getOutputStream();
os.write("Hello".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class TCPClient extends Thread {
#Override public void run() {
try {
Socket s = new Socket(InetAddress.getLocalHost().getHostAddress(),8080);
//Socket s = new Socket("www.google.com",80);
//Log.i("",s.getLocalAddress().getHostAddress());
byte[] b = new byte[512];
int n;
if (s.isConnected()) {
OutputStream os = s.getOutputStream();
os.write("Hi How are you \r\n\r\n".getBytes());
InputStream is = s.getInputStream();
while((n=is.read(b))>0){
Log.d("TCPClient",new String(b));
b = new byte[512];
}
}
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The code work fine but just for the first time I click my button.
the error is java.net.BindException: Address already in use .
If it works the first time, but not after that it sounds like you aren't closing your socket correctly before your program exits.
You can check to see if it's still open by running
netstat
pending your not on a windows machine. I'm sure they have something similar.

Categories

Resources