套接字应用在发送消息服务器-客户端时出错(首先是连接异常,然后是下一次尝试绑定异常)

时间:2018-07-18 14:14:58

标签: java android sockets client-server p2p

我正在尝试使用Android平台上的Java Socket和Wifi P2P连接来创建服务器-客户端聊天应用程序,以用于我的大学论文。该应用程序将允许服务器创建新的聊天室,而客户端将加入聊天室。

但是,当服务器和客户端第一次在聊天室中时,它始终无法发送和接收消息。服务器和客户端离开聊天室并创建新的聊天室后,它将成功发送和接收消息。

我有用于发送和接收消息的源代码:

SendMessageServer.java

public class SendMessageServer extends AsyncTask<Message, Message, Message> {

private static final String TAG = "SendMessageServer";
private Context mContext;
private static final int serverPort = 4446;
private boolean isMine;

public SendMessageServer(Context context, boolean mine){
    mContext = context;
    isMine = mine;
}

@Override
protected Message doInBackground(Message... messages) {

    // Display Message Before Sending
    publishProgress(messages);

    // Send Message to Client
    try {
        ArrayList<InetAddress> listClients = ServerThread.clients;
        for(InetAddress addr : listClients) {
            if(messages[0].getSenderAddress()!=null && addr.getHostAddress().equals(messages[0].getSenderAddress().getHostAddress())) {
                return messages[0];
            }

            Socket socket = new Socket();
            socket.setReuseAddress(true);
            socket.bind(null);
            Log.v(TAG,"Connect to Client: " + addr.getHostAddress());

            socket.connect(new InetSocketAddress(addr, serverPort));
            Log.v(TAG,"Connect to " + addr.getHostAddress() + " Success");

            OutputStream outputStream = socket.getOutputStream();

            new ObjectOutputStream(outputStream).writeObject(messages[0]);
            Log.v(TAG, "Write to "+ addr.getHostAddress() + " Success");

            socket.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.v(TAG, "Send Message Server Error");
    }
    return messages[0];
}

@Override
protected void onProgressUpdate(Message... values) {
    super.onProgressUpdate(values);

    if(isActivityRunning(MainMenu.class)) {
        ChatActivity.refreshList(values[0], isMine);
    }
}

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

@SuppressWarnings("rawtypes")
public Boolean isActivityRunning(Class activityClass) {
    ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

    for (ActivityManager.RunningTaskInfo task : tasks) {
        if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName())) {
            return true;
        }
    }
    return false;
}
}

SendMessageClient.java

public class SendMessageClient extends AsyncTask<Message, Message, Message> {

    private static final String TAG = "SendMessageClient";

    private Context mContext;
    private static final int serverPort = 4445;
    private InetAddress mServerAddress;

    public SendMessageClient(Context context, InetAddress serverAddress){
        mContext = context;
        mServerAddress = serverAddress;
    }

    @Override
    protected Message doInBackground(Message... messages) {
        // Display Message Before Sending
        publishProgress(messages);

        // Send the message
        Socket socket = new Socket();
        try {
            socket.setReuseAddress(true);
            socket.bind(null);
            socket.connect(new InetSocketAddress(mServerAddress, serverPort));
            Log.v(TAG, "Connect to Server : " + mServerAddress.getHostAddress() + " Success");

            OutputStream outputStream = socket.getOutputStream();
            new ObjectOutputStream(outputStream).writeObject(messages[0]);
            Log.v(TAG, "Send Message Client Success");
        } catch (IOException e) {
            e.printStackTrace();
            Log.v(TAG, "Send Message Client Error");
        } finally{
            if (socket != null) {
                if (socket.isConnected()) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.v(TAG, "Send Message Client Error");
                    }
                }
            }
        }
        return messages[0];
    }

    @Override
    protected void onProgressUpdate(Message... messages) {
        super.onProgressUpdate(messages);

        if(isActivityRunning(MainMenu.class)){
            ChatActivity.refreshList(messages[0], true);
        }
    }

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

    @SuppressWarnings("rawtypes")
    public Boolean isActivityRunning(Class activityClass) {
        ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (ActivityManager.RunningTaskInfo task : tasks) {
            if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName())) {
                return true;
            }
        }

        return false;
    }
}

