真的很简单的TCP客户端

G.V*_*.V. 16 android tcp

我希望我的应用程序输入我的服务器的URL,例如http://192.168.1.8/和端口1234.当我的服务器收到TCP请求消息时,它会发回一个文件(服务器已经实现).

我认为我不需要像AsyncTask那样复杂的东西,因为我不想保持连接.从服务器接收答案,我的连接必须关闭.

任何前进或尖端的迹象都受到高度赞赏.

Dan*_*ent 38

这是一个简单的TCP客户端,它使用我基于本教程中 的代码工作的套接字(教程的代码也可以在这个GitHub存储库中找到).

请注意,此代码适用于在客户端和服务器之间来回发送字符串,通常采用JSON格式.

这是TCP客户端代码:

import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class TcpClient {

    public static final String TAG = TcpClient.class.getSimpleName();
    public static final String SERVER_IP = "192.168.1.8"; //server IP address
    public static final int SERVER_PORT = 1234;
    // message to send to the server
    private String mServerMessage;
    // sends message received notifications
    private OnMessageReceived mMessageListener = null;
    // while this is true, the server will continue running
    private boolean mRun = false;
    // used to send messages
    private PrintWriter mBufferOut;
    // used to read messages from the server
    private BufferedReader mBufferIn;

    /**
     * Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TcpClient(OnMessageReceived listener) {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     *
     * @param message text entered by client
     */
    public void sendMessage(final String message) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (mBufferOut != null) {
                    Log.d(TAG, "Sending: " + message);
                    mBufferOut.println(message);
                    mBufferOut.flush();
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

    /**
     * Close the connection and release the members
     */
    public void stopClient() {

        mRun = false;

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

        mMessageListener = null;
        mBufferIn = null;
        mBufferOut = null;
        mServerMessage = null;
    }

    public void run() {

        mRun = true;

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

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

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

            try {

                //sends the message to the server
                mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                //receives the message which the server sends back
                mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));


                //in this while the client listens for the messages sent by the server
                while (mRun) {

                    mServerMessage = mBufferIn.readLine();

                    if (mServerMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(mServerMessage);
                    }

                }

                Log.d("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'");

            } catch (Exception e) {
                Log.e("TCP", "S: Error", e);
            } finally {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

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

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
    //class at on AsyncTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,在Activity中将TcpClient声明为成员变量:

public class MainActivity extends Activity {

    TcpClient mTcpClient;

    //............
Run Code Online (Sandbox Code Playgroud)

然后,使用AsyncTask连接到您的服务器并在UI线程上接收响应(请注意,从服务器接收的消息onProgressUpdate()在AsyncTask 中的方法覆盖中处理):

public class ConnectTask extends AsyncTask<String, String, TcpClient> {

    @Override
    protected TcpClient doInBackground(String... message) {

        //we create a TCPClient object
        mTcpClient = new TcpClient(new TcpClient.OnMessageReceived() {
            @Override
            //here the messageReceived method is implemented
            public void messageReceived(String message) {
                //this method calls the onProgressUpdate
                publishProgress(message);
            }
        });
        mTcpClient.run();

        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        //response received from server
        Log.d("test", "response " + values[0]);
        //process server response here....

}
Run Code Online (Sandbox Code Playgroud)

要启动与服务器的连接,请执行AsyncTask:

new ConnectTask().execute("");
Run Code Online (Sandbox Code Playgroud)

然后,向服务器发送消息:

//sends the message to the server
if (mTcpClient != null) {
    mTcpClient.sendMessage("testing");
}
Run Code Online (Sandbox Code Playgroud)

您可以随时关闭与服务器的连接:

if (mTcpClient != null) {
    mTcpClient.stopClient();
}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记将`<uses-permission android:name ="android.permission.INTERNET"> </ uses-permission>`添加到您的`AndroidManifest.xml`中 (5认同)
  • -1“AsyncTasks 理想情况下应该用于短操作(最多几秒钟。)” https://developer.android.com/reference/android/os/AsyncTask.html (2认同)
  • 这是我尝试学习 android 的第二天。过去熟悉 C 语言中的 tcp/ip,我发现上面的代码片段在涉及低级和高级交互的安排和抽象方面非常具有说明性。谢谢。 (2认同)

小智 8

感谢您的代码。就我而言,我没有使用基于行的协议,因此无法接收数据。我编写了与我的特定服务器设置配合使用的替代实现:

  1. 在TcpClient.java文件中,“ run()”命令应替换为下面的代码片段

    公共无效run(){

    mRun = true;
    
    try {
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
        Log.e("TCP Client", "C: Connecting...");
        Socket socket = new Socket(serverAddr, SERVER_PORT);
        try {
            mBufferOut = new PrintWriter(socket.getOutputStream());
            Log.e("TCP Client", "C: Sent.");
            mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            int charsRead = 0; char[] buffer = new char[1024]; //choose your buffer size if you need other than 1024
    
            while (mRun) {
                charsRead = mBufferIn.read(buffer);
                mServerMessage = new String(buffer).substring(0, charsRead);
                if (mServerMessage != null && mMessageListener != null) {
                    mMessageListener.messageReceived(mServerMessage);}
                mServerMessage = null;
            }
            Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + mServerMessage + "'"); 
    
    Run Code Online (Sandbox Code Playgroud)

//其余代码可以,请参见原始

  1. MainActivity.java中的doInBackgroud将收到的消息发布到onProgressUpdate,您可以将其显示在其他对象中,例如TextView

    @Override
    protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            Log.d("test", "response " + values[0]);
            response.setText(response.getText() + "/n" +values[0]);
    } 
    
    Run Code Online (Sandbox Code Playgroud)

//“响应”是在函数中声明的TextView对象

public class MainActivity extends AppCompatActivity {
TextView response; //...so on
Run Code Online (Sandbox Code Playgroud)

和功能

protected void onCreate(Bundle savedInstanceState) { response = (TextView) findViewById(R.id.textView); //..so on