简体   繁体   English

Android Studio 连接到Socket服务器

[英]Android Studio Connect to Socket server

I have a server running in Java using Eclipse (Here the full code):我有一台使用 Eclipse 在 Java 中运行的服务器(这里是完整代码):

public class Main {

public static void main(String[]args) {
    
    // BBDD connection var
    Connection con = null;
    
    // Sockets
    ServerSocket server = null;
    try {
        server = new ServerSocket(5010);
    } catch (IOException e2) {System.out.println("Error at creating server, check if the port is in use");System.exit(-1);}
    
    /*** MySQL driver loading***/
    try {
        Class.forName("com.mysql.jdbc.Driver");
        System.out.println("MySQL driver is UP");
    } catch (ClassNotFoundException e1) {System.out.println("Error loading MySQL driver");}
    
    /*** Stablishing connection with the ddbb ***/
    try {
        con= (Connection) DriverManager.getConnection("jdbc:mysql://IP/Database", "username", "password");
        System.out.println("Connection stablished");
    } catch (SQLException e) {
        System.out.println("SQL ERROR");
        e.printStackTrace();
    }
    
    /*** Assigning thread for client ***/
    System.out.println("Listening for new requests...");
    while (true) {
        
        try {
            Socket clientSocket;
            clientSocket = server.accept();
            System.out.println("Connection stablished");
            
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
            
            ThreadForClient client = new ThreadForClient(con, clientSocket, dis, dos);

            Thread thread = new Thread(cliente);
            thread .start();
        } catch (IOException e) {System.out.println("Error making client socket");}
    }
}

class ThreadForClient implements Runnable {

Connection con;
Socket clientSocket;
DataInputStream dis;
DataOutputStream dos;

public ThreadForClient(Connection con, Socket s, DataInputStream dis, DataOutputStream dos) {
    this.con = con;
    this.clientSocket = s;
    this.dis = dis;
    this.dos = dos;
 }

@Override
public void run() {

    try {
        int opc = dis.readInt();
        switch (opc) {
            case 1:
                String email = dis.readUTF();
                Boolean result = existeUsuario(email);
                dos.writeBoolean(result);
                break;
            default: break;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public Boolean userExists(String email) throws SQLException { // 1
    
    email = email.toLowerCase();
    Statement stmt;
    stmt = con.createStatement();
    ResultSet rs=stmt.executeQuery("select * from users where email = '"+email+"'");
    boolean result = rs.first();
    return result;
}

}

As you can see, the client sends 2 values and receives 1, the first one is for the switch, which will indicate what to exceute, for now I just have on option (checking if email exists in the ddbb), the second value is the email as the code has already entered the switch.如您所见,客户端发送2个值并接收1个,第一个用于切换,这将指示要执行的操作,现在我只有on选项(检查ddbb中是否存在email),第二个值是email 作为代码已经进入开关。

The server is fully working and I already tested it with a Client Test project in Eclipse (It is what I want to do in Android Studio):服务器完全正常工作,我已经在 Eclipse 中使用客户端测试项目对其进行了测试(这是我想在 Android Studio 中执行的操作):

public static void main(String[] args) {
    
    Socket socket = null;
    try {
        socket = new Socket(HOST, PORT);
        System.out.println("Conection succesful");
        
        DataOutputStream dos;
        DataInputStream dis;
        
        dos = new DataOutputStream(socket.getOutputStream());
        dis = new DataInputStream(socket.getInputStream());
        

        dos.writeInt(1);
        dos.writeUTF("email@example.com");
        
        Boolean bool = dis.readBoolean();
        if (bool) {
            System.out.println("Email exists in the BBDD.");
        } else {
            System.out.println("Email does not exist in the BBDD.");
        }
        
        socket.close();
        
    } catch (Exception e) {System.out.println("Server connection failed");}
  
}

Now what I want to do is doing the same client in Android Studio so it can connect to the server.现在我要做的是在 Android Studio 中执行相同的客户端,以便它可以连接到服务器。

I tried this:我试过这个:

public class SocketConnection {

UserExists ue;

public SocketConnection() throws IOException {
    connect();
}

public void connect() {
   
    ue = new UserExists();
    ue.execute();

}
}

class UserExists extends AsyncTask<Void, Void, Void> {

int PORT = 5010;
String HOST = "192.168.1.5";
private Socket socket;

private DataOutputStream dos;
private DataInputStream dis;

@Override
protected Void doInBackground(Void... voids) {
    try {
        socket = new Socket(HOST, PORT);
        dos = new DataOutputStream(socket.getOutputStream());
        dis = new DataInputStream(socket.getInputStream());
    } catch (Exception e) {
        System.out.println("Socket error");
        e.printStackTrace();
    }
    return null;
}

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
}
}

When I run it it does not give me any error but if I log the socket value at doInBackground's bottom to see the socket value, it says it is null.当我运行它时,它不会给我任何错误,但是如果我在 doInBackground 底部记录套接字值以查看套接字值,它会说它是 null。

I also tried using Thread and Handle but I can't get the result the server gives me back to the main thread.我也尝试使用 Thread 和 Handle,但我无法得到服务器将结果返回给主线程。

According to RFC 1918, addresses in the 192.168.0.0-192.168.255.255 range are private.根据 RFC 1918,192.168.0.0-192.168.255.255 范围内的地址是私有的。 Such addresses can be used internally by any network so they're often used inside an organization.这样的地址可以在任何网络内部使用,因此它们经常在组织内部使用。 They cannot be used on the Internet since they aren't unique.它们不能在 Internet 上使用,因为它们不是唯一的。 Why my ip address starts with 192.? 为什么我的 ip 地址以 192 开头。?

I think that your local network is somehow preventing that connection.我认为您的本地网络以某种方式阻止了该连接。 But without further details nobody can actually tell as far I know.但没有进一步的细节,据我所知,没有人能真正说出。

If you are running everything on the same computer you may want to take a look at "loopback" address.如果您在同一台计算机上运行所有内容,则可能需要查看“环回”地址。 Usually 127.0.0.1, that should loop back to your machine.通常是 127.0.0.1,它应该循环回你的机器。

If you want to run a full server you may need to dig more into networking and want to understand how networks function.如果你想运行一个完整的服务器,你可能需要更多地研究网络,并想了解 function 是如何网络的。

I managed to resolve this.我设法解决了这个问题。 I just made a thread inside a "Connection" class in Android Studio.我刚刚在 Android Studio 的“连接”class 中创建了一个线程。

Inside "Connection" I have some class-level variables, which I use with the thread (The thread can't modify variables in the method the thread was created but it can read class-level variables) so the thread itself makes the connection with the socket server and saves the value taken to also a class-level variable.在“连接”中,我有一些类级变量,我与线程一起使用(线程无法修改创建线程的方法中的变量,但它可以读取类级变量),因此线程本身与套接字服务器并将取值保存到类级变量中。

In the main thread (in the same method that called the thread) I used a loop that looks at the thread status, if it has finished, reads the variable and applies it where I want.在主线程中(在调用线程的同一方法中)我使用了一个循环来查看线程状态,如果它已完成,则读取变量并将其应用到我想要的位置。

Here the code:这里的代码:

public class Connection{

private String HOST = "83.xx.xx.xx";
private int PORT = 5010;

private Socket socket;

private DataOutputStream dos;
private DataInputStream dis;

boolean result;
String email;

public boolean userExists(String dev) throws InterruptedException { // true = exists, false = does not exist. dev is the email to search
    this.email = dev;
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                socket = new Socket(HOST, PORT);
                dos = new DataOutputStream(socket.getOutputStream());
                dis = new DataInputStream((socket.getInputStream()));
                dos.writeInt(1); // 1 = Sends the option for telling the server that we want to search a user
                dos.writeUTF(email); //Sends the email
                result = dis.readBoolean(); // Recieve if email exists or not
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("Couldn't connect to server");
            }
        }
    });
    thread.start();
    for (int c=0; c<25; c++){ //Wait for the thread to end
        if (thread.isAlive()) {
            //Thread hasn't finished yet...
            Thread.sleep(100);
        } else if (c == 24) {
            //This would be a timeout
            result = false;
        } else {
            //Thread has finished
            break;
        }
    }
    return result; // true in case server found the email, false in case it doesn't or in case of a timeout
}

I think another possibility could be making the thread just do the connection (and another one for closing it) and saving the socket as class-level variable, so you can send and receive from the main thread, I didn't try it tho.我认为另一种可能性可能是让线程只进行连接(以及另一个用于关闭它)并将套接字保存为类级变量,这样您就可以从主线程发送和接收,我没有尝试过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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