简体   繁体   English

安卓聊天客户端:socket连接

[英]Android chat client: socket connection

im new to Android.我是 Android 新手。 First I wrote a Chat_Client and Server in Java.首先,我用 Java 编写了一个 Chat_Client 和服务器。 It works great.它工作得很好。

Then i tried to convert it to an working Android app, I always get the message "Cannot connect to the Server! Try again!"然后我尝试将其转换为可运行的 Android 应用程序,但总是收到消息“无法连接到服务器!再试一次!” so it's obviously something wrong with the Socket connection attempt, but I can't figure out what it is.所以很明显 Socket 连接尝试有问题​​,但我无法弄清楚它是什么。

Background knowledge:背景知识:
- Im connected to my root server and take a look at the chat_server process. - 我连接到我的根服务器并查看 chat_server 进程。 It's running!它在运行!
- I tried to connect from an other chat_client on my PC to the chat_server. - 我试图从我 PC 上的其他 chat_client 连接到 chat_server。 It works!有用!
- The host and the port are the right one. - 主机和端口是正确的。 Checked it a few times.检查了几次。
- Permissions are set <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> - 权限设置<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
- I can run the app on my Nexus 5 - 我可以在我的 Nexus 5 上运行该应用程序
- There are no Errors listed in LogCat or the Console, it seems like it run normally.. - LogCat 或控制台中没有列出错误,看起来它运行正常..

My chat_client code:我的 chat_client 代码:

package de.Voldemord.chatter;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class MainActivity extends Activity implements OnClickListener{
    private Button btn;
    private EditText et_send;
    private EditText et_chat;
    private String s_username = "Voldemord", s_host = "www.example.com";         // !Example host!
    private int s_port = 2222;                                                   // !Example port!
    private Socket socket = null;
    private BufferedReader in;
    private PrintWriter out;
    @SuppressWarnings({ "unchecked", "rawtypes" })
    ArrayList<String> users = new ArrayList();
    boolean isConnected = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et_send = (EditText) findViewById(R.id.sendTextView);
    et_chat = (EditText) findViewById(R.id.chatTextView);

    btn = (Button) findViewById(R.id.btn);
    btn.setOnClickListener(this);


    if (isConnected == false){
        try{
            socket = new Socket(InetAddress.getByName(s_host), s_port);
            InputStreamReader streamreader = new InputStreamReader(socket.getInputStream());
            in = new BufferedReader(streamreader);
            out = new PrintWriter(socket.getOutputStream());
            out.println(s_username + ":has connected.:Connect");
            out.flush(); 
            isConnected = true; 
        }catch (Exception ex){
            et_chat.append("Cannot Connect! Try Again. \n"+ socket);
        }

        ListenThread();

    }else if (isConnected == true){
        et_chat.append("You are already connected. \n");
    }

}

