Android应用socket即时通讯的实现
一、服务器
思路:
首先创建服务器,用一个死循环等候若干个客户端的连接。一旦有客户端连接,就把客户端添加到集合当中,并且启动一个新的线程来保持长连接,监控客户端发来的信息。一旦接收到有客户端发来的信息,就进行包装后遍历集合,把包装好的信息发送给每一个客户端。
代码如下:
- /**
- * Tcp通信服务器
- * @author Devin Chen
- *
- */
- public class CSServer {
- private static final int PORT = 8888;
- private List<Socket> mClientList = new ArrayList<Socket>();
- private ServerSocket server = null;
- private ExecutorService mExecutors = null; // 线程池对象
- public static void main(String[] args) {
- new CSServer();
- }
- /**
- * 构造方法:任务是启动服务器,等待客户端连接
- */
- public CSServer() {
- try {
- server = new ServerSocket(PORT);
- mExecutors = Executors.newCachedThreadPool(); // 创建线程池
- System.out.println("服务器已启动,等待客户端连接...");
- Socket client = null;
- /*
- * 用死循环等待多个客户端的连接,连接一个就启动一个线程进行管理
- */
- while (true) {
- client = server.accept();
- // 把客户端放入集合中
- mClientList.add(client);
- mExecutors.execute(new Service(client)); // 启动一个线程,用以守候从客户端发来的消息
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- class Service implements Runnable {
- private Socket socket;
- private BufferedReader in = null;
- private String message = "";
- public Service(Socket socket) {
- this.socket = socket;
- try {
- in = new BufferedReader(new InputStreamReader(
- socket.getInputStream()));// 获得输入流对象
- // 客户端只要一连到服务器,便发送连接成功的信息
- message = "服务器地址:" + this.socket.getInetAddress();
- this.sendMessage(message);
- message = "当前连接总数:" + mClientList.size();
- this.sendMessage(message);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- @Override
- public void run() {
- try {
- while (true) {
- if ((message = in.readLine()) != null) {
- // 当客户端发送的信息为:exit时,关闭连接
- if (message.equals("exit")) {
- closeSocket();
- break;
- } else {
- // 接收客户端发过来的信息message,然后转发给客户端。
- message = socket.getInetAddress() + ":" + message;
- this.sendMessage(message);
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 关闭客户端
- *
- * @throws IOException
- */
- public void closeSocket() throws IOException {
- mClientList.remove(socket);
- in.close();
- message = "主机:" + socket.getInetAddress() + "关闭连接\n目前在线:"
- + mClientList.size();
- socket.close();
- this.sendMessage(message);
- }
- /**
- * 将接收的消息转发给每一个客户端
- *
- * @param msg
- */
- public void sendMessage(String msg) {
- System.out.println(msg);// 先在控制台输出
- int count = mClientList.size();
- // 遍历客户端集合
- for (int i = 0; i < count; i++) {
- Socket mSocket = mClientList.get(i);
- PrintWriter out = null;
- try {
- out = new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(mSocket.getOutputStream())),
- true);// 创建输出流对象
- out.println(msg);// 转发
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
二、Android客户端
思路:
设置权限。
首先开辟线程,在线程中连接服务器,并获取输入流和输出流,并用一个死循环接收来自服务器的消息,输入流收到消息进行处理,用handler通知给UI线程更新文本框。
编辑框填好消息,直接点击发送。用获得的输出流发送消息。
代码:
- /**
- * Android Tcp即时通讯客户端
- */
- public class MainActivity extends Activity implements Runnable{
- private TextView tv_msg = null;
- private EditText ed_msg = null;
- private Button btn_send = null;
- private static final String HOST = "192.168.0.100";//服务器地址
- private static final int PORT = 8888;//连接端口号
- private Socket socket = null;
- private BufferedReader in = null;
- private PrintWriter out = null;
- //接收线程发送过来信息,并用TextView追加显示
- public Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- tv_msg.append((CharSequence) msg.obj);
- }
- };
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- tv_msg = (TextView) findViewById(R.id.txt_1);
- ed_msg = (EditText) findViewById(R.id.et_talk);
- btn_send = (Button) findViewById(R.id.btn_send);
- btn_send.setOnClickListener(new Button.OnClickListener() {
- @Override
- public void onClick(View v) {
- String msg = ed_msg.getText().toString();
- if (socket.isConnected()) {//如果服务器连接
- if (!socket.isOutputShutdown()) {//如果输出流没有断开
- out.println(msg);//点击按钮发送消息
- ed_msg.setText("");//清空编辑框
- }
- }
- }
- });
- //启动线程,连接服务器,并用死循环守候,接收服务器发送过来的数据
- new Thread(this).start();
- }
- /**
- * 连接服务器
- */
- private void connection() {
- try {
- socket = new Socket(HOST, PORT);//连接服务器
- in = new BufferedReader(new InputStreamReader(socket
- .getInputStream()));//接收消息的流对象
- out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
- socket.getOutputStream())), true);//发送消息的流对象
- } catch (IOException ex) {
- ex.printStackTrace();
- ShowDialog("连接服务器失败:" + ex.getMessage());
- }
- }
- /**
- * 如果连接出现异常,弹出AlertDialog!
- */
- public void ShowDialog(String msg) {
- new AlertDialog.Builder(this).setTitle("通知").setMessage(msg)
- .setPositiveButton("ok", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- }
- }).show();
- }
- /**
- * 读取服务器发来的信息,并通过Handler发给UI线程
- */
- public void run() {
- connection();// 连接到服务器
- try {
- while (true) {//死循环守护,监控服务器发来的消息
- if (!socket.isClosed()) {//如果服务器没有关闭
- if (socket.isConnected()) {//连接正常
- if (!socket.isInputShutdown()) {//如果输入流没有断开
- String getLine;
- if ((getLine = in.readLine()) != null) {//读取接收的信息
- getLine += "\n";
- Message message=new Message();
- message.obj=getLine;
- mHandler.sendMessage(message);//通知UI更新
- } else {
- }
- }
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
运行效果:
如果要扩展优化成一个有模有样的即时通讯工具。考虑发发送的消息用json进行格式化,包含用户昵称和图片地址等等,服务器收到后解析,在添加上时间等进行重新包装。客户端收到消息,同样进行解析,装载到美化好的listview当中。
相关推荐
- 初创团队的Android应用质量保障之道
- 初创团队的 Android 应用质量保障之道
- 棉花糖多少钱_如何在6.0棉花糖及更高版本中访问Android的正在运行的应用程序列表...
- hittest方法的底层实现与应用
- Android应用开发(二):Activity生命周期剖析以及如何启动新的Activity或网页
- JavaFX本地应用自动更新功能的实现——FXLauncher
- SaaS应用市场的定价模式--何时实现免费增值
- SaaS应用市场的定价模式--何时实现免费增值
- 2、了解小程序端要实现的功能 - 微擎小程序模块应用开发
- android 实现简单的引导层图层功能
- 无人机专用4G数传:宇时4G数传 安卓客户端正式发布
- 解决阿里云服务器自己安装的mysql不能链接问题