ReceiveMessageServer.java

public class ReceiveMessageServer extends AbstractReceiver {

    private static final String TAG = "ReceiveMessageServer";

    private static final int serverPort = 4445;
    private Context mContext;
    private ServerSocket serverSocket;

    public ReceiveMessageServer(Context context){
        mContext = context;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            serverSocket = new ServerSocket(serverPort);
            while(true) {
                Socket clientSocket = serverSocket.accept();

                InputStream inputStream = clientSocket.getInputStream();
                ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
                Message message = (Message) objectInputStream.readObject();

                // Add Sender InetAddress to Message
                InetAddress senderAddress = clientSocket.getInetAddress();
                message.setSenderAddress(senderAddress);

                clientSocket.close();
                publishProgress(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.v(TAG, "Receive Message Failed : IOException");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            Log.v(TAG, "Receive Message Failed : ClassNotFoundException");
        }
        return null;
    }

    @Override
    protected void onCancelled() {
        try {
            serverSocket.close();
            Log.v(TAG, "Server Socket Close Success");
        } catch (IOException e) {
            e.printStackTrace();
            Log.v(TAG, "Server Socket Close Failed");
        }
        super.onCancelled();
    }

    @Override
    protected void onProgressUpdate(Message... values) {
        super.onProgressUpdate(values);
        playNotification(mContext, values[0]);

        // Check Message Type exclude Text Message
        int type = values[0].getmType();
        if(type == Message.audioMessage || type == Message.fileMessage) {
            values[0].saveByteArrayToFile(mContext);
        }

        new SendMessageServer(mContext, false).executeOnExecutor(THREAD_POOL_EXECUTOR, values);
    }

}

ReceiveMessageClient.java

public class ReceiveMessageClient extends AbstractReceiver {

private static final String TAG = "ReceiveMessageClient";

private static final int serverPort = 4446;
private Context mContext;
private ServerSocket socket;

public ReceiveMessageClient(Context mContext) {
    this.mContext = mContext;
}

@Override
protected Void doInBackground(Void... params) {
    try {
        socket = new ServerSocket(serverPort);
        socket.setReuseAddress(true);
        while (true) {
            Socket destinationSocket = socket.accept();

            InputStream inputStream = destinationSocket.getInputStream();
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            ObjectInputStream objectInputStream = new ObjectInputStream(bufferedInputStream);
            Message message = (Message) objectInputStream.readObject();

            destinationSocket.close();
            publishProgress(message);
        }
    } catch (IOException e) {
        e.printStackTrace();
        Log.v(TAG, "Receive Message Client Failed : IOException");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        Log.v(TAG, "Receive Message Client Failed : ClassNotFoundException");
    }
    return null;
}

@Override
protected void onCancelled() {
    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    super.onCancelled();
}

@Override
protected void onProgressUpdate(Message... values) {
    super.onProgressUpdate(values);
    playNotification(mContext, values[0]);

    /* Check if the Message Contains Audio/Video/File
     * If true, Save to External Storage
    */
    int type = values[0].getmType();
    if (type == Message.audioMessage || type == Message.fileMessage){
        values[0].saveByteArrayToFile(mContext);
    }

    if (isActivityRunning(MainMenu.class)){
        ChatActivity.refreshList(values[0], false);
    }
}

public Boolean isActivityRunning(Class activityClass) {
    ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

    for (ActivityManager.RunningTaskInfo task : tasks) {
        if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
            return true;
    }

    return false;
}
}

AbstractReceiver类仅用于通知,因此我认为问题仅来自于这四个类。

这是发生错误时的Logcat

07-18 21:06:31.952 12064-12426/com.archenians.inlesschat W/System.err: java.net.ConnectException: failed to connect to /192.168.49.220 (port 4446): connect failed: ECONNREFUSED (Connection refused)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:129)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:188)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:457)
        at java.net.Socket.connect(Socket.java:927)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err:     at java.net.Socket.connect(Socket.java:853)
