基于socket实现的简单聊天android软件

这款app是基于socket来写的,为何选择socket来写,暂定为老师要求的。。。

这款app的运行条件是首先要运行服务端,之后再登录客户端,登录后就可以开始聊天了,聊天内容用了listview来显示,在网上搜罗了一些适配器加上的

新手的话对于消息处理机制肯定不是很理解,这里附上参考网址:http://www.cnblogs.com/yaozhenfa/p/np_android_Handler.html

首先上代码

必要条件:

AndroidManifest.xml文件当中必须加入下面这句话

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

服务端:

/**
 * 多线程服务器
 */
public class Server implements Runnable{


    private Socket socket;
    private Ponline ponline;


    public Server(Socket socket) {
        this.socket = socket;
        ponline = Ponline.getInstance();
    }


    @Override
    public void run() {
        try {
            System.out.println("child thread is running...");
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg = null;
            System.out.println("waiting for msg...");
            while ((msg = reader.readLine()) != null) {
                System.out.println(msg);
                if(!msg.startsWith("send")){
                    ponline.putSockets(msg, socket);
                    System.out.println("******save a client socket******");
                }else{
                    //use another login socket outputstream
                    String [] msgs = msg.split(":");
                    if(msgs[2] == null){//group chat
                        Set<String> allSockets = ponline.getAllSockets();
                        for(String user : allSockets){
                            if (user != msgs[1]) {
                                PrintWriter writer = new PrintWriter(ponline.getSockets(user).getOutputStream());
                                writer.println(msg);
                                writer.flush();
                            }
                        }
                    }else{//single chat
                        PrintWriter writer = new PrintWriter(ponline.getSockets(msgs[2]).getOutputStream());
                        writer.println(msg);
                        writer.flush();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        boolean flag = true;
        while (flag) {
            Socket socket = serverSocket.accept();
            new Thread(new Server(socket)).start();
        }
    }
}

服务端保存在线用户类:

/**
 * 存放连接的客户端socket
 */
public class Ponline {
    private static  Ponline mOnline;
    private HashMap<String,Socket> sockets = new HashMap<>();


    public Ponline(){}


    public synchronized static Ponline getInstance() {
        if(null == mOnline) {
            mOnline = new Ponline();
        }
        return mOnline;
    }


    public void putSockets(String str, Socket socket) {
        sockets.put(str, socket);
    }


    public Socket getSockets(String str) {
        return sockets.get(str);
    }


    public void remove(String str){
        sockets.remove(str);
    }


    public Set<String> getAllSockets() {
        return sockets.keySet();
    }
}


客户端:

public class Chat extends Activity {//ChatClient


    private Button btnSend ;
    private EditText eTmsg;
    private ListView listView;


    private Socket socket;


    private String userName;
    private String singleChat;
    private boolean isConnected = false;
    private final String IP = "192.168.1.102";
    private final int PORT = 8888;


    private List<Map<String, String>> mData = new ArrayList<Map<String, String>>();
    private MyAdapter adapter;




    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            //修改UI控件操作
            if(msg.what == 0x123){
                String [] arr = (String[])msg.obj;
                String from = arr[0];
                String msgs = arr[1];
                Map<String, String> temp = new HashMap<String, String>();
                temp.put("user",from);
                temp.put("msg", msgs);
                mData.add(temp);
                adapter.notifyDataSetChanged();
            }
        }
    };


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


        btnSend = (Button) findViewById(R.id.btnSend);
        eTmsg = (EditText) findViewById(R.id.eTmsg);
        listView = (ListView) findViewById(R.id.listView);
        userName = getIntent().getStringExtra("user");
        singleChat = getIntent().getStringExtra("isSingle");


        adapter = new MyAdapter(this);
        listView.setAdapter(adapter);


        //connect to server when activity start
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Socket socket = new Socket(IP, PORT);
                    PrintWriter writer = new PrintWriter(socket.getOutputStream());
                    writer.println(userName);
                    writer.flush();
                    PConnection.socket = socket;
                    new ChatThread(socket).start();//start child thread
                    System.out.println("connect to server");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();


        btnSend.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 String str = eTmsg.getText().toString().trim();
                 sendMsg(userName, singleChat, str);
                 eTmsg.setText("");
             }
        });
    }
    /*
    * send msg to server
    * */
    public void sendMsg (final String from,final String to,final String msg) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    socket = PConnection.socket;
                    OutputStream os = socket.getOutputStream();
                    PrintWriter writer = new PrintWriter(os);
                    writer.println("send:" + from + ":" + to + ":" + msg);
                    writer.flush();
                    System.out.println("send msg to server");
                    Message message = handler.obtainMessage(0x123, new String[] {from , msg});
                    message.sendToTarget();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }




    /*
     * ViewHolder静态类
     * */
    static class ViewHolder
    {
        public TextView user;
        public TextView msg;
    }


    /*
    * listView适配器
    * */
    private class MyAdapter extends BaseAdapter
    {
        private LayoutInflater mInflater = null;
        private MyAdapter(Context context)
        {
            //根据context上下文加载布局,这里的是Demo17Activity本身,即this
            this.mInflater = LayoutInflater.from(context);
        }
        @Override
        public int getCount() {
            //How many items are in the data set represented by this Adapter.
            //在此适配器中所代表的数据集中的条目数
            return mData.size();
        }
        @Override
        public Object getItem(int position) {
            // Get the data item associated with the specified position in the data set.
            //获取数据集中与指定索引对应的数据项
            return position;
        }
        @Override
        public long getItemId(int position) {
            //Get the row id associated with the specified position in the list.
            //获取在列表中与指定索引对应的行id
            return position;
        }


        //Get a View that displays the data at the specified position in the data set.
        //获取一个在数据集中指定索引的视图来显示数据
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            //如果缓存convertView为空,则需要创建View
            if(convertView == null)
            {
                holder = new ViewHolder();
                //根据自定义的Item布局加载布局
                convertView = mInflater.inflate(R.layout.list_item, null);
                holder.user = (TextView)convertView.findViewById(R.id.tv);
                holder.msg = (TextView)convertView.findViewById(R.id.info);
                //将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag
                convertView.setTag(holder);
            }else
            {
                holder = (ViewHolder)convertView.getTag();
            }
            holder.user.setText((String)mData.get(position).get("user"));
            holder.msg.setText((String)mData.get(position).get("msg"));


            return convertView;
        }


    }


    class ChatThread extends Thread{
        private Socket s;


        public ChatThread(Socket s) {
            super();
            this.s = s;
        }


        @Override
        public void run() {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                while (true) {
                    String content = null;
                    while((content = br.readLine()) != null) {
                        System.out.println("rec msg from server:"+content);
                        String [] msg = content.split(":");
                        Message message = handler.obtainMessage(0x123, new String[] {msg[1] , msg[3]});
                        message.sendToTarget();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


客户端保存socket类:

/**
 * 存放登录后的socket,在发送消息和接收消息时使用该socket
 */
public class PConnection {
    public static Socket socket;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值