聊天室服务端
16lz
2021-01-23
前言
这是我用java写的Android聊天室项目的服务端,当然也可用于java项目。这里写了两个服务端,一个只实现多人聊天,一个可多人,可一对一。
Android客户端
源码
-
服务端1(多人聊天)
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.HashMap;public class Run2 { private final static int PORT = 12345;//自定义端口号 public static ArrayList<Socket> list ; public static void main(String[] args) throws IOException { //重开一条线程启动服务器 new Thread(new startServer()).start(); } static class startServer implements Runnable{ @Override public void run() { try { ServerSocket server = new ServerSocket(PORT); list = new ArrayList<>(); while (true) { Socket client = server.accept(); System.out.println(client); //只要有人连接上就把对应的Socket就存入List集合中 list.add(client); //再开一条线程用来传输数据 //调用构造器,第一个参数是当前的Socket,根据他去获取用户传入的数据 //第二个参数是List集合,通过他去给每个连接上的发送数据 new choicesend2(client,list).start(); } } catch (IOException e) { e.printStackTrace(); } } }}class choicesend2 extends Thread { private Socket socket; private DataOutputStream dos; private DataInputStream dis; public ArrayList<Socket> list; public choicesend2(Socket socket, ArrayList<Socket> list) { this.socket = socket; this.list = list; } @Override public void run() { try { // dis = new DataInputStream(socket.getInputStream()); //这里一定要无限循环,不然只能接收一次消息 while (true) {//使服务器无限循环 //这些都是用来接收用户传来的数据的,可自行更改 String title; String name; String ip; char[] temp = new char[200]; int len = 0; char c = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } title = new String(temp, 0, len); len = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } name = new String(temp, 0, len); len = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } ip = new String(temp, 0, len); System.out.println(ip); //遍历集合,拿出每一个连接的Socket,向他们发送数据 for (Socket socket : list) { if(socket==this.socket) //如果是自己就不发 continue; // 让dos关联每一个Socket,吧数据传出 dos = new DataOutputStream(socket.getOutputStream()); try { dos.writeChars(title); dos.writeChar('\t'); dos.writeChars(name); dos.writeChar('\t'); dos.writeInt(0); dos.flush(); } catch (IOException e) { e.printStackTrace(); } } } }catch (IOException e) { e.printStackTrace(); } }}
-
服务端2(多人聊天+一对一)
问题:我们在多人聊天时是用ArrayList集合来存放每一个连接上的Socket对象,但是显然我们自己无法判断出那个是我要去传输数据的Socket
解决方案:把ArrayList改为HashMap,键存放识别用户的信息,值存放Socket,发送时根据键判断是否要与此时的Socket建立连接
比如我的键传的ip,根据ip判断是否建立连接(显然这种不能在一台电脑上相互传输,(HashMap无重复))
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.HashMap;public class Run { private final static int PORT = 12345; public static ArrayList<Socket> list ; public static HashMap<String,Socket> hs; public static void main(String[] args) throws IOException { new Thread(new startServer()).start(); } static class startServer implements Runnable{ @Override public void run() { try { ServerSocket server = new ServerSocket(PORT); hs = new HashMap<>(); while (true) { Socket client = server.accept(); System.out.println(client); hs.put(client.getInetAddress().toString(),client); new choicesend(client,hs).start(); } } catch (IOException e) { e.printStackTrace(); } } }}class choicesend extends Thread { private Socket socket; private String key; private DataOutputStream dos; private DataInputStream dis; public HashMap<String,Socket> hs; public choicesend(Socket socket, HashMap<String,Socket> hs) { this.socket = socket; this.hs = hs; } @Override public void run() { try { dis = new DataInputStream(socket.getInputStream()); while (true) {//使服务器无限循环 String title; String name; //这里是我传入的ip,与HashMap进行匹配 String ip; char[] temp = new char[200]; int len = 0; char c = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } title = new String(temp, 0, len); len = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } name = new String(temp, 0, len); len = 0; while ((c = dis.readChar()) != '\t') { temp[len] = c; len++; } ip = new String(temp, 0, len); System.out.println(ip); //如果传入的是255.255.255.255说明是群发 if(ip.equals("255.255.255.255")){ for(String sendip : hs.keySet()){ System.out.println(sendip+"集合中的ip"); Socket socket = hs.get(sendip); dos = new DataOutputStream(socket.getOutputStream()); try { // System.out.println("我发了"); dos.writeChars(title); dos.writeChar('\t'); dos.writeChars(name); dos.writeChar('\t'); dos.writeInt(0); dos.flush(); } catch (IOException e) { //list.remove(socket); e.printStackTrace(); } } } //否则用传入的ip与HashMap的键匹配 else{ for(String sendip : hs.keySet()){ // System.out.println(sendip+"集合中的ip"); //刚才通过client.getInetAddress().toString()获取的ip开头是“/”,所以去掉第一位 sendip = sendip.substring(1,sendip.length()); //如果匹配上拿到对应的Socket对象 if(ip.equals(sendip)){ Socket socket = hs.get(sendip); if(socket!=null) dos = new DataOutputStream(socket.getOutputStream()); try { System.out.println("我发了"); dos.writeChars(title); dos.writeChar('\t'); dos.writeChars(name); dos.writeChar('\t'); dos.writeInt(1); dos.flush(); } catch (IOException e) { // list.remove(socket); e.printStackTrace(); } } } } } }catch (IOException e) { e.printStackTrace(); } }}
反思:
这种一对一的局限性显然很大,只能通过ip去匹配,如果想通过id去找人又如何匹配呢?我认为可以写一个注册登录界面,当登录时就可以获取到用户的Socket,用HashMap去维护,键传入id,值传入Socket对象,这样只要是登录的都传进了我们的HashMap,当需要一对一时就可以用id去匹配聊天。
更多相关文章
- Android SQLite数据库操作实例
- 【Android】Android 联系人数据库浅析之通话记录
- android与服务端通信
- android 使用Intent传递数据之剪切板
- Android 内存数据库
- android入门1:有关布局与activity数据传递等
- Android联系人数据库全解析(5)
- android 5.0多用户支持