为了账号安全,请及时绑定邮箱和手机立即绑定

Android之Socket群组聊天

标签:
Android

在这只做了一个简单的例子,没有用到数据库,思路就是客户端发送信息到服务器端,服务器端转发所有数据到客户端,校验服务器端发来消息是否是自己发出的,如果是自己发出的,则不显示自己的消息

  • 贴一下Android客户端的源码 -

    MainActivity.Java

  1. package com.zml.chatproject; 

  2.  

  3. import android.os.AsyncTask; 

  4. import android.os.Bundle; 

  5. import android.os.Handler; 

  6. import android.os.Message; 

  7. import android.support.v7.app.AppCompatActivity; 

  8. import android.text.Editable; 

  9. import android.text.TextUtils; 

  10. import android.text.TextWatcher; 

  11. import android.util.Log; 

  12. import android.view.KeyEvent; 

  13. import android.view.View; 

  14. import android.view.WindowManager; 

  15. import android.widget.Button; 

  16. import android.widget.EditText; 

  17. import android.widget.ListView; 

  18. import android.widget.Toast; 

  19.  

  20. import com.google.gson.Gson; 

  21.  

  22. import java.io.DataInputStream; 

  23. import java.io.DataOutputStream; 

  24. import java.io.IOException; 

  25. import java.net.Socket; 

  26. import java.util.ArrayList; 

  27. import java.util.List; 

  28.  

  29.  

  30. /** 

  31.  * @author 郑明亮   @email 1072307340@qq.com 

  32.  * @Time:2016/4/20 14:25 

  33.  * @version 1.0 

  34.  * TODO 

  35.  */ 

  36. public class MainActivity extends AppCompatActivity implements View.OnClickListener, TextWatcher { 

  37.     private static final String TAG = "MainActivity"; 

  38.     public static final int SENDMESSAGE = 0x004; 

  39.     public static final String name = System.currentTimeMillis()+""; 

  40.     List<Msg> list ; 

  41.     ListView mListView; 

  42.     EditText edit; 

  43.     Button bt_send; 

  44.     Socket socket; 

  45.     public static final int SHOWMSG = 0x003; 

  46.     private DataInputStream mDataInputStream = null; 

  47.     private DataOutputStream mDataOutputStream = null; 

  48.     private boolean Conneted = false; 

  49.     Handler mHandler = new Handler() { 

  50.         @Override 

  51.         public void handleMessage(Message msg) { 

  52.             super.handleMessage(msg); 

  53.             Log.i(TAG,"执行到handle"); 

  54.             if (msg.what == SENDMESSAGE) { 

  55.                 Msg xiaoxi = (Msg) msg.obj; 

  56.                 Log.i(TAG,"handler:"+xiaoxi.toString()); 

  57.                 list.add(xiaoxi); 

  58.                 //设置适配器 

  59.                 mListView.setAdapter(new MyAdapter(MainActivity.this, list)); 

  60.                 mListView.setSelection(mListView.getCount()-1); 

  61.             } 

  62.         } 

  63.     }; 

  64.  

  65.     @Override 

  66.     protected void onCreate(Bundle savedInstanceState) { 

  67.         super.onCreate(savedInstanceState); 

  68.         setContentView(R.layout.activity_main); 

  69.         mListView = (ListView) findViewById(R.id.listView); 

  70.         edit = (EditText) findViewById(R.id.et_edit); 

  71.         edit.addTextChangedListener(this); 

  72.         bt_send = (Button) findViewById(R.id.bt_send); 

  73.         bt_send.setOnClickListener(this); 

  74.         list = new ArrayList<>(); 

  75.    new AsyncTask<Void,Void,String>(){ 

  76.        @Override 

  77.        protected String doInBackground(Void... params) { 

  78.            try { 

  79.                socket = new Socket("172.18.40.182", 9999); 

  80. //               socket = new Socket("115.28.167.152", 9999); 

  81.                connect(); 

  82.                ClientThread thread = new ClientThread(); 

  83.                thread.run(); 

  84.  

  85.            } catch (IOException e) { 

  86.                e.printStackTrace(); 

  87.            } 

  88.            return null; 

  89.        } 

  90.    }.execute(); 

  91.  

  92.     } 

  93.  

  94.     @Override 

  95.     public boolean onKeyDown(int keyCode, KeyEvent event) { 

  96.         switch (event.getAction()){ 

  97.             case KeyEvent.KEYCODE_HOME: 

  98.                 Toast.makeText(MainActivity.this,"就是不让你退出,O(∩_∩)O哈哈哈~",Toast.LENGTH_LONG).show(); 

  99.                 Log.i(TAG,"KeyEvent.KEYCODE_HOME"+KeyEvent.KEYCODE_HOME); 

  100.                 break; 

  101.             case KeyEvent.KEYCODE_MOVE_HOME: 

  102.                 Toast.makeText(MainActivity.this,"就是不让你退出,O(∩_∩)O哈哈哈~",Toast.LENGTH_LONG).show(); 

  103.                 Log.i(TAG,"KeyEvent.KEYCODE_MOVE_HOME"+KeyEvent.KEYCODE_MOVE_HOME); 

  104.                 break; 

  105.         } 

  106.         return true; 

  107.     } 

  108.     @Override 

  109.     public void onAttachedToWindow() 

  110.  

  111.     { // TODO Auto-generated method stub 

  112.  

  113.         this.getWindow().setType(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); 

  114.  

  115.         super.onAttachedToWindow(); 

  116.  

  117.     } 

  118.     @Override 

  119.     public void onClick(View v) { 

  120.         switch (v.getId()){ 

  121.             case R.id.bt_send: 

  122.                 String show = edit.getText().toString().trim(); 

  123.                 if (TextUtils.isEmpty(show)){ 

  124.  

  125.                 }else { 

  126.                     edit.setText(""); 

  127.                     Msg msg = new Msg(); 

  128.                     msg.setFlag(Msg.TO); 

  129.                     msg.setMsg(show); 

  130.                     msg.setUsername(name); 

  131.                     list.add(msg); 

  132.                     mListView.setAdapter(new MyAdapter(MainActivity.this,list)); 

  133.                     mListView.setSelection(mListView.getCount()-1); 

  134.                     try {if (mDataOutputStream==null){ 

  135.                         mDataOutputStream = new DataOutputStream(socket.getOutputStream()); 

  136.                     } 

  137.                         Gson gson = new Gson(); 

  138.                       show =  gson.toJson(msg); 

  139.                         mDataOutputStream.writeUTF(show); 

  140.                         mDataOutputStream.flush(); 

  141.                         Log.i(TAG,"发送成功:"+show); 

  142.                     } catch (IOException e) { 

  143.                         e.printStackTrace(); 

  144.                     } 

  145.  

  146.                 } 

  147.                 break; 

  148.         } 

  149.     } 

  150.  

  151.     @Override 

  152.     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

  153.         bt_send.setEnabled(false); 

  154.     } 

  155.  

  156.     @Override 

  157.     public void onTextChanged(CharSequence s, int start, int before, int count) { 

  158.         if (s.length()>0){ 

  159.             bt_send.setEnabled(true); 

  160.         } 

  161.     } 

  162.  

  163.     @Override 

  164.     public void afterTextChanged(Editable s) { 

  165.  

  166.     } 

  167.  

  168.     /** 

  169.      * 开启线程,接收消息 

  170.      */ 

  171.     private class ClientThread implements Runnable { 

  172.         @Override 

  173.         public void run() { 

  174.             while (Conneted) { 

  175.                 try { 

  176.                     String str = mDataInputStream.readUTF(); 

  177.                     Log.i(TAG,"子线程得到数据:"+str); 

  178.                     Gson gson = new Gson(); 

  179.                     Msg msg = gson.fromJson(str,Msg.class); 

  180.                     msg.setFlag(Msg.FROM); 

  181.                     Message message = mHandler.obtainMessage(); 

  182.                     message.what = SENDMESSAGE; 

  183.                     message.obj = msg; 

  184.                     mHandler.sendMessage(message); 

  185.  

  186.                 } catch (IOException e) { 

  187.                     e.printStackTrace(); 

  188.                 } 

  189.  

  190.  

  191.             } 

  192.         } 

  193.     } 

  194.  

  195.     /** 

  196.      * 打开连接 

  197.      */ 

  198.     public void connect() { 

  199.         try { 

  200.             mDataInputStream = new DataInputStream(socket.getInputStream()); 

  201.             mDataOutputStream = new DataOutputStream(socket.getOutputStream()); 

  202.             if (socket.isConnected()){ 

  203.                 Log.i(TAG, "连接上了"); 

  204.             }else { 

  205.                 Log.i(TAG, "连接失败"); 

  206.             } 

  207.  

  208.             Conneted = true; 

  209.         } catch (IOException e) { 

  210.             e.printStackTrace(); 

  211.         } 

  212.  

  213.     } 

  214.  

  215.     /** 

  216.      * 断开与服务器的连接 

  217.      */ 

  218.     public void disconnect() { 

  219.         try { 

  220.             mDataInputStream.close(); 

  221.             mDataOutputStream.close(); 

  222.             socket.close(); 

  223.         } catch (IOException e) { 

  224.             e.printStackTrace(); 

  225.         } 

  226.  

  227.     } 

  228.  

  229.     @Override 

  230.     protected void onDestroy() { 

  231.         super.onDestroy(); 

  232.         disconnect(); 

  233.     } 

  234. }

