Android Socket实现多个客户端即时通信聊天

聊天室的原理是这样的,一个客户端与服务器建立通讯成功,即客户端socket连接到服务器的ServerSocket之后,服务器端程序将对应的socket加入到容器中,为每一个socket创建一条线程,服务器端读到客户端发来的信息之后,遍历该容器,给容器中的每个socket发送一次,就完成了所有客户端广播。当客户端离开时,向服务器发送一条断开连接信息,从服务器端断开socket,将容器中的对应socket移除掉。

图:

服务器端Server,java:

accept通信后,为该socket建立一条线程,开启循环读写操作

/**
 * Created by konghao on 2017/11/8.
 */
public class Server {
 
    static List<Socket> cons = new LinkedList<Socket>();
    private static Socket socket = null;
 
    public static class ServerThread extends Thread{
        private Socket s;
 
        public ServerThread(Socket socket){
            this.s = socket;
            cons.add(s);
        }
 
        @Override
        public void run(){
            System.out.print("新用户加入\n");
            System.out.print("当前在线数量:"+cons.size()+"\n");
            try{
                while(true){
 
                    BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                    String mess;// = br.readLine();
                    //保存信息
                    if((mess=br.readLine())!=null) {
                        if(mess.equals("-用户退出-")){
                            s.close();
                        }
                        System.out.print("客户端:" + mess + "\n");
                        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                        //为了证明是服务器返回的数据,我对mess修改在发送到客户端
                        //这里修改广播到所有客户端
                        for (Socket so : cons){
                            BufferedWriter buffw = new BufferedWriter(new OutputStreamWriter(so.getOutputStream()));
                            String str = "服务器>>"+mess+"\n";
                            buffw.write(str);
                            buffw.flush();
                        }
                        //
                        //单客户端通信
                        /*
                        String str = "服务器>>"+mess+"\n";
                        bw.write(str);
                        bw.flush();
                        */
                    }
                }
            }catch (IOException e){
                System.out.print("用户退出!\n");
                cons.remove(s);
                e.printStackTrace();
                this.interrupt();
                //e.printStackTrace();
            }catch (NullPointerException e) {
                System.out.print("NullPointerException");
            }finally {
                try {
                    s.close();
                }catch (IOException e){
                    System.out.print("IOException-2");
                    e.printStackTrace();
                }
            }
        }
 
    }
 
    public static void main(String[] args) throws IOException {
 
        ServerSocket ss = new ServerSocket(30001);
        while(true){
            Socket s = ss.accept();
            new Thread(new ServerThread(s)).start();
        }
    }
}

安卓客户端:

进入活动时候创建一条线程,完成socket连接,和循环监听接受服务器发来的消息。当发送按钮按下后,向服务器发送消息。退出活动时候,向服务器发送结束通信信息,服务器收到后关闭socket。

ChatRoomActivity.java

