简体   繁体   中英

Android Client/ Laptop Server

I'm trying to create a client/server application where, a laptop acts like server and share its internet connection with an android phone that acts like client, I can enstablish the connection between client and server, the problem is that when the client try to write on the socket, it get stuck there. This is the android xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.giuseppe.client">
<uses-permission android:name="android.permission.INTERNET" >
</uses-permission>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

This is the android client

package com.example.giuseppe.client;

import java.io.*;
import java.net.*;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;


import org.w3c.dom.Text;

import static java.net.InetAddress.*;

public class MainActivity extends Activity {
    private Socket socket;
    private static final int port=5555;
private static final String addr="192.168.1.37";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Client()).start();
}

public void onClick(View view){
    try{
        TextView tx=(TextView) findViewById(R.id.txt);

        EditText et= (EditText) findViewById(R.id.et);
        String str= et.getText().toString();
        DataOutputStream out= new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())) ;
        out.writeUTF(str);
        out.close();
        socket.close();

    }catch(UnknownHostException e){
        e.printStackTrace();
    }catch (IOException e){
        e.printStackTrace();
    }catch (Exception e){
        e.printStackTrace();
    }
}

class Client implements Runnable {
    @Override
    public void run() {
        try {
            TextView tx= (TextView) findViewById(R.id.txt);
            tx.setText("Before connection");
            InetAddress server = InetAddress.getByName(addr);
            socket = new Socket("192.168.1.37", port);
            tx.setText("After connection");
        } catch (UnknownHostException a) {

        } catch (IOException a) {

        } catch (Exception a){

        }
    }
}

This is the server code

 import java.io.*;
 import java.net.*;
public class Server {

public static void main(String[] args) {
    int port=5555;
    byte[] buff =new byte[1024];
    String str; 
    // TODO Auto-generated method stub
    try {
        ServerSocket server=new ServerSocket(port);
        System.out.println("Before accept");
        Socket client=server.accept(); 
        System.out.println("After accept");
        DataInputStream in=new DataInputStream(new BufferedInputStream(client.getInputStream()));
        str=in.readUTF();


        System.out.println("Message received");
        in.close();
        client.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
}

}

I suppose the problem is in the client because I also tried to use the server to send a string and while the server send it, the client doesn't receive it. Sorry for my bad english. Thanks to all

+++++EDIT+++++

I tried also OutputStream out=socket.getOutputStream(); and then out.write(str.getBytes()), but in this case it get stuck here, when I try to write in the socket, could be any android's configuration the problem?

Disclaimer: I cannot validate the correctness of your Android code so I am assuming that is fine, and only commenting on your networking code, which is the root cause of your issue.

2 main problems in your code are:

  1. In your server code you are reading and reading, and doing nothing
  2. Your server is single threaded

You main problem is #1 above and as soon as you resolve your #1, you will get another problem which is #2.

Your #1 problem is that you need to define some logic on how you want to consider the end of stream or input, refer below code example ( read the comments in the code ), also you don't necessarily need to use readUTF method, instead you can use " I/O bridge classes " like InputStreamReader which acts as a bridge between your byte stream and character stream , so you can use InputStreamReader clientSocketReader = (new InputStreamReader(clientSocket.getInputStream(), "UTF8")); , and I cannot say why you really need DataInputStream and can't use a InputStreamReader but in my opinion you can go for using a bridge class.

    int portNumber = 8001;
    try {
        ServerSocket serverSocket = new ServerSocket(portNumber);
        Socket clientSocket = serverSocket.accept();
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) { // **** this basically means that read one full line, you have to specify condition like this, so suppose you have created a telnet session with this server now keep on typing and as soon you will hit entered then while block processing will start. 
            System.out.println("@@@ " + inputLine);
            out.println(inputLine); // *** here same input is written back to the client, so suppose you have telnet session then same input can be seen
        }
    } catch (IOException e) {
        System.out.println(
                "Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
        System.out.println(e.getMessage());
    }

Now your #2 problem is that your server is single threaded, you need to have a multi-threaded server which basically means that you should process each client request in a new thread. Read this answer of mine which throws more light on single threaded v/s multi-threaded server. See below code example for a multi-threaded server:

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import com.learn.Person;

/**
 * @author himanshu.agrawal
 *
 */
public class TestWebServer2 {

    public static void main(String[] args) throws IOException {
        startWebServer();
    }

    /**
     * test "backlog" in ServerSocket constructor
test -- If <i>bindAddr</i> is null, it will default accepting
     * connections on any/all local addresses.
     * @throws IOException
     */

    private static void startWebServer() throws IOException {
        InetAddress address = InetAddress.getByName("localhost");
        ServerSocket serverSocket = new ServerSocket(8001, 1, address);
        // if set it to 1000 (1 sec.) then after 1 second porgram will exit with SocketTimeoutException because server socket will only listen for 1 second.
        // 0 means infinite
        serverSocket.setSoTimeout(/*1*/0000);

        while(true){
            /*Socket clientSocket = serverSocket.accept();*/ // a "blocking" call which waits until a connection is requested
            System.out.println("1");
            TestWebServer2.SocketThread socketThread = new TestWebServer2().new SocketThread();
            try {
                socketThread.setClientSocket(serverSocket.accept());
                Thread thread = new Thread(socketThread);
                thread.start();
                System.out.println("2");
            } catch (SocketTimeoutException socketTimeoutException) {
                System.err.println(socketTimeoutException);
            }
        }

    }

    public class SocketThread implements Runnable{

        Socket clientSocket;

        public void setClientSocket(Socket clientSocket) throws SocketException {
            this.clientSocket = clientSocket;
            //this.clientSocket.setSoTimeout(2000); // this will set timeout for reading from client socket.
        }

        public void run(){
            System.out.println("####### New client session started." + clientSocket.hashCode() + " | clientSocket.getLocalPort(): " + clientSocket.getLocalPort()
                    + " | clientSocket.getPort(): " + clientSocket.getPort());
            try {
                listenToSocket(); // create this method and you implement what you want to do with the connection.
            } catch (IOException e) {
                System.err.println("#### EXCEPTION.");
                e.printStackTrace();
            }
        }


    }

}

That is an Art Producer / Consumer Problem. After the Server return from accept , the Client has an etablished Connection to the Server. While the Sever is waiting for data to read (Consumer) , The Client (Producer ) is doing nothing. The Client should write something on The Socket In order to continue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM