3

I am transfer files using socket from Android to Android using WiFi Direct. I am starting service for sending files in following code

        String[] filesPath = data.getStringArrayExtra("all_path");
        Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
        serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
        serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, filesPath);
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS, info.groupOwnerAddress.getHostAddress());
        serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
        getActivity().startService(serviceIntent);

Service code is:

 @Override
protected void onHandleIntent(Intent intent)
{

    Context context = getApplicationContext();
    if (intent.getAction().equals(ACTION_SEND_FILE))
    {
        //String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
        String[] files = intent.getExtras().getStringArray(EXTRAS_FILE_PATH);
        String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
        Socket socket = new Socket();
        int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);

        try
        {
            Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
            socket.bind(null);
            socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);

            Log.d(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());

            ArrayList<File> filesList = new ArrayList<File>();
            for (String file : files)
            {
                filesList.add(new File(Uri.parse("file://" + file).getPath()));
            }
            send(filesList, socket);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            Log.e(WiFiDirectActivity.TAG, e.getMessage());
        }
        finally
        {

            if (socket.isConnected())
            {
                try
                {
                    socket.close();
                }
                catch (IOException e)
                {
                    // Give up
                    e.printStackTrace();
                }
            }
        }
    }
}

Sending files method:

public void send(ArrayList<File> files, Socket socket)
{
    try
    {
        //DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        System.out.println(files.size());
        //write the number of files to the server
        dos.writeInt(files.size());
        dos.flush();
        //write file names
        for (File file1 : files)
        {
            dos.writeUTF(file1.getName());
            dos.flush();
        }
        //buffer for file writing, to declare inside or outside loop?
        int n;
        byte[] buf = new byte[1024 * 8];
        //outer loop, executes one for each file
        for (File file : files)
        {
            System.out.println(file.getName());
            FileInputStream fis = new FileInputStream(file);
            dos.writeLong(file.length());
            dos.flush();
            while ((n = fis.read(buf)) != -1)
            {
                dos.write(buf, 0, n);
                dos.flush();
            }
        }
        dos.close();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

Receiving side code is:

@Override
    protected String doInBackground(Void... params)
    {
        try
        {
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(8988));
            //ServerSocket serverSocket = new ServerSocket(8988);
            Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
            Socket client = serverSocket.accept();
            Log.d(WiFiDirectActivity.TAG, "Server: connection done");
            receive(client);
            return "";
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }

    public void receive(Socket socket)
    {
        try
        {
            DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
            //read the number of files from the client
            int number = dis.readInt();
            ArrayList<File> files = new ArrayList<File>(number);
            System.out.println("Number of Files to be received: " + number);
            //read file names, add files to arraylist
            for (int i = 0; i < number; i++)
            {
                File file = new File(dis.readUTF());
                files.add(file);
            }
            int n;
            byte[] buf = new byte[1024 * 8];

            for (File file : files)
            {
                System.out.println("Receiving file: " + file.getName());
                final File f = new File(Environment.getExternalStorageDirectory() + "/WiFiDirect/" + file.getName());
                File dirs = new File(f.getParent());
                if (!dirs.exists())
                {
                    dirs.mkdirs();
                }
                f.createNewFile();
                FileOutputStream fos = new FileOutputStream(f);
                long fileSize = dis.readLong();
                while (fileSize > 0 && (n = dis.read(buf, 0, (int) Math.min(buf.length, fileSize))) != -1)
                {
                    fos.write(buf, 0, n);
                    fileSize -= n;
                }
                fos.close();
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (socket.isConnected())
            {
                try
                {
                    socket.close();
                }
                catch (IOException e)
                {
                    // Give up
                    e.printStackTrace();
                }
            }
        }
    }

All the code is working fine and when I launch app on both app for first time, files transferred successfully. But in second time files transferring failed on receiving side,

            ServerSocket serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(8988));

Third line from above code serverSocket.bind(new InetSocketAddress(8988)); throws exception java.net.BindException: bind failed: EADDRINUSE (Address already in use) How to resolve this exception? Any suggestion will be appreciated. Thanks

NASSER
  • 5,900
  • 7
  • 38
  • 57
  • 1
    Why do you `bind()` the _client_ socket at all? – fge Oct 30 '14 at 07:03
  • @fge I was using 'ServerSocket serverSocket = new ServerSocket(8988);' before this but i setReuseAddress to true but failed – NASSER Oct 30 '14 at 07:06
  • @fge Is there any issue ragarding service? because I am starting service every time to send files but not stop it, is there any need to stop the service before sending again? if yes then what is the best way to do that? – NASSER Oct 30 '14 at 07:08
  • I think you might [need to do `socket.shutdownOutput()`](http://stackoverflow.com/a/4623091/1270789) before `socket.close()` on the client size. – Ken Y-N Oct 30 '14 at 07:14
  • @ KenY-N socket.shutdownOutput() is not working. – NASSER Oct 30 '14 at 07:27
  • @KenY-N No. `socket.close()` sends a FIN if it hasn't already been sent. – user207421 Oct 30 '14 at 07:34
  • 1
    I solved the issue. I was closing client socket on server side after receiving all the files but server socket should be close. i-e serverSocket.close(); – NASSER Oct 30 '14 at 09:21
  • 1
    No, the server socket should be closed when you want to exit the program, no tnjustbwhen you've finished with one client. You'd be far better off fixing your server so it can handle more than one client per execution. – user207421 Oct 30 '14 at 20:32

1 Answers1

5

I am starting service every time to send files but not stop it, is there any need to stop the service before sending again?

Yes, of course there is, otherwise it is still listening at port 8988, so you can't start another instance.

if yes then what is the best way to do that?

Kill the old one. But why are you starting it when it's already running?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    How can I reuse the running service to send files again? Can you help me about this, any code.. – NASSER Oct 30 '14 at 07:43
  • Just put a loop around the accept/receive code, and if you want it concurrent start a thread per accepted socket. NB the `isConnected()` tests are futile. If the socket exists it must be closed. – user207421 Oct 30 '14 at 08:01