protected void onDestroy(){
    super.onDestroy();
    sendDisconnect();
    Disconnect();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onClick(View v) {   
    String nothing = "";
    if ((et_send.getText()).equals(nothing)) {
        et_send.setText("");
        et_send.requestFocus();
    } else {
        try {
           out.println(s_username + ":" + et_send.getText() + ":" + "Chat");
           out.flush(); // flushes the buffer
        } catch (Exception ex) {
            et_chat.append("Message was not sent. \n");
        }
        et_send.setText("");
        et_send.requestFocus();
    }

    et_send.setText("");
    et_send.requestFocus();
}

public void sendDisconnect(){
    String bye = (s_username + ": :Disconnect");
    try{
        out.println(bye);
        out.flush();
    }catch (Exception e){
        et_chat.append("Could not send Disconnect message.\n");
    }
}

public void Disconnect(){
    try{
        et_chat.append("Disconnected.\n");
        socket.close();
    }catch (Exception e){
        et_chat.append("Failed to disconnect.\n");
    }
    isConnected = false;
}

public void ListenThread(){
    Thread IncomingReader = new Thread(new IncomingReader());
    IncomingReader.start();
}

public void userAdd(String user){
    users.add(user);
}

public void userRemove(String user){
    et_chat.append(user + " is now Offline.\n");
}

public class IncomingReader implements Runnable{
    @Override
    public void run(){
        String[] data;
        String stream, done = "Done", connect = "Connect", disconnect = "Disconnect", chat = "Chat", shutdown = "Shutdown";

        try{
            while ((stream = in.readLine()) != null){
                 data = stream.split(":");

                 if(data[data.length-1].equals(shutdown)){ 
                    if(data[0].equals("Server")){
                        et_chat.append("Server: The Server is Shutting down!\n");
                    }
                    sendDisconnect();
                    Disconnect();
                 }else if (data[data.length-1].equals(chat)){
                    et_chat.append(data[0] + ": " + extract(stream) + "\n");
                   // et_chat.setCaretPosition(et_chat.getDocument().getLength());
                 }else if (data[data.length-1].equals(connect)){
                    userAdd(data[0]);
                 }else if (data[data.length-1].equals(disconnect)){
                     userRemove(data[0]);
                 }else if (data[data.length-1].equals(done)){
                    users.clear();
                 }
            }
       }catch(Exception ex){ 

       }
    }

    private String extract(String input) {
        for(int i=0;i<input.length();i++){
            if(input.charAt(i) == ':'){
                input =  input.substring(i+1,input.length()-5);
                break;
            }
        } 
        return input;
    }
}


}  

My root_chat_server code:我的 root_chat_server 代码:

import java.awt.EventQueue;
import java.io.*;
import java.net.*;
import java.util.*;

public class root_Chat_Server{
    private ServerStart serverStart;
    private boolean isStarted = false;
    private Thread starter;

@SuppressWarnings("rawtypes")
ArrayList clientOutputStreams;
@SuppressWarnings("rawtypes")
ArrayList clientHandler;
ArrayList<String> users;
/**
 * Create the application.
 */

 public class ClientHandler implements Runnable{
       BufferedReader reader;
       Socket sock;
       PrintWriter client;

       public ClientHandler(Socket clientSocket, PrintWriter user){
            client = user;
            try{
                sock = clientSocket;
                InputStreamReader isReader = new InputStreamReader(sock.getInputStream());
                reader = new BufferedReader(isReader);
            }
            catch (Exception ex){
                System.out.print("Unexpected error... \n");
            }
       }

       @Override
       public void run(){
            String message, connect = "Connect", disconnect = "Disconnect", chat = "Chat" ;
            String[] data;

            try{
                while ((message = reader.readLine()) != null){
                    System.out.print("Received: " + message + "\n");
                    data = message.split(":");

                    for (String token:data){
                        System.out.print(token + "\n");
                    }

                    if (data[data.length-1].equals(connect)){
                        tellEveryone((data[0] + ":" + data[1] + ":" + chat));
                        userAdd(data[0]);
                    }else if (data[data.length-1].equals(disconnect)){
                        tellEveryone((data[0] + ":has disconnected." + ":" + chat));
                        userRemove(data[0]);
                    }else if (data[data.length-1].equals(chat)){
                        System.out.print("\n\n"+ message +"\n\n");
                        tellEveryone(message);
                    }else{
                        System.out.print("No Conditions were met. \n");
                    }
                } 
             }catch (Exception ex){
                System.out.print("Lost a connection. \n");
                ex.printStackTrace();
                clientOutputStreams.remove(client);
             } 
       }
       public void stop() throws IOException{
           sock.close();
       }
 }

public root_Chat_Server() {

}

private void start(){
    if(!isStarted){
        starter = new Thread(serverStart = new ServerStart());
        starter.start();

        System.out.print("Server started...\n");
        isStarted = true;
    }
}


private void stop(){
    try{
        tellEveryone("Server:Shutdown");
        Thread.sleep(2000);
        serverStart.stop();
        isStarted = false;
    }catch (InterruptedException | IOException ex){
        Thread.currentThread().interrupt();
    }
    System.out.print("Server is stopping...\n\n\n");
}

private void users(){
    System.out.print("\nOnline Users:\n");

    for(String current_users : users){
        System.out.print("-" + current_users + "\n");
    }
}

public class ServerStart implements Runnable{
    ServerSocket serverSock;
    Socket clientSock;
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void run(){
        clientOutputStreams = new ArrayList();
        users = new ArrayList();  
        clientHandler = new ArrayList();
        ClientHandler clientHand;

        try{
            serverSock = new ServerSocket(2222);

            while (true){
                clientSock = serverSock.accept();
                PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
                clientOutputStreams.add(writer);

                Thread listener = new Thread(clientHand = new ClientHandler(clientSock, writer));
                clientHandler.add(clientHand);
                listener.start();
                System.out.print("Got a connection. \n");
            }
        }catch (Exception ex){
            System.out.print("Error making a connection. \n");
        }
    }