07-18 21:06:31.955 12064-12426/com.archenians.inlesschat W/System.err:     at com.archenians.inlesschat.Asynctasks.SendMessageServer.doInBackground(SendMessageServer.java:53)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err:     at com.archenians.inlesschat.Asynctasks.SendMessageServer.doInBackground(SendMessageServer.java:22)
        at android.os.AsyncTask$2.call(AsyncTask.java:295)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
        at java.lang.Thread.run(Thread.java:818)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err: Caused by: android.system.ErrnoException: connect failed: ECONNREFUSED (Connection refused)
07-18 21:06:31.956 12064-12426/com.archenians.inlesschat W/System.err:     at libcore.io.Posix.connect(Native Method)
07-18 21:06:31.957 12064-12426/com.archenians.inlesschat W/System.err:     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:111)
        at libcore.io.IoBridge.connectErrno(IoBridge.java:144)
        at libcore.io.IoBridge.connect(IoBridge.java:127)
        ... 11 more
07-18 21:06:31.957 12064-12426/com.archenians.inlesschat V/SendMessageServer: Send Message Server Error
07-18 21:06:31.974 12064-12177/com.archenians.inlesschat D/OpenGLRenderer: CacheTexture 3 upload: x, y, width height = 0, 28, 394, 382

它表示类SendMessageServer.java第53行

socket.connect(new InetSocketAddress(addr, serverPort));

它在客户端显示相同的错误。

编辑:

如果服务器和客户端离开聊天室并创建一个新的聊天室,则发送和接收消息将成功。但是,一旦成功,ServerThread就会出现一个新问题。

有我的ServerThread.java和ClientThread.java代码

ServerThread.java

public class ServerThread extends Thread {

    private static final String TAG = "ServerThread";

    private static final int SERVER_PORT = 4444;
    public static ArrayList<InetAddress> clients;
    private ServerSocket serverSocket;

    public ServerThread(){
        clients = new ArrayList<InetAddress>();
    }

    @Override
    public void run() {
        clients.clear();

        try {
            serverSocket = new ServerSocket(SERVER_PORT);
            // Collect IP Client
            while(true) {
                Socket clientSocket = serverSocket.accept();
                if(!clients.contains(clientSocket.getInetAddress())){
                    clients.add(clientSocket.getInetAddress());
                    Log.v(TAG, "New client: " + clientSocket.getInetAddress().getHostAddress());
                }

                clientSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void interrupt() {
        super.interrupt();
        try {
            serverSocket.close();
            Log.v(TAG, "Server init process interrupted");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

ClientThread.java

public class ClientThread extends Thread {

    public static final String TAG = "ClientThread";

    private static final int SERVER_PORT = 4444;
    private InetAddress mServerAddr;

    public ClientThread(InetAddress serverAddr){
        mServerAddr = serverAddr;
    }

    @Override
    public void run() {
        Socket socket = new Socket();
        try {
            socket.bind(null);
            socket.connect(new InetSocketAddress(mServerAddr, SERVER_PORT));
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

从服务器端,错误显示在行上:

serverSocket = new ServerSocket(SERVER_PORT);

这是Logcat的绑定异常

07-20 07:57:20.531 6417-6616/com.archenians.inlesschat W/System.err: java.net.BindException: bind failed: EADDRINUSE (Address already in use)
        at libcore.io.IoBridge.bind(IoBridge.java:104)
        at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:137)
07-20 07:57:20.532 6417-6616/com.archenians.inlesschat W/System.err:     at java.net.ServerSocket.<init>(ServerSocket.java:106)
        at java.net.ServerSocket.<init>(ServerSocket.java:75)
        at com.archenians.inlesschat.Threads.ServerThread.run(ServerThread.java:28)
    Caused by: android.system.ErrnoException: bind failed: EADDRINUSE (Address already in use)
        at libcore.io.Posix.bind(Native Method)
07-20 07:57:20.533 6417-6616/com.archenians.inlesschat W/System.err:     at libcore.io.ForwardingOs.bind(ForwardingOs.java:56)
        at libcore.io.IoBridge.bind(IoBridge.java:102)
        ... 4 more 

我一直尝试添加

setReuseAddress(true);

但是,即使服务器和客户端关闭聊天室并再次创建一个新的聊天室,发送消息也永远不会成功。

有人可以帮助我吗?

告诉我这些代码在哪里以及如何解决。

0 个答案:

没有答案