public class ChatRoomActivity extends Activity implements View.OnClickListener{
    private Socket socket = null;
    private EditText edit;
    private Button send,disconnect;
    private RecyclerView msg_recyclerView;
    private MsgAdapter adapter;
    private List<Msg> msgs = new ArrayList<Msg>();//存储消息容器
    private String name = "";
    private static final int UPDATE = 1;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat_room);
 
        Intent intent = getIntent();
        name = intent.getStringExtra("name");
        Log.d("孔昊",name);
 
        //从服务器读数进程
        new Thread(new Runnable() {
            private String msg_get="";
            @Override
            public void run() {
                try {
                    socket = new Socket();
                    socket.connect(new InetSocketAddress("公网IP", 30001), 5000);
 
                    //input
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 
                    while((msg_get=br.readLine())!=null){
                        Message message = new Message();
                        Bundle bundle = new Bundle();
                        Log.d("孔昊",msg_get);
                        bundle.putString("msg",msg_get);
                        message.setData(bundle);
                        message.what = UPDATE;
                        handler.sendMessage(message);
                    }
 
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }).start();
 
        edit = (EditText) findViewById(R.id.edit);
        send = (Button) findViewById(R.id.send);
        send.setOnClickListener(this);
        disconnect = (Button) findViewById(R.id.disconnect);
        disconnect.setOnClickListener(this);
 
        msg_recyclerView = (RecyclerView) findViewById(R.id.msg_view);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        msg_recyclerView.setLayoutManager(linearLayoutManager);
        adapter = new MsgAdapter(msgs);
        msg_recyclerView.setAdapter(adapter);
    }
 
    Handler handler = new Handler(){
 
        @Override
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            switch (msg.what){
                //更新消息列表
                case UPDATE:{
                    Bundle bundle = msg.getData();
                    String msg_get = bundle.getString("msg");
                    Msg msg1 = new Msg(msg_get);
                    msgs.add(msg1);
                    adapter.notifyDataSetChanged();
                }
                break;
            }
        }
    };
 
    //向服务器发数据进程
    class SocketThread extends Thread{
        private String msg;
        //Socket socket;
 
        public SocketThread(String m){
            msg = m;
        }
 
        @Override
        public void run(){
            try {
 
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                bw.write(msg);
                bw.newLine();
                bw.flush();
 
            }catch (IOException e){
                e.printStackTrace();
            }
        }
 
    }
 
    @Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.send:{
                String s = name +":"+ edit.getText().toString();
                edit.setText("");
                new Thread(new SocketThread(s)).start();
            }
            break;
            case R.id.disconnect:{
                try {
                    //socket.shutdownOutput();
                    //socket.shutdownInput();
                    //socket.close();
                    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                    bw.write("-用户退出-");
                    bw.newLine();
                    bw.flush();
                    //发送message,更新UI
                    Message message = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("msg","你已经退出聊天!");
                    message.setData(bundle);
                    message.what = UPDATE;
                    handler.sendMessage(message);
 
                }catch (IOException e){
                    //Log.d("孔昊","断开连接");
                    e.printStackTrace();
                }
            }
            break;
        }
    }
 
    //back事件
 
    @Override
    public void onBackPressed(){
        try {
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("-用户退出-");
            bw.newLine();
            bw.flush();
 
        }catch (IOException e){
            e.printStackTrace();
        }
        super.onBackPressed();
    }
 
}

服务器端收到的信息:

另附java控制台作为客户端代码:

/**
 * Created by konghao on 2017/11/8.
 */
