很久以前的一个Demo,这里服务器只做转发功能,根据ID地址和端口号来标识身份,群聊和私聊只是简单实现,
服务器代码如下:
import java.util.*; import java.io.*; import java.net.*; public class Server extends Thread { private static Vector<Socket> vecClient = new Vector<Socket>(); private PrintWriter out; private BufferedReader in; private Socket clientsocket; public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2014); // 创建 System.out.println("启动服务器! "); Socket sock; while (true) { sock = server.accept(); // 等待客户请求 Server ser = new Server(sock); ser.start(); // 启动 } } public Server(Socket socket) { this.clientsocket = socket; vecClient.addElement(socket); // 增加客户线程到数组 try { // 获取服务端传来的字节流好,存到缓冲区 in = new BufferedReader(new InputStreamReader( socket.getInputStream())); // printwriter,文本输出流打印对象的格式化表示形式,只有调用println等,自动刷新即true,强行把缓冲区的数据输出。 out = new PrintWriter(new OutputStreamWriter( socket.getOutputStream()), true); // input、OutputStreamWriter 是字符流通向字节流的桥梁 } catch (IOException e) { } } public void run() { try { Newclient(); // 向新客户发出欢迎信息,通知所有在线客户有新客户连接了 while(true) // 处理与客户的交流 { String msg=in.readLine(); //数据读取 if(msg.equals("bye")|| msg.equals("拜拜"))//当输入拜拜或bye时候退出 { Xiaxian(); in.close(); // 关闭输入流 clientsocket.close(); // 关闭socket break; } else if(msg.indexOf("@")==0&&msg.indexOf(" ")>0){ int end=msg.indexOf(" "); String findAddr=msg.substring(1,end); if(vecClient.isEmpty() == false) //判断为空 { for(int i=0;i<vecClient.size();i++) { Socket socket = vecClient.get(i); String addr = socket.getInetAddress().toString().replace("/", "") + ":" + socket.getPort(); if(findAddr.equals(addr)){ String addr2 = clientsocket.getInetAddress().toString().replace("/", "") + ":" + clientsocket.getPort(); //elementAt返回指定索引处的组件,而get返回列表中指定位置处的元素 PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient.get(i).getOutputStream()),true); pw.println("大神"+addr2+" 对你 说: "+msg.substring(end)); } } } } // 否则将接收到的信息向所有在线客户发出去 else { if(vecClient.isEmpty() == false) for(int i=0;i<vecClient.size();i++) { //elementAt返回指定索引处的组件,而get返回列表中指定位置处的元素 PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient.get(i).getOutputStream()),true); pw.println("大神"+clientsocket.getInetAddress().toString()+":"+clientsocket.getPort()+" 说: "+msg); } } } } catch(IOException e) { } } public void Newclient() throws IOException // 新来的,用此函数 { String addr = clientsocket.getInetAddress().toString() + ":" + clientsocket.getPort(); out.println("欢迎:" + addr+"加入! "); try { if (vecClient.isEmpty() == false) for (int i = 0; i < vecClient.size(); i++) { Socket socket = vecClient.get(i); PrintWriter pw = new PrintWriter(new OutputStreamWriter( socket.getOutputStream()), true); String addr2 = socket.getInetAddress().toString() + ":" + socket.getPort(); if (addr.equals(addr2)) { pw.println("欢迎加入聊天,私聊请用@ip:port 内容"); } else { pw.println("新成员:" + clientsocket.getInetAddress().toString() + ":" + clientsocket.getPort() + " 嗨起来吧!"); } } } catch (IOException e) { } } public void Xiaxian() throws IOException // 下线方法 { out.println("再见,连接关闭!"); if (vecClient.isEmpty() == false) for (int i = 0; i < vecClient.size(); i++) { PrintWriter pw = new PrintWriter(new OutputStreamWriter(vecClient .get(i).getOutputStream()), true); pw.println("--" + clientsocket.getInetAddress().toString() + ":" + clientsocket.getPort() + " 已经下线"); } vecClient.remove(clientsocket); } }
客服端,可在本地命令运行多个测试,私聊格式:@ip:port(这里必须有空格)内容,原理如下:
import java.net.*; import java.io.*; import java.util.*; class Client { public static void main(String[] args) { try { Socket socket=new Socket("localhost",2014); ClientSend send=new ClientSend(socket); // 创建发送线程 ClientReceive receive=new ClientReceive(socket); // 创建接收线程 send.start(); // 启动发送线程 receive.start(); // 启动接收线程 } catch(Exception e) { System.out.println("服务器没有开启呢!"); e.printStackTrace(); } } } class ClientSend extends Thread { private Socket socket; private PrintWriter out; public ClientSend(Socket socket) { this.socket=socket; try { out=new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true); //返回一个服务器与客户端的输出流,true强行把缓冲区的数据输出 } catch(IOException e) { e.printStackTrace(); } } public void run() // 发送信息到服务器 { String msg; Scanner input=new Scanner(System.in);//输入 msg = input.nextLine(); //nextLine方法返回的是回车之前的所有字符 while(true) { //用equalsIgnoreCase可忽略大小写 if(msg.equals("bye") || msg.equals("拜拜")) { out.println(msg); break; } out.println(msg); msg = input.nextLine(); } } } class ClientReceive extends Thread //接收 { private Socket socket; private BufferedReader in; public ClientReceive(Socket socket) { this.socket= socket; try { in=new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch(IOException e) { e.printStackTrace(); } } public void run() // 接收服务器发来的信息 { try { String msg=in.readLine(); while(msg.equals("bye") == false) { System.out.println(msg); msg=in.readLine(); } in.close(); socket.close(); } catch(IOException e) { e.printStackTrace(); } } }
时间: 2024-12-15 20:15:39