Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android TCP客户端发送数据,但TCP服务器接收空数据_Android_Sockets_Tcp_Server_Client - Fatal编程技术网

Android TCP客户端发送数据,但TCP服务器接收空数据

Android TCP客户端发送数据,但TCP服务器接收空数据,android,sockets,tcp,server,client,Android,Sockets,Tcp,Server,Client,我的应用程序中有一个TCP客户端和一个TCP服务器类。 客户端发送小字符串,如“1 | 2 |”或“1 | 11 |” 客户端类 public class TcpClient { private static final int MAX_DATA_RETRY = 1; private static final int PING_TIMEOUT = 100; private ClientThread thread; private boolean mRun = true; private P

我的应用程序中有一个TCP客户端和一个TCP服务器类。 客户端发送小字符串,如“1 | 2 |”或“1 | 11 |”

客户端类

public class TcpClient {


private static final int MAX_DATA_RETRY = 1;
private static final int PING_TIMEOUT = 100;

private ClientThread thread;
private boolean mRun = true;
private PrintWriter mBufferOut;

private String mIPAdress;


private ArrayList<BufferDataItem> messageBuffer = new ArrayList<BufferDataItem>();
private Socket mSocket;

public TcpClient()
{
    thread = new ClientThread();
    thread.start();
}

private class ClientThread extends Thread {

    @Override
    public void run() {

        while(mRun)
        {
            if(messageBuffer.size() <= 0)
                continue;

            BufferDataItem currMessage = messageBuffer.get(0);
            currMessage.retryCount++;
            if(currMessage.retryCount > MAX_DATA_RETRY)
            {
                messageBuffer.remove(0);
                continue;
            }

            try {
                //here you must put your computer's IP address.
                InetAddress serverAddr = InetAddress.getByName(currMessage.ip);



                //Log.e("TCP Client", "C: Connecting...");

                try {
                    if(!serverAddr.isReachable(PING_TIMEOUT))
                    {
                        //only attempt to connect to devices that are reachable
                        messageBuffer.remove(0);
                        continue;
                    }


                    //create a socket to make the connection with the server
                    mSocket = new Socket(serverAddr, TcpManager.SERVER_PORT);

                    //Log.i("TCP Debug", "inside try catch");
                    //sends the message to the server

                    mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);

                    String message = currMessage.message;
                    if (mBufferOut != null && !mBufferOut.checkError()) {
                        Log.d("TCP SEND", "PUTTING IN BUFFER!  " + message);
                        mBufferOut.println(message);
                        listener.messageSent(message, currMessage.ip);
                        messageBuffer.remove(0);
                    }
                    mBufferOut.flush();

                }
                catch (ConnectException e) {
                    //Connection refused by found device!
                    //Log.e("TCP", "C: ConnectException   ip = "+currMessage.ip, e);
                    listener.hostUnreachable(currMessage.ip);
                    continue;
                }
                catch (Exception e) {
                    Log.e("TCP", "S: Error", e);
                    listener.messageSendError(e);
                }
                finally {
                    if(mSocket != null)
                        mSocket.close();
                }

            }
            catch (Exception e) {
                Log.e("TCP", "C: Error", e);
                listener.messageSendError(e);
                continue;
            }
        }
    }
}



/**
 * Sends the message entered by client to the server
 *
 * @param message text entered by client
 */
public void sendMessage(String message) {

    BufferDataItem data = new BufferDataItem();
    data.message = message;
    data.ip = mIPAdress;
    messageBuffer.add(data);
}

public void sendMessage(String message, String ip) {
    mIPAdress = ip;
    BufferDataItem data = new BufferDataItem();
    data.message = message;
    data.ip = mIPAdress;
    messageBuffer.add(data);
}


/**
 * Close the connection and release the members
 */
public void stopClient() {
    Log.i("Debug", "stopClient");

    mRun = false;

    if (mBufferOut != null) {
        mBufferOut.flush();
        mBufferOut.close();
    }
    mBufferOut = null;
}

private class BufferDataItem
{
    public String message = "";
    public int retryCount = 0;
    public String ip = "";
}

private OnMessageSent listener = null;

public interface OnMessageSent {
    public void messageSent(String message, String ip);

    public void hostUnreachable(String ip);

    public void messageSendError(Exception e);

}

public void setMessageSentListener(OnMessageSent listener)
{
    this.listener = listener;
}

public void removeMessageSentListener()
{
    this.listener = null;
}
}