public class Client {
    private static String name;
    private static Socket socket;
    public static void main(String[] args) {
        try {
            name = "孔昊";
            Socket s = new Socket("112.74.92.125",30001);
            socket = s;
            System.out.println("客户端IP:"+s.getLocalAddress()+"端口"+s.getPort());
            //构建IO流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
 
            //建立键盘输入:
            Scanner scanner = new Scanner(System.in);
            while(true){
                System.out.println("请输入发送消息内容:");
                bw.write(name+":"+scanner.nextLine()+"\n");
                bw.newLine();
                bw.flush();
                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
                //读取服务器返回的消息数据
                System.out.println(s.getInetAddress().getLocalHost()+":"+s.getPort()+">>"+br.readLine());
            }
 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                socket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
 
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android 基于Socket的聊天室实例

    Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路.一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信. Client A  发信息给 Client B ,  A的信息首先发送信息到服务器Server ,Server接受到信息后再把A的信息广播发送给所有的Clients 首先我们要在服务器建立一个ServerSocket ,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待

  • android Socket实现简单聊天功能以及文件传输

    干程序是一件枯燥重复的事,每当感到内心浮躁的时候,我就会找小说来看.我从小就喜爱看武侠小说,一直有着武侠梦.从金庸,古龙,梁羽生系列到凤歌(昆仑),孙晓(英雄志)以及萧鼎的(诛仙)让我领略着不一样的江湖. 如果你有好看的武侠系列小说,给我留言哦.题外话就扯这么多了,接着还是上技术. 看看今天实现的功能效果图: 可以这里使用多台手机进行通讯,我采用的服务器发送消息. 是不是只有发送消息,有些显得太单调了.好,在发送消息的基础上增加文件传输.后期会增加视频,音频的传输,增加表情包.那一起来看看图文消

  • 基于Socket.IO实现Android聊天功能代码示例

    一.简述 Socket.IO是一个完全由JavaScript实现.基于Node.js.支持WebSocket的协议用于实时通信.跨平台的开源框架,它包括了客户端的JavaScript和服务器端的Node.js. 该种官方介绍看起来有点懵逼,简而言之就是:客户端可通过Socket.IO与服务器建立实时通信管道 二.应用 该下就是介绍Socket.IO通信管道的铺设.通信以及销毁工作. 2.1 引入Socket.io包 compile 'io.socket:socket.io-client:0.8.

  • android socket聊天室功能实现

    前提概要 笔者很久之前其实就已经学习过了socket,当然也是用socket做过了聊天室,但是觉得此知识点比较一般,并无特别难的技术点,于是也并未深究. 然而近期一个项目中对socket的使用却让笔者感觉socket强大无比,可以实现诸多功能. 个人Socket体验 项目主要有关智能家居,需要实现多台手机同时对灯进行操作(开或者关),主要需要实现以下几点: 1.进入界面时获取所有灯的状态. 2.一台手机改变了灯的状态,其他的手机上可以有所显示. 3.硬件上改变了灯的状态(手动开关灯),所有手机上

  • Android Socket通信实现简单聊天室

    socket通信是基于底层TCP/IP协议实现的.这种服务端不需要任何的配置文件和tomcat就可以完成服务端的发布,使用纯java代码实现通信.socket是对TCP/IP的封装调用,本身并不是一种协议,我们通过socket来调用协议来跟服务端进行通信和数据的传输.socket就像客户端与服务端之间的一条信息通道,每一个不同的客户端都会建立一个独立的socket,双方都没有关闭连接的话,连接-也就是建立好的这条socket通道将一直保持,服务端要跟那一个客户端通信只需要找到对应的socket对

  • android使用Socket通信实现多人聊天应用

    使用Socket实现多人聊天应用,供大家参考,具体内容如下 在讲scoket通信器先可以先了解一下网络协议 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在"无差别"的网络之上.可以将网络协议分为四层,从高到低依次为:应用层.传输层.网络层.链路层. 两种Socket类型的基本通信 TCP是一个可靠的.面向连接的协议.它可以保证数据从连接的一方传递到另一方,并且发送数据的顺序

  • Android使用Websocket实现聊天室

    最近的项目中要实现一个聊天的功能,类似于斗鱼TV的聊天室功能,与服务器端人商量后决定用WebSocket来做,但是在这之前我只知道Socket但是听都没有听过WebSocket,但是查看了相关的材料以后发现实现一个聊天室其实是很简单的!下面我们先来看看WebSocket. Autobahn|Android 是由Autobahn开发一个开源的Java/Android网络库,实现了WebSocket协议和Web应用程序消息传输协议来创建本地移动的WebSocket/ WAMP的客服端. WebSoc

  • android Socket实现简单聊天小程序

    android Socket实现简单聊天小程序,供大家参考,具体内容如下 服务器端: package org.hwq.echo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public cla

  • Android基于socket实现的简单C/S聊天通信功能

    本文实例讲述了Android基于socket实现的简单C/S聊天通信功能.分享给大家供大家参考,具体如下: 主要想法:在客户端上发送一条信息,在后台开辟一个线程充当服务端,收到消息就立即回馈给客户端. 第一步:创建一个继续Activity的SocketClientActity类,包为com.pku.net 编写布局文件socketclient.xml,代码如下: <?xml version="1.0" encoding="utf-8"?> <Lin

  • Android Socket实现多个客户端聊天布局

    本文实例为大家分享了Android Socket实现多个客户端聊天布局的具体代码,供大家参考,具体内容如下 服务器Socket接受到客户端发送的消息之后,转发给容器中的其他Socket,别的客户端接受到显示在左边,自己发的显示在右边. 消息类 public class Msg {     private String msg;       private int left_right;       public Msg(String msg,int left_right){         th

随机推荐