    private void stop() throws IOException{
        if(serverSock != null && clientSock != null){
            serverSock.close();
            clientSock.close();
        }else if(serverSock != null){
            serverSock.close();
        }
    }
}

public void userAdd (String data){
    String message, add = ": :Connect", done = "Server: :Done", name = data;
    if(!users.contains(name)){
        System.out.print("Before " + name + " added. \n");
        users.add(name);
        System.out.print("After " + name + " added. \n");
        String[] tempList = new String[(users.size())];
        users.toArray(tempList);

        for (String token:tempList){
            message = (token + add);
            tellEveryone(message);
        }
        tellEveryone(done);
    }else{
        PrintWriter writer = (PrintWriter)clientOutputStreams.get(clientOutputStreams.size()-1);
        ClientHandler clientHand = (ClientHandler)clientHandler.get(clientHandler.size()-1);
        writer.println("Disconnect:Shutdown");
        writer.flush();
        try {
            clientHand.stop();
        } catch (IOException e) {
            e.printStackTrace();
        }
        clientHandler.remove(clientHandler.size()-1);
        clientOutputStreams.remove(clientOutputStreams.size()-1);
    }
}

public void userRemove (String data){
    String message, add = ": :Connect", done = "Server: :Done", name = data;
    users.remove(name);
    String[] tempList = new String[(users.size())];
    users.toArray(tempList);

    for (String token:tempList){
        message = (token + add);
        tellEveryone(message);
    }
    tellEveryone(done);
}

@SuppressWarnings("rawtypes")
public void tellEveryone(String message){
Iterator it = clientOutputStreams.iterator();

    while (it.hasNext()){
        try{
            PrintWriter writer = (PrintWriter) it.next();
            writer.println(message);
            System.out.print("Sending: " + message + "\n");
            writer.flush();
        }catch (Exception ex){
            System.out.print("Error telling everyone. \n");
        }
    } 
}

/**
 * Launch the application.
 */
public static void main(String[] args){
    EventQueue.invokeLater(new Runnable(){
        public void run(){
            if(args.length == 1){
                root_Chat_Server server = new root_Chat_Server();
                if(args[0].equals("start")){
                    server.start();
                }else if(args[0].equals("stop")){
                    server.stop();
                }else if(args[0].equals("users")){
                    server.users();
                }
            }else{
                System.out.println("java root_Chat_Server start|stop|users");
            }
        }
    });
}
}

Thank you for every answer!谢谢你的每一个回答!

There are no errors because you are catching exceptions and printing "Cannot connect to the Server! Try again!".没有错误,因为您正在捕获异常并打印“无法连接到服务器!再试一次!”。 You should print the exception messages to discover what is happening.您应该打印异常消息以发现发生了什么。

In Android, you have to run asynchronous network operations on a thread other than the main one.在 Android 中,您必须在主线程以外的线程上运行异步网络操作。 You are currently running the socket operation on the main thread, and this will cause an exception.您当前正在主线程上运行套接字操作,这将导致异常。

If you having trouble using native asynchronous in your project.如果您在项目中使用本机异步时遇到问题。 Have a look this link .看看这个链接 You can used this for your project.您可以将其用于您的项目。 It runs on a backend Node.js with a android client.它在带有 android 客户端的后端Node.js上运行。

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

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