聊天室的原理是这样的,一个客户端与服务器建立通讯成功,即客户端socket连接到服务器的ServerSocket之后,服务器端程序将对应的socket加入到容器中,为每一个socket创建一条线程,服务器端读到客户端发来的信息之后,遍历该容器,给容器中的每个socket发送一次,就完成了所有客户端广播。当客户端离开时,向服务器发送一条断开连接信息,从服务器端断开socket,将容器中的对应socket移除掉。
图:
服务器端Server,java:accept通信后,为该socket建立一条线程,开启循环读写操作/*** Created by konghao on 2017/11/8.
*/ public class Server {
static List
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.javapublic 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
@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();}}
}}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:Android常用的数据加密方式代码详解解析Android数据加密之异或加密算法Android数据加密之Base64编码算法的简单实现Android数据加密之Rsa加密的简单实现Android10 客户端事务管理ClientLifecycleManager源码解析Android Socket实现多个客户端聊天布局Android客户端与服务端数据加密传输方案详解
