• Android之Socket群组聊天


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

    • 贴一下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. }
  • 相关阅读:
    读理,妙句秒人秒事,二记
    读理,妙句秒人秒事,一记
    (原)DirectX11 深度测试(有点另类)
    游戏编程书籍推荐
    android入门-环境搭建
    Spring||Interview
    JSR-133内存模型手册
    JVM执行引擎
    HIbernate总结
    虚拟机类加载机制
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5454781.html
Copyright © 2020-2023  润新知