Android Studio 连接到 Socket 服务器

Posted

技术标签:

【中文标题】Android Studio 连接到 Socket 服务器【英文标题】:Android Studio Connect to Socket server 【发布时间】:2021-08-12 08:30:40 【问题描述】:

我有一个使用 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;



如您所见,客户端发送 2 个值并接收 1 个,第一个用于切换,这将指示要执行的内容,现在我只有 on 选项(检查 ddbb 中是否存在电子邮件),第二个值是电子邮件,因为代码已经进入开关。

服务器完全正常工作,我已经在 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");
  

现在我想做的是在 Android Studio 中执行相同的客户端,以便它可以连接到服务器。

我试过了:

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);


当我运行它时,它不会给我任何错误,但是如果我在 doInBackground 底部记录套接字值以查看套接字值,它会说它是空的。

我也尝试过使用 Thread 和 Handle,但我无法得到服务器返回给我的主线程的结果。

【问题讨论】:

【参考方案1】:

根据 RFC 1918,192.168.0.0-192.168.255.255 范围内的地址是私有的。此类地址可以在任何网络内部使用,因此它们经常在组织内部使用。它们不能在 Internet 上使用,因为它们不是唯一的。 Why my ip address starts with 192.?

我认为您的本地网络以某种方式阻止了该连接。但没有进一步的细节,据我所知,没有人能真正说出。

如果您在同一台计算机上运行所有内容,您可能需要查看“环回”地址。通常是 127.0.0.1 ,应该循环回你的机器。

如果您想运行完整的服务器,您可能需要更深入地研究网络并想了解网络的运作方式。

【讨论】:

我现在刚刚尝试使用我的公共 IP 打开端口并将 AsyncTask 主机方向更改为:83.**.**.**:5010 但它不起作用,它没有执行该方法仍然将套接字服务器保留为空。 你从哪里得到 83.xx.xx.xx:5010? 这是我的公网IP,所以我把它换成了'x'。 现在它可以工作了,我尝试使用我的本地 IP 地址 (192.168.1.5) 并且也可以工作!这不是知识产权问题。您可以使用 192.x.x.x、127.0.0.1 (localhost) 和公共地址。您可以在whatismyipaddress.com 找到您的,只是不要忘记在您的路由器中打开正确的端口!【参考方案2】:

我设法解决了这个问题。我刚刚在 Android Studio 的“连接”类中创建了一个线程。

在“连接”中,我有一些类级变量,我与线程一起使用(线程无法修改创建线程的方法中的变量,但它可以读取类级变量)所以线程本身使与套接字服务器的连接,并将取值保存到类级变量中。

在主线程中(在调用线程的同一方法中)我使用了一个循环来查看线程状态,如果它已完成,则读取变量并将其应用到我想要的位置。

代码如下:

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

我认为另一种可能性是让线程只进行连接(以及另一个用于关闭它)并将套接字保存为类级变量,这样您就可以从主线程发送和接收,我没有尝试还是这样。

【讨论】:

以上是关于Android Studio 连接到 Socket 服务器的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Android 手机连接到 Visual Studio Code?

从 Android Studio 连接到 SQL Server 2014

Android Studio 错误:无法连接到守护进程

最近的 Android Studio 无法连接到 Firebase?

如何将 Visual Studio 2015 Android 模拟器连接到网络?

无法使用 android studio 连接到“xampp server localhost”