Msg.java 消息实体类

  1. package com.zml.chatproject; 

  2.  

  3. /** 

  4.  * Created by bri on 2016/4/16. 

  5.  */ 

  6.  

  7. /** 

  8.  * 消息实体类 

  9.  */ 

  10. public class Msg { 

  11.     public static final int FROM = 0x001; 

  12.     public static final int TO = 0x002; 

  13.  

  14.     /** 

  15.      * 发送聊天消息 

  16.      */ 

  17.     private String msg; 

  18.     /** 

  19.      * 标识符,表示是发送方还是接收方 

  20.      */ 

  21.     private int flag; 

  22.     /** 

  23.      * 用户名 

  24.      */ 

  25.     private String username; 

  26.  

  27.     @Override 

  28.     public String toString() { 

  29.         return "Msg{" + 

  30.                 "msg='" + msg + '\\'' + 

  31.                 ", flag=" + flag + 

  32.                 ", username='" + username + '\\'' + 

  33.                 '}'; 

  34.     } 

  35.  

  36.     public String getMsg() { 

  37.         return msg; 

  38.     } 

  39.  

  40.     public void setMsg(String msg) { 

  41.         this.msg = msg; 

  42.     } 

  43.  

  44.     public int getFlag() { 

  45.         return flag; 

  46.     } 

  47.  

  48.     public void setFlag(int flag) { 

  49.         this.flag = flag; 

  50.     } 

  51.  

  52.     public String getUsername() { 

  53.         return username; 

  54.     } 

  55.  

  56.     public void setUsername(String username) { 

  57.         this.username = username; 

  58.     } 

  59. }

MyAdapter 数据适配器

  1. package com.zml.chatproject; 

  2.  

  3. import android.content.Context; 

  4. import android.util.Log; 

  5. import android.view.LayoutInflater; 

  6. import android.view.View; 

  7. import android.view.ViewGroup; 

  8. import android.widget.BaseAdapter; 

  9. import android.widget.ListAdapter; 

  10. import android.widget.TextView; 

  11.  

  12. import java.util.List; 

  13.  

  14. /** 

  15.  * Created by bri on 2016/4/17. 

  16.  */ 

  17. public class MyAdapter extends BaseAdapter implements ListAdapter { 

  18.     private static final String TAG = "MyAdapter"; 

  19.  

  20.     Context context; 

  21.     List<Msg> message; 

  22.     public MyAdapter(Context context, List<Msg> message) { 

  23.         this.context = context; 

  24.         this.message = message; 

  25.     } 

  26.  

  27.     @Override 

  28.     public int getCount() { 

  29.         return message.size(); 

  30.     } 

  31.  

  32.     @Override 

  33.     public Object getItem(int position) { 

  34.         return null; 

  35.     } 

  36.  

  37.     @Override 

  38.     public long getItemId(int position) { 

  39.         return 0; 

  40.     } 

  41.  

  42.     @Override 

  43.     public View getView(int position, View convertView, ViewGroup parent) { 

  44.  

  45.         if (convertView == null){ 

  46.         convertView = LayoutInflater.from(context).inflate(R.layout.activity_main_item,null); 

  47.  

  48.  

  49.         } 

  50.         TextView tv_from = ViewHolder.get(convertView,R.id.tv_chatting_from); 

  51.         TextView tv_to = ViewHolder.get(convertView,R.id.tv_chatting_to); 

  52. //        tv_from.setText(message.getMsg()); 

  53.         Log.i(TAG,"接收成功"+message.get(position).getMsg()); 

  54.         if (message.get(position).getFlag()==(Msg.FROM)){ 

  55.             if (message.get(position).getUsername().equals(MainActivity.name)){ 

  56.                 tv_from.setVisibility(View.GONE); 

  57.                 tv_to.setVisibility(View.GONE);} 

  58.             else { Log.i(TAG,"接收成功FROM"+message.get(position).getMsg()); 

  59.                 tv_from.setText(message.get(position).getMsg()); 

  60.                 tv_from.setVisibility(View.VISIBLE); 

  61.                 tv_to.setVisibility(View.GONE);} 

  62.  

  63.  

  64. //            Toast.makeText(context,"from:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show(); 

  65.         }if (message.get(position).getFlag()==(Msg.TO)){ 

  66. //            Toast.makeText(context,"to:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show(); 

  67.             Log.i(TAG,"接收成功TO"+message.get(position).getMsg()); 

  68.             tv_to.setText(message.get(position).getMsg()); 

  69.             tv_from.setVisibility(View.GONE); 

  70.             tv_to.setVisibility(View.VISIBLE); 

  71.  

  72.         } 

  73.  

  74.  

  75.         return convertView; 

  76.  

  77.  

  78.     } 

  79.  

  80. }

