1.perface:
上一章中聊天程序存在着不足如下:
1. 无法实现多客户端的聊天
2.客户信息存储问题
3.服务器转发同步问题:
现在解决如下:见如下代码:
2.service:code:
client:
class exp_client implements Runnable { Socket cs = null; String hostName = "localhost"; int port = 8000; DataInputStream is = null; static DataOutputStream os = null; static DataInputStream stdIn = null; exp_client(String hostName, int port) { this.hostName = hostName; this.port = port; } public void run() { try { cs = new Socket(hostName, port); is = new DataInputStream(cs.getInputStream()); os = new DataOutputStream(cs.getOutputStream()); stdIn = new DataInputStream(System.in); System.out.println("客户端"); os.writeUTF("你好服务器!"); os.flush(); new rcThread(cs).start(); // 启动接收线程 new scThread(cs).start(); // 启动发送线程 } catch (Exception e) { System.err.println(e); } } }
2.2 发送和接受线程如下:
class scThread extends Thread { // 自定义发送线程内部类 Socket client; DataOutputStream is = null; private DataInputStream stdIn; DataOutputStream os = exp_client.os; scThread(Socket client) throws Exception { this.client = client; is = new DataOutputStream(client.getOutputStream()); stdIn = new DataInputStream(System.in); } public void run() { String str; try { while (true) { str = stdIn.readLine(); os.writeUTF(client.getInetAddress().toString() + ":" + client.getLocalPort() + ":" + str); os.flush(); } } catch (Exception e) { System.err.println(e.toString()); } } }
2.3 接受线程类:
class rcThread extends Thread { // 自定义接收线程内部类 Socket client; DataInputStream is = null; private DataInputStream stdIn=exp_client.stdIn; rcThread(Socket client) throws Exception { this.client = client; is = new DataInputStream(client.getInputStream()); } public void run() { String str; stdIn = new DataInputStream(System.in); try { while (true) { str = is.readUTF(); System.out.println(str); } } catch (Exception e) { System.err.println(e.toString()); } } }
2.4 服务器代码如下:
class MyServer implements Runnable { static Vector<Socket> clients = new Vector(); ServerSocket ss = null; MyServer(int port) { try { ss = new ServerSocket(port); // 端口号唯一标是本进程 System.out.println("启动本地" + port + "端口"); } catch (IOException e) { System.err.println("启动本地" + port + "端口失败"); System.exit(1); } } public void run() { Socket cs = null; try { while (true) { cs = ss.accept(); clients.add(cs); clientThread ct = new clientThread(cs); Thread tct = new Thread(ct); tct.start(); } } catch (IOException e) { System.err.println(e.toString()); } } } 2.5 server 线程如下:
class clientThread implements Runnable { Socket cs = null; clientThread(Socket cs) { this.cs = cs; } public void run() { String inputStr, outputStr; try { DataOutputStream os = new DataOutputStream(cs.getOutputStream()); DataInputStream is = new DataInputStream(cs.getInputStream()); DataOutputStream cos = null; os.writeUTF("Welcome to My Chat Server"); os.flush();// 立即将数据从输出缓存提交给网络发送 while ((inputStr = is.readUTF()) != null) { System.out.println("Customer:" + inputStr); outputStr = inputStr; // 将接收到的信息转发出去 for (Socket c : MyServer.clients) { cos = new DataOutputStream(c.getOutputStream()); cos.writeUTF(outputStr); cos.flush(); } } os.close(); // 流关闭 is.close(); cs.close(); // 套接字关闭 } catch (IOException e) { System.err.println(e.getMessage()); } } }
测试代码:
public class StartClient { public static void main(String[] args) { exp_client ec = new exp_client("localhost", 8000); Thread tec = new Thread(ec); try { tec.start(); tec.join(); } catch (Exception e) { System.err.println(e); } } }
public class StartServer { public static void main(String[] args) { MyServer ms = new MyServer(8000); Thread tms = new Thread(ms); tms.start(); } }
3.reference: