您的位置:首页 > 其它

命令行界面的C/S聊天室应用 (Socket多线程实现)

2015-02-08 17:20 561 查看
命令行界面即在Eclipe控制台输入数据。

服务器端包含多个线程,每个Socket对应一条线程,该线程负责读取对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一遍(将一个客户端发送的数据"广播给其他客户端"),因此需要在服务器端使用List来保存所有的Socket.

下面是服务器端的实现代码,程序为服务器提供了两个类,一个是创建ServerSocket监听的主类,一个是负责处理每个Socket通信的线程类.

packagecom.net.scday1; importjava.io.IOException; importjava.net.ServerSocket; importjava.net.Socket; importjava.util.ArrayList; publicclassMyServer{ //定义保存所有Socket的ArrayList publicstaticArrayList<Socket>scoketList=newArrayList<Socket>(); publicstaticvoidmain(String[]args){ try{ ServerSocketss=newServerSocket(30000); while(true){ //此代码会阻塞,将一直等待别人的连接 Sockets=ss.accept(); scoketList.add(s); //每当客户端连接后启动一条ServerThread线程为该客户端服务 newThread(newServerThread(s)).start(); } }catch(IOExceptione){ e.printStackTrace(); } } }

packagecom.net.scday1; importjava.io.BufferedReader; importjava.io.IOException; importjava.io.InputStreamReader; importjava.io.PrintStream; importjava.net.Socket; /** *负责处理每个线程通信的线程类 *@authoryulei * */ publicclassServerThreadimplementsRunnable{ //定义当前线程所处理的Socket Sockets=null; //该线程所处理Socket所对应的输入流 BufferedReaderbr=null; publicServerThread(Sockets)throwsIOException{ this.s=s; //初始化该Socket对应的输入流 br=newBufferedReader(newInputStreamReader(s.getInputStream())); } publicvoidrun(){ try{ Stringcontent=null; //采用循环不断从Socket中读取客户端发送过来的数据 while((content=readFromClient())!=null){ //遍历SocketList中的每个Socket //将读到的内容向每个Socket发送一次 for(Sockets:MyServer.scoketList){ PrintStreamps=newPrintStream(s.getOutputStream()); ps.println(content); } } }catch(Exceptione){ } } //定义读取客户端数据的方法 privateStringreadFromClient(){ try{ returnbr.readLine(); //如果捕获到异常,表明该Socket对应的客户端已经关闭 }catch(IOExceptione){ //删除该Socket MyServer.scoketList.remove(s); } returnnull; } }

每个客户端应包含两条线程:一条负责读取用户的键盘输入,并将用户的输入数据写入Socket对应的输出流中;一条负责读取Socket对应输入流中的数据(从服务器发送过来的数据),并将这些数据打印输出。其中,负责读取用户键盘输入的线程由MyClinet负责,也就是由程序的主线程负责。客户端程序代码如下:

packagecom.net.scday1; importjava.io.BufferedReader; importjava.io.InputStreamReader; importjava.io.PrintStream; importjava.net.Socket; publicclassMyClient{ publicstaticvoidmain(String[]args)throwsException{ Sockets=newSocket("127.0.0.1",30000); //客户端启动ClientThread线程不断读取来自服务器的数据 newThread(newClientThread(s)).start(); //获取该Socket对应的输出流 PrintStreamps=newPrintStream(s.getOutputStream()); Stringline=null; //不断读取键盘输入 BufferedReaderbr=newBufferedReader(newInputStreamReader(System.in)); while((line=br.readLine())!=null){ if(""==line||"".equals(line.trim())){ System.out.println("不允许发送空数据!"); }else{ //将用户的键盘输入内容写入Socket对应的输出流 ps.println(line); } } } }

packagecom.net.scday1; importjava.io.BufferedReader; importjava.io.IOException; importjava.io.InputStreamReader; importjava.net.Socket; publicclassClientThreadimplementsRunnable{ //该线程负责处理的Socket privateSockets; //该线程所处理的Socket所对应的输入流 BufferedReaderbr=null; publicClientThread(Sockets)throwsIOException{ this.s=s; br=newBufferedReader(newInputStreamReader(s.getInputStream())); } @Override publicvoidrun(){ try{ Stringcontent=null; //不断读取Socket输入流中的内容,并将这些内容打印输出 while((content=br.readLine())!=null){ System.out.println(content); } }catch(Exceptione){ } } }

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: