Android通过Socket与服务器之间进行通信的示例

作者:狼之神 时间:2023-11-13 04:53:15 

一、首先进行Server的编写:


public class SocketServer {
private static Socket mSocket;

public static void main(String[] argc) {
 try {
  //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
  ServerSocket serverSocket = new ServerSocket(12345);
  InetAddress address = InetAddress.getLocalHost();
  String ip = address.getHostAddress();

//2.调用accept()等待客户端连接
  System.out.println("~~~服务端已就绪,等待客户端接入~,服务端ip地址: " + ip);
  mSocket = serverSocket.accept();

//3.连接后获取输入流,读取客户端信息
  InputStream is = null;
  InputStreamReader isr = null;
  BufferedReader br = null;
  OutputStream os = null;
  is = mSocket.getInputStream();
  isr = new InputStreamReader(is, "UTF-8");
  br = new BufferedReader(isr);
  String info = null;
  while ((info = br.readLine()) != null) {
   System.out.println("客户端发送过来的信息" + info);
   if (info.equals(BackService.HEART_BEAT_STRING)) {
    sendmsg("ok");

} else {
    sendmsg("服务器发送过来的信息" + info);

}
  }

mSocket.shutdownInput();
  mSocket.close();

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

}

//为连接上服务端的每个客户端发送信息
public static void sendmsg(String msg) {
 PrintWriter pout = null;
 try {
  pout = new PrintWriter(new BufferedWriter(
   new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);
  pout.println(msg);
 } catch (IOException e) {
  e.printStackTrace();
 }
}
}

二、对客户端的编写,主要用用AIDL进行Server和Client

AIDL 的编写主要为以下三部分:

1、创建 AIDL

1)、创建要操作的实体类,实现 Parcelable 接口,以便序列化/反序列化
2)、新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件
3)、Make project ,生成 Binder 的 Java 文件

2、服务端

1)、创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法
2)、在 onBind() 中返回

3、客户端

1)、实现 ServiceConnection 接口,在其中拿到 AIDL 类
2)、bindService()
3)、调用 AIDL 类中定义好的操作请求

IBackService.aidl 文件


package com.example.dell.aidlservice;

// Declare any non-default types here with import statements

interface IBackService {
/**
 * Demonstrates some basic types that you can use as parameters
 * and return values in AIDL.
 */

boolean sendMessage(String message);
}

Service的编写,命名为BackService


public class BackService extends Service {
private static final String TAG = "danxx";
public static final String HEART_BEAT_STRING = "HeartBeat";//心跳包内容
/**
 * 心跳频率
 */
private static final long HEART_BEAT_RATE = 3 * 1000;
/**
 * 服务器ip地址
 */
public static final String HOST = "172.16.50.115";
/**
 * 服务器端口号
 */
public static final int PORT = 12345;
/**
 * 服务器消息回复广播
 */
public static final String MESSAGE_ACTION = "message_ACTION";
/**
 * 服务器心跳回复广播
 */
public static final String HEART_BEAT_ACTION = "heart_beat_ACTION";
/**
 * 读线程
 */
private ReadThread mReadThread;

private LocalBroadcastManager mLocalBroadcastManager;
/***/
private WeakReference<Socket> mSocket;

// For heart Beat
private Handler mHandler = new Handler();
/**
 * 心跳任务,不断重复调用自己
 */
private Runnable heartBeatRunnable = new Runnable() {

@Override
 public void run() {
  if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
   boolean isSuccess = sendMsg(HEART_BEAT_STRING);//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket
   if (!isSuccess) {
    mHandler.removeCallbacks(heartBeatRunnable);
    mReadThread.release();
    releaseLastSocket(mSocket);
    new InitSocketThread().start();
   }
  }
  mHandler.postDelayed(this, HEART_BEAT_RATE);
 }
};

private long sendTime = 0L;
/**
 * aidl通讯回调
 */
private IBackService.Stub iBackService = new IBackService.Stub() {

/**
  * 收到内容发送消息
  * @param message 需要发送到服务器的消息
  * @return
  * @throws RemoteException
  */
 @Override
 public boolean sendMessage(String message) throws RemoteException {
  return sendMsg(message);
 }
};

