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

Honey ·
更新时间:2024-11-01
· 501 次阅读

聊天室的原理是这样的,一个客户端与服务器建立通讯成功,即客户端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();             }         }     } }



客户端 通信

需要 登录 后方可回复, 如果你还没有账号请 注册新账号