ViewHoder 一个超实用的通用ViewHoder类

  1. package com.zml.chatproject; 

  2.  

  3. import android.content.Context; 

  4. import android.util.Log; 

  5. import android.view.LayoutInflater; 

  6. import android.view.View; 

  7. import android.view.ViewGroup; 

  8. import android.widget.BaseAdapter; 

  9. import android.widget.ListAdapter; 

  10. import android.widget.TextView; 

  11.  

  12. import java.util.List; 

  13.  

  14. /** 

  15.  * Created by bri on 2016/4/17. 

  16.  */ 

  17. public class MyAdapter extends BaseAdapter implements ListAdapter { 

  18.     private static final String TAG = "MyAdapter"; 

  19.  

  20.     Context context; 

  21.     List<Msg> message; 

  22.     public MyAdapter(Context context, List<Msg> message) { 

  23.         this.context = context; 

  24.         this.message = message; 

  25.     } 

  26.  

  27.     @Override 

  28.     public int getCount() { 

  29.         return message.size(); 

  30.     } 

  31.  

  32.     @Override 

  33.     public Object getItem(int position) { 

  34.         return null; 

  35.     } 

  36.  

  37.     @Override 

  38.     public long getItemId(int position) { 

  39.         return 0; 

  40.     } 

  41.  

  42.     @Override 

  43.     public View getView(int position, View convertView, ViewGroup parent) { 

  44.  

  45.         if (convertView == null){ 

  46.         convertView = LayoutInflater.from(context).inflate(R.layout.activity_main_item,null); 

  47.  

  48.  

  49.         } 

  50.         TextView tv_from = ViewHolder.get(convertView,R.id.tv_chatting_from); 

  51.         TextView tv_to = ViewHolder.get(convertView,R.id.tv_chatting_to); 

  52. //        tv_from.setText(message.getMsg()); 

  53.         Log.i(TAG,"接收成功"+message.get(position).getMsg()); 

  54.         if (message.get(position).getFlag()==(Msg.FROM)){ 

  55.             if (message.get(position).getUsername().equals(MainActivity.name)){ 

  56.                 tv_from.setVisibility(View.GONE); 

  57.                 tv_to.setVisibility(View.GONE);} 

  58.             else { Log.i(TAG,"接收成功FROM"+message.get(position).getMsg()); 

  59.                 tv_from.setText(message.get(position).getMsg()); 

  60.                 tv_from.setVisibility(View.VISIBLE); 

  61.                 tv_to.setVisibility(View.GONE);} 

  62.  

  63.  

  64. //            Toast.makeText(context,"from:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show(); 

  65.         }if (message.get(position).getFlag()==(Msg.TO)){ 

  66. //            Toast.makeText(context,"to:"+message.get(position).getMsg(),Toast.LENGTH_LONG).show(); 

  67.             Log.i(TAG,"接收成功TO"+message.get(position).getMsg()); 

  68.             tv_to.setText(message.get(position).getMsg()); 

  69.             tv_from.setVisibility(View.GONE); 

  70.             tv_to.setVisibility(View.VISIBLE); 

  71.  

  72.         } 

  73.  

  74.  

  75.         return convertView; 

  76.  

  77.  

  78.     } 

  79.  

  80. }

  • 好了,客户端的源码贴完了,接下来服务器端的源码就比较简单了