这在最初几次运行时工作正常,然后客户端发送“1 | 11 |”,服务器在读取期间将st设置为null。 字符串st=input.readLine()


有人有什么建议吗?

我认为服务器在一段时间后没有收到有效数据有两个可能的原因

  • 服务器未关闭套接字
    s
    ,因为
    mEnd
    从未设置为true。客户端为每条消息打开一个新的TCP连接。服务器为连接创建套接字,但它从不关闭套接字,连接的服务器端保持打开状态。这是一个资源泄漏,可能会导致问题

  • 客户端使用
    ArrayList messageBuffer
    ArrayList
    不是线程安全的集合,并且从多个线程使用了
    messageBuffer
    。在此处使用
    synchronizedList
    是安全的。看到手术室了吗


  • 我发现服务器在一段时间后没有收到有效数据的两个可能原因

  • 服务器未关闭套接字
    s
    ,因为
    mEnd
    从未设置为true。客户端为每条消息打开一个新的TCP连接。服务器为连接创建套接字,但它从不关闭套接字,连接的服务器端保持打开状态。这是一个资源泄漏,可能会导致问题

  • 客户端使用
    ArrayList messageBuffer
    ArrayList
    不是线程安全的集合,并且从多个线程使用了
    messageBuffer
    。在此处使用
    synchronizedList
    是安全的。看到手术室了吗


  • ArrayList不是线程安全的容器。客户端代码修改来自不同线程的
    messageBuffer
    ,而不进行任何同步。此外,
    mEnd
    在服务器代码中从未设置为true。所以服务器永远不会关闭客户端套接字和相关流->资源泄漏。感谢Zaboj。我必须承认,多线程确实让我头疼。你能推荐一个线程安全的替代ArrayList吗?对于服务器,我认为套接字必须保持打开状态,以便继续接收正在进行的数据。不是这样吗?客户端为每条消息创建一个新的tcp连接。服务器为每个tcp连接创建一个新套接字。这些插座必须关闭。也许这不是主要的错误,但服务器在长时间运行后将缺少资源。谢谢。ArrayList的线程安全替代品呢?ArrayList不是线程安全的容器。客户端代码修改来自不同线程的
    messageBuffer
    ,而不进行任何同步。此外,
    mEnd
    在服务器代码中从未设置为true。所以服务器永远不会关闭客户端套接字和相关流->资源泄漏。感谢Zaboj。我必须承认,多线程确实让我头疼。你能推荐一个线程安全的替代ArrayList吗?对于服务器,我认为套接字必须保持打开状态,以便继续接收正在进行的数据。不是这样吗?客户端为每条消息创建一个新的tcp连接。服务器为每个tcp连接创建一个新套接字。这些插座必须关闭。也许这不是主要的错误,但服务器在长时间运行后将缺少资源。谢谢。作为ArrayList的线程安全替代方案呢?
    public class TcpServer {
    
    private ServerThread thread;
    private boolean mRun = true;
    private boolean mEnd = false;
    
    
    public TcpServer()
    {
        thread = new ServerThread();
        thread.start();
    }
    
    private class ServerThread extends Thread {
    
        @Override
        public void run() {
    
            try {
                Boolean end = false;
                ServerSocket ss = new ServerSocket(TcpManager.SERVER_PORT);
                while (mRun) {
                    //Server is waiting for client here, if needed
                    Socket s = ss.accept();
                    BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
                    //PrintWriter output = new PrintWriter(s.getOutputStream(), true); //Autoflush
                    String st = input.readLine();
                    String remoteIP = s.getRemoteSocketAddress().toString();
                    int index = remoteIP.indexOf(":");
                    remoteIP = remoteIP.substring(1,index);
    
                    Log.d("TCP READ", "TCP READ: " + st);
                    if(st != null)
                        listener.messageReceived(st, remoteIP);
                    //output.println("Good bye and thanks for all the fish :)");
    
                    if(mEnd)
                    {
                        s.close();
                        mRun = false;
                    }
                }
    
                ss.close();
    
    
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
    //class at on asynckTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message, String ip);
    }
    
    private OnMessageReceived listener = null;
    
    public void SetMessageReceivedListener(OnMessageReceived listener)
    {
        this.listener = listener;
    }
    
    public void RemoveMessageReceivedListener()
    {
        this.listener = null;
    }