GitHub完整代码!
当不同设备间的IP地址互相可见,Socket可实现设备间的通信。
使用Service必须在AndroidManifest.xml注册:
<service
android:name=".TCPServerService"
android:enabled="true"
android:exported="true">service>
第一步,创建服务端:
在Service中,开辟线程监听本地的一个端口:serverSocket = new ServerSocket(8688)
;获取Socket实例:Socket client = serverSocket.accept()
;创建BufferedReader
实例用于接收客户端消息(String str = in.readLine()
);创建PrintWriter
用于向客户端发送消息(out.println("欢迎来到聊天室!")
)。
//服务端
public class TCPServerService extends Service {
private boolean mIsServiceDestoryed = false;
private String[] mDefinedMessages = new String[]{
"你好啊,LXB",
"请问你叫什么名字呀?",
"中午吃了什么呢,可以分享一下吗?",
"你知道吗?我可以同时和多个人聊天的哦",
"爱笑的人运气不会太差哦~"
};
@Override
public void onCreate() {
new Thread(new TcpServer()).start();//开辟线程监听8688端口
super.onCreate();
}
public TCPServerService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
mIsServiceDestoryed = true;
super.onDestroy();
}
}
线程里监听端口的方法:
private class TcpServer implements Runnable{
@SuppressWarnings("resource")
@Override
public void run() {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(8688);//监听本地8688端口
} catch (IOException e) {
System.err.println("establish tcp server failed, port:8688");
e.printStackTrace();
return;
}
while (!mIsServiceDestoryed){
try{
final Socket client = serverSocket.accept();//接收客户端8688端口请求
System.out.println("accept");
new Thread(){
@Override
public void run() {
try{
responseClient(client);//把8688端口接收到的Socket传给responseClient()
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
监听方法里响应客户端的方法:
private void responseClient(Socket client) throws IOException{
//用于接收客户端消息
BufferedReader in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
//用于向客户端发送消息
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(client.getOutputStream())),true);
out.println("欢迎来到聊天室!");//向客户端发送消息
while (!mIsServiceDestoryed){
String str = in.readLine();//从in读取client的信息
System.out.println("msg from client: " + str);
if (str == null){
//客户端断开连接
break;
}
int i = new Random().nextInt(mDefinedMessages.length);//产生一个随机数
String msg = mDefinedMessages[i];
out.println(msg);//向服务端发送消息
System.out.println("send: " + msg);
}
System.out.println("client quit.");
//关闭流
MyUtils.close(out);
MyUtils.close(in);
client.close();
}
在AndroidManifest.xml中要声明网络权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
开启Service的方法:
//开启TCP-Service
Intent service = new Intent(this,TCPServerService.class);
startService(service);
第二步,创建客户端:
开启线程,获得Socket:socket = new Socket("localhost",8688)
,创建PrintWriter
(mPrintWriter.println(msg)
)实例用于发送数据;创建BufferedReader
(String msg = br.readLine()
)用于读取服务端的消息;
//客户端
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final int MESSAGE_RECEIVE_NEW_MSG = 1;
private static final int MESSAGE_SOCKET_CONNECTED = 2;
private Button mSendButton;
private TextView mMessageTextView;
private EditText mMessageEditText;
private Socket mClientSocket;
private PrintWriter mPrintWriter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessageTextView = (TextView) findViewById(R.id.textview);
mSendButton = (Button) findViewById(R.id.button);
mSendButton.setOnClickListener(this);
mMessageEditText = (EditText) findViewById(R.id.edittext);
//开启线程,连接TCP-Service
new Thread(){
@Override
public void run() {
connectTCPServer();
}
}.start();
}
}
用Handler来处理消息:
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MESSAGE_RECEIVE_NEW_MSG:
mMessageTextView.setText(mMessageTextView.getText() + (String)msg.obj);
break;
case MESSAGE_SOCKET_CONNECTED:
mSendButton.setEnabled(true);//使发送消息的按钮可按
break;
}
}
};
转换时间表达的方法:
//转化时间表达
@SuppressLint("SimpleDateFormat")
private String formatDateTime(long time){
return new SimpleDateFormat("(HH:mm:ss)").format(new Date(time));
}
线程中的处理:(接收数据)
private void connectTCPServer(){
Socket socket = null;
while (socket == null){//连接Socket,连接上时这块代码就没用了
try{
socket = new Socket("localhost",8688);//创建8688端口的Socket
mClientSocket = socket;
//用于发送数据
mPrintWriter = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),true);
mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);//让Handler执行相关动作
System.out.println("connect server success");
} catch (IOException e) {//连接失败后会重连,重试间隔1000毫秒
SystemClock.sleep(1000);
System.out.println("connect tcp server failed, retry...");
}
}
try{
//接收服务端的消息
BufferedReader br = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while (!MainActivity.this.isFinishing()){//当Activity不结束,就一直读取消息
String msg = br.readLine();//从BufferedReader读取消息
System.out.println("receive :" + msg);
if (msg != null){
String time = formatDateTime(System.currentTimeMillis());
final String showedMsg = "server " + time + ":" + msg + "\n";
//把收到的消息交给Handler处理
mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG,showedMsg).sendToTarget();
}
}
System.out.println("quit...");
MyUtils.close(mPrintWriter);//关闭发送数据的PrintWriter
MyUtils.close(br);//关闭接收服务端的消息BufferedReader
socket.close();//关闭Socket
} catch (IOException e) {
e.printStackTrace();
}
}
按钮点击事件:(发送数据)
//发送消息按钮的点击事件
@Override
public void onClick(View v) {
if (v == mSendButton){
final String msg = mMessageEditText.getText().toString();
if (!TextUtils.isEmpty(msg) && mPrintWriter != null){
mPrintWriter.println(msg);//PrintWriter发送数据给服务端
mMessageEditText.setText("");
String time = formatDateTime(System.currentTimeMillis());
final String showedMsg = "self " + time + ":" + msg + "\n";
mMessageTextView.setText(mMessageTextView.getText() + showedMsg);
}
}
}
onDestroy
善后处理:
@Override
protected void onDestroy() {
if (mClientSocket != null){
try{
mClientSocket.shutdownInput();
mClientSocket.close();//关闭Socket
} catch (IOException e) {
e.printStackTrace();
}
}
super.onDestroy();
}