C/S聊天室分为服务器端和客户端,均需要采用多线程来实现。
服务器端主线程需要不断地监听端口,一旦有客户端的请求时,产生相应的Socket,将其加入到队列中并启动子线程,子线程负责接收客户端消息(使用Socket的getInputStream()函数来处理),再将消息发送到所有的客户端(使用Socket的getOutputStream()函数)。
客户端主线程负责获取键盘输入(相当于侦听键盘输入),并传递给Socket的输出流(使用Socket的getOutputStream(),为什么这里是getOutputStream(),因为对Socket而言是输出流),而子线程负责取得服务器端发过来的消息(使用Socket的getInputStream())。
代码如下,代码没有实现界面:
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class Server { private final int PORT=30000; public static ArrayList<Socket> socketList=new ArrayList<Socket>(); public void init() { try ( ServerSocket serverSocket=new ServerSocket(PORT); ) { while(true) { Socket socket=serverSocket.accept(); socketList.add(socket); new Thread(new ServerThread(socket)).start(); } }catch (IOException e) { // TODO Auto-generated catch block System.out.println("服务器启动失败,是否"+PORT+"端口已被占用?"); } } public static void main(String[] args) { // TODO Auto-generated method stub Server s=new Server(); s.init(); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; public class ServerThread implements Runnable { private Socket s=null; private BufferedReader br=null; public ServerThread(Socket s) { this.s=s; } @Override public void run() { // TODO Auto-generated method stub try { br=new BufferedReader(new InputStreamReader(s.getInputStream())); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("Socket对应的输入流获取失败!"); } String content=null; while((content=readFromClient())!=null) { for(Socket s:Server.socketList) { try ( PrintStream ps=new PrintStream(s.getOutputStream()); // 让该程序通过该输出流向socket中输出数据 ) { ps.println(content); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } private String readFromClient() { // TODO Auto-generated method stub try { return br.readLine(); } catch (IOException e) { // TODO Auto-generated catch block Server.socketList.remove(s); } return null; } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException; public class Client { private final static int PORT=30000; private final static String host="127.0.0.1"; public static void main(String[] args) throws UnknownHostException, IOException { // TODO Auto-generated method stub Socket s=new Socket(host,PORT); new Thread(new ClientThread(s)).start(); // 子线程完成与服务器通信 PrintStream ps=new PrintStream(s.getOutputStream()); // 让程序通过该输出流向Socket中输出数据,得到了socket的输出流 String line=null; BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); // br.readline()不断读取键盘输入内容 while((line=br.readLine())!=null) { ps.println(line); } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; public class ClientThread implements Runnable { private Socket s=null; private BufferedReader br=null; public ClientThread(Socket s) throws IOException { this.s=s; br=new BufferedReader(new InputStreamReader(s.getInputStream())); // 该句只是返回了这样一个对象,里面并不包含屏幕中的语句 } // 其用readline()的时候才得到输入语句 @Override public void run() { // TODO Auto-generated method stub String content=null; try { while((content=br.readLine())!=null) // readline()遇到输入末尾的时候才会返回null { System.out.println(content); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
原文地址:http://blog.csdn.net/a0agd1x50/article/details/37612579