@Override
public IBinder onBind(Intent arg0) {
 return iBackService;
}

@Override
public void onCreate() {
 super.onCreate();
 new InitSocketThread().start();
 mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
}

public boolean sendMsg(final String msg) {
 if (null == mSocket || null == mSocket.get()) {
  return false;
 }
 final Socket soc = mSocket.get();
 if (!soc.isClosed() && !soc.isOutputShutdown()) {
  new Thread(new Runnable() {
   @Override
   public void run() {
    try {
     OutputStream os = soc.getOutputStream();
     String message = msg + "\r\n";
     os.write(message.getBytes());
     os.flush();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }).start();
  sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间
 } else {
  return false;
 }
 return true;
}

private void initSocket() {//初始化Socket
 try {
  //1.创建客户端Socket,指定服务器地址和端口
  Socket so = new Socket(HOST, PORT);
  mSocket = new WeakReference<Socket>(so);
  mReadThread = new ReadThread(so);
  mReadThread.start();
  mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包
 } catch (UnknownHostException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 }
}

/**
 * 心跳机制判断出socket已经断开后,就销毁连接方便重新创建连接
 *
 * @param mSocket
 */
private void releaseLastSocket(WeakReference<Socket> mSocket) {
 try {
  if (null != mSocket) {
   Socket sk = mSocket.get();
   if (!sk.isClosed()) {
    sk.close();
   }
   sk = null;
   mSocket = null;
  }
 } catch (IOException e) {
  e.printStackTrace();
 }
}

class InitSocketThread extends Thread {
 @Override
 public void run() {
  super.run();
  initSocket();
 }
}

// Thread to read content from Socket
class ReadThread extends Thread {
 private WeakReference<Socket> mWeakSocket;
 private boolean isStart = true;

public ReadThread(Socket socket) {
  mWeakSocket = new WeakReference<Socket>(socket);
 }

public void release() {
  isStart = false;
  releaseLastSocket(mWeakSocket);
 }

@Override
 public void run() {
  super.run();
  Socket socket = mWeakSocket.get();
  if (null != socket) {
   try {
    InputStream is = socket.getInputStream();
    byte[] buffer = new byte[1024 * 4];
    int length = 0;
    while (!socket.isClosed() && !socket.isInputShutdown() && isStart && ((length = is.read(buffer)) != -1)) {
     if (length > 0) {
      String message = new String(Arrays.copyOf(buffer, length)).trim();
      Log.e(TAG, message);
      //收到服务器过来的消息,就通过Broadcast发送出去
      if (message.equals("ok")) {//处理心跳回复
       Intent intent = new Intent(HEART_BEAT_ACTION);
       mLocalBroadcastManager.sendBroadcast(intent);

} else {
       //其他消息回复
       Intent intent = new Intent(MESSAGE_ACTION);
       intent.putExtra("message", message);
       mLocalBroadcastManager.sendBroadcast(intent);
      }
     }
    }
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
 }
}

@Override
public void onDestroy() {
 super.onDestroy();
 mHandler.removeCallbacks(heartBeatRunnable);
 mReadThread.release();
 releaseLastSocket(mSocket);
}

}

MainActivity


public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mResultText;
private EditText mEditText;
private Intent mServiceIntent;

private IBackService iBackService;

private ServiceConnection conn = new ServiceConnection() {

@Override
 public void onServiceDisconnected(ComponentName name) {
  iBackService = null;

}

@Override
 public void onServiceConnected(ComponentName name, IBinder service) {
  iBackService = IBackService.Stub.asInterface(service);
 }
};

class MessageBackReciver extends BroadcastReceiver {
 private WeakReference<TextView> textView;

public MessageBackReciver(TextView tv) {
  textView = new WeakReference<TextView>(tv);
 }

@Override
 public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();
  TextView tv = textView.get();
  if (action.equals(BackService.HEART_BEAT_ACTION)) {
   if (null != tv) {
    Log.i("danxx", "Get a heart heat");
    tv.setText("Get a heart heat");
   }
  } else {
   Log.i("danxx", "Get a heart heat");
   String message = intent.getStringExtra("message");
   tv.setText("服务器消息:" + message);
  }
 }
}

private MessageBackReciver mReciver;

private IntentFilter mIntentFilter;

private LocalBroadcastManager mLocalBroadcastManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);

mResultText = (TextView) findViewById(R.id.resule_text);
 mEditText = (EditText) findViewById(R.id.content_edit);
 findViewById(R.id.send).setOnClickListener(this);
 findViewById(R.id.send1).setOnClickListener(this);
 mReciver = new MessageBackReciver(mResultText);

mServiceIntent = new Intent(this, BackService.class);

mIntentFilter = new IntentFilter();
 mIntentFilter.addAction(BackService.HEART_BEAT_ACTION);
 mIntentFilter.addAction(BackService.MESSAGE_ACTION);

}

