使Service作为服务端 跑在com.example.sockettest:remote的私有进程中
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sockettest">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SocketTest">
<service
android:name=".TCPServerService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Socket服务端代码
package com.example.sockettest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import com.ethan.ethanutils.IOUtil;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class TCPServerService extends Service {
private static final String TAG = "Ethan";
private final String[] mDefinedMessages = new String[]{"你好小姐姐", "你好小哥哥"};
private boolean mIsServiceDestroyed = false;
public TCPServerService() {
}
@Override
public void onCreate() {
new Thread(new TcpServer()).start();
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
mIsServiceDestroyed = true;
super.onDestroy();
}
class TcpServer implements Runnable {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(10000);
while (!mIsServiceDestroyed) {
Socket client = serverSocket.accept();
Log.i(TAG, "服务端连接成功");
// 当连接成功后 单独开一个线程去负责通信 原线程继续阻塞在accept() 这样使得服务器可以与多个客户端连接
new Thread(() -> {
responseClient(client);
}).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null)
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void responseClient(Socket client) {
BufferedReader br = null;
PrintWriter pw = null;
try {
br = new BufferedReader(new InputStreamReader(client.getInputStream()));
pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
while (!mIsServiceDestroyed) {
// readLine()以换行符为分界 所以如果发来的消息没有换行符是接收不到的
String s = br.readLine();
Log.i(TAG, "服务端收到了消息: " + s);
// 约定以null作为结束符
if (s == null)
break;
String reply = mDefinedMessages[new Random().nextInt(mDefinedMessages.length)];
pw.println(reply);
}
// 如果客户端要求断开连接就会退出while
Log.i(TAG, "服务端断开连接");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null)
IOUtil.closeStream(br);
if (pw != null)
IOUtil.closeStream(pw);
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
MainActivity作为客户端,跑在com.example.sockettest进程中
Socket客户端代码
package com.example.sockettest;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import com.ethan.ethanutils.IOUtil;
import java.io.*;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Ethan";
Socket mClientSocket;
PrintWriter pw;
BufferedReader br;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, TCPServerService.class);
startService(intent);
new Thread(this::connectTCPServer).start();
Button sendMsg = findViewById(R.id.button);
sendMsg.setOnClickListener((v) -> {
new Thread(() -> {
pw.println("你好服务器!");
}).start();
});
}
@Override
protected void onDestroy() {
try {
// 丢弃当前流中没被接收的数据
mClientSocket.shutdownInput();
mClientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}
private void connectTCPServer() {
// 如果没创建成功就一直尝试创建
while (mClientSocket == null) {
try {
mClientSocket = new Socket("localhost", 10000);
pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mClientSocket.getOutputStream())), true);
Log.i(TAG, "客户端连接成功");
} catch (IOException e) {
SystemClock.sleep(1000);
Log.w(TAG, "连接超时,等待重试...");
e.printStackTrace();
}
}
try {
br = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
// 只要没离开页面断开连接 就一直在这里循环读消息
while (!this.isFinishing()) {
String s = br.readLine();
Log.i(TAG, "客户端收到了消息:" + s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (pw != null)
IOUtil.closeStream(pw);
if (br != null)
IOUtil.closeStream(br);
}
}
}