Client.java 重写一个子线程

  1.  

  2. import java.io.DataInputStream; 

  3. import java.io.DataOutputStream; 

  4. import java.io.IOException; 

  5. import java.net.Socket; 

  6. import java.util.ArrayList; 

  7. import java.util.Collections; 

  8. import java.util.Iterator; 

  9. import java.util.List; 

  10.  

  11. /** 

  12.  * @author 郑明亮 

  13.  * @Time:2016年4月16日 下午9:01:53 

  14.  * @version 1.0 

  15.  */ 

  16.  

  17.  

  18. public class Client implements  Runnable { 

  19.     Socket socket; 

  20.     List<Client> clients  ; 

  21.     public static final int SHOWMSG = 0x003; 

  22.     private DataInputStream mDataInputStream = null; 

  23.     private DataOutputStream mDataOutputStream = null; 

  24.     private boolean Conneted = false; 

  25.     public Client(Socket socket){ 

  26.         this.socket = socket; 

  27.         try { 

  28.             mDataInputStream = new DataInputStream(socket.getInputStream()); 

  29.             mDataOutputStream = new DataOutputStream(socket.getOutputStream()); 

  30.             Conneted = true; 

  31.             clients =new ArrayList<Client>(); 

  32.         } catch (IOException e) { 

  33.             e.printStackTrace(); 

  34.         } 

  35.  

  36.     }; 

  37.  

  38.     /** 

  39.      * 发送消息 

  40.      */ 

  41.     public void send(String string){ 

  42.         try { 

  43.             mDataOutputStream.writeUTF(string);//向输入流中写入数据 

  44.             System.out.println("向输入流中写入数据"); 

  45.         } catch (IOException e) { 

  46.             e.printStackTrace(); 

  47. //            Server.clients.remove(this);//出错时,客户端可能已断线,移除当前客户端 

  48.             System.out.println("出错时,客户端可能已断线,移除当前客户端"); 

  49.         } 

  50.     } 

  51.     @Override 

  52.     public void run() { 

  53.     while(Conneted){ 

  54.         try { 

  55.             System.out.println("连接成功!"); 

  56.             //读取数据 

  57.             String str = mDataInputStream.readUTF(); 

  58.             clients = Server.clients; 

  59.             synchronized (clients) { 

  60.                 Iterator<Client> iterator =clients.iterator(); 

  61.                 while (iterator.hasNext()) { 

  62.                     Client client = iterator.next(); 

  63.                     //将读取的数据发送回去 

  64.                     System.out.println("将读取的数据发送回去"+str); 

  65.                     client.send(str); 

  66.                 } 

  67. //                Conneted = false; 

  68.             } 

  69.         } catch (IOException e) { 

  70.             e.printStackTrace(); 

  71.             Server.clients.remove(this); 

  72.             System.out.println("线程出现异常"); 

  73.         }finally{ 

  74.  

  75. //            try { 

  76. ////                mDataOutputStream.close(); 

  77. ////                mDataInputStream.close(); 

  78. //            } catch (IOException e) { 

  79. //                // TODO Auto-generated catch block 

  80. //                e.printStackTrace(); 

  81. //            } 

  82.         } 

  83.     } 

  84.     } 

  85.  

  86.  

  87. }

Server 服务器端,先运行起它来,再去部署客户端即可

  1. import java.io.IOException; 

  2. import java.net.ServerSocket; 

  3. import java.net.Socket; 

  4. import java.util.ArrayList; 

  5. import java.util.Collections; 

  6. import java.util.List; 

  7.  

  8. /** 

  9.  * @author 郑明亮 

  10.  * @Time:2016年4月16日 下午9:01:43 

  11.  * @version 1.0 

  12.  */ 

  13. public class Server { 

  14.     static boolean started = false; 

  15.     public static List<Client> clients = new ArrayList<>(); 

  16.  

  17.     public static void main(String a[]){ 

  18.     try { 

  19.         ServerSocket serverSocket = new ServerSocket(9999); 

  20.         System.out.println("开启服务,等待监听"); 

  21.         started = true; 

  22.         while (started) { 

  23.             System.out.println("开始监听"); 

  24.             Socket socket = serverSocket.accept(); 

  25.             Client client = new Client(socket);     

  26.             new Thread(client).start(); 

  27.             clients.add(client); 

  28.         } 

  29.  

  30.  

  31.     } catch (IOException e) { 

  32.         // TODO Auto-generated catch block 

  33.         e.printStackTrace(); 

  34.     } 

  35.  

  36. }

原文链接:http://www.apkbus.com/blog-725636-60419.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消