@Override
protected void onStart() {
 super.onStart();
 mLocalBroadcastManager.registerReceiver(mReciver, mIntentFilter);
 bindService(mServiceIntent, conn, BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
 super.onStop();
 unbindService(conn);
 mLocalBroadcastManager.unregisterReceiver(mReciver);
}

public void onClick(View view) {
 switch (view.getId()) {
  case R.id.send:
   String content = mEditText.getText().toString();
   try {
    boolean isSend = iBackService.sendMessage(content);//Send Content by socket
    Toast.makeText(this, isSend ? "success" : "fail", Toast.LENGTH_SHORT).show();
    mEditText.setText("");
   } catch (RemoteException e) {
    e.printStackTrace();
   }
   break;

case R.id.send1:
   new Thread(new Runnable() {
    @Override
    public void run() {
     try {
      acceptServer();
     } catch (IOException e) {
      e.printStackTrace();
     }
    }
   }).start();
   break;

default:
   break;
 }
}

private void acceptServer() throws IOException {
 //1.创建客户端Socket,指定服务器地址和端口
 Socket socket = new Socket("172.16.50.115", 12345);
 //2.获取输出流,向服务器端发送信息
 OutputStream os = socket.getOutputStream();
 PrintWriter printWriter = new PrintWriter(os); //将输出流包装为打印流

//获取客户端的IP地址
 InetAddress address = InetAddress.getLocalHost();
 String ip = address.getHostAddress();
 printWriter.write("客户端:~" + ip + "~ 接入服务器!!");
 printWriter.flush();
 socket.shutdownInput();
 socket.close();
}
}

源码地址

来源:https://www.jianshu.com/p/f76a14c4d8e0

标签:Android,Socket,服务器,通信
0
投稿

猜你喜欢

  • java8新特性教程之time包使用总结

    2023-02-08 03:58:19
  • C#中反射和扩展方法如何运用

    2023-08-02 01:43:16
  • C++动态数组类的封装实例

    2022-07-03 14:52:25
  • Java Swing JList列表框的实现

    2021-09-05 08:20:56
  • Android实现淘宝客户端倒计时界面

    2023-09-18 21:25:09
  • Android application捕获崩溃异常怎么办

    2023-09-26 11:07:12
  • 适用于WebForm Mvc的Pager分页组件C#实现

    2022-05-11 22:11:34
  • 使用Sharding-JDBC对数据进行分片处理详解

    2021-07-27 23:46:04
  • 25行Java代码将普通图片转换为字符画图片和文本的实现

    2023-11-24 02:04:26
  • Mybatis实现自定义类型转换器TypeHandler的方法

    2023-09-28 14:52:22
  • java教学笔记之对象的创建与销毁

    2023-08-14 02:00:39
  • Java获取e.printStackTrace()打印的信息方式

    2022-05-18 05:19:26
  • 详解Mybatis中常用的约束文件

    2023-11-28 08:02:17
  • 如何搭建新的WPF项目框架

    2023-09-28 08:18:05
  • Android贝塞尔曲线初步学习第二课 仿QQ未读消息气泡拖拽黏连效果

    2023-08-18 10:18:20
  • java9迁移注意问题总结

    2022-07-19 11:26:30
  • Spring Boot2.X国际化文件编写配置

    2023-02-24 11:34:24
  • intellij idea使用git stash暂存一次提交的操作

    2023-03-08 08:30:11
  • java实现对Hadoop的操作

    2021-10-05 16:30:37
  • Android WaveView实现水流波动效果

    2021-11-09 16:50:59
  • asp之家 软件编程 m.aspxhome.com