BIO实现:
该程序采用C/S架构
(程序虽然表面上是一个客户端接收其他所有客户端发送过来的消息,其实是每个客户端只对服务器端进行通讯)。
通过IO流进行数据交换。
client:
建立一个socket套接字连接服务器端。
客户端创立两个线程,一个线程负责接收消息,另一个负责发送消息。
server:
每个客户端连上服务端后会在服务端建立一个自定义的管道(MyChannel)
服务端拥有一个储存所有管道的容器。(如list) List userList = new ArrayList();
/**
每个管道内各有一个DataInputStream和DataOutputStream,这两个流都是属于服务器
他们分别连接的是客户端的DataOutputStream和DataInputStream
*/
服务器端只需接收到某一个客户端的消息后把这条消息发送给其他客户端(
for(A a : userlist){
if(this==a)
continue;
a.send()
}
)。
Server端:
/*** 每个客户端连上服务端后会在服务端建立一个自定义的管道(MyChannel)
* 服务端拥有一个储存所有管道的容器。(如userList)
* 每建立一个新的连接后都会把该链接所产生的管道线程扔入userList中*/
public classServer {public static List userList = new ArrayList();public static void main(String[] args) throwsException{
ServerSocket server= new ServerSocket(9999);
System.out.println("------------------Server is Open-----------------");while (true) {
Socket client=server.accept();
MyChannel myChannel= newMyChannel(client);newThread(myChannel).start();
userList.add(myChannel);
}
}
}
/*** 该类是服务器端的管道的实现类
* 每个管道内各有一个DataInputStream和DataOutputStream,
* 他们分别连接的是客户端的DataOutputStream和DataInputStream*/
public class MyChannel implementsRunnable {privateDataInputStream dis;privateDataOutputStream dos;private boolean isStop = false;publicMyChannel(Socket client) {try{
dis= newDataInputStream(client.getInputStream());
dos= newDataOutputStream(client.getOutputStream());
}catch(IOException e) {
isStop= true;
CloseUtil.closeAll(dos,dis,client);
}
}privateString reciveMsg(){
String s= "";try{
s=dis.readUTF();
System.out.println(s);
}catch(IOException e) {
isStop= true;
CloseUtil.closeAll(dis,dos);
Server.userList.remove(this);
}returns;
}private voidsendMsg(String s){if (s != null && !"".equals(s)){try{
dos.writeUTF(s);
dos.flush();
}catch(IOException e) {
isStop= true;
CloseUtil.closeAll(dis,dos);
}
}
}/*** */
private voidsendOther(){
String s= this.reciveMsg();
List userList =Server.userList;for(MyChannel channel : userList) {if (this ==channel)continue;
channel.sendMsg(s);
}
}
@Overridepublic voidrun() {while (!isStop)
sendOther();
}
}
Client端:
public classClient {private static File file = new File("Client.properties");private static Properties properties = newProperties();private static String HOSTNAME = "";private static int PORT = 0;static{if (!file.exists()){try{
file.createNewFile();
FileOutputStream fos= newFileOutputStream(file);
properties.setProperty("hostname","localhost");
properties.setProperty("port","9999");
properties.store(fos,null);
fos.close();
}catch(IOException e) {
e.printStackTrace();
}
}try{
properties.load(newFileInputStream(file));
HOSTNAME= properties.getProperty("hostname");
PORT= Integer.parseInt(properties.getProperty("port"));
}catch(IOException e) {
e.printStackTrace();
}
}public static void main(String[] args) throwsException{
Socket client= newSocket(HOSTNAME,PORT);
Scanner input= newScanner(System.in);
System.out.println("客户端已启动,请输入您的昵称:");
String name=input.next();
System.out.println("已进入聊天室!");new Thread(newSendRun(client),name).start();new Thread(newReceiveRun(client),name).start();
}
}
ReceiveRun
1 public class SendRun implementsRunnable {2
3 private DataOutputStream dos = null;4 private boolean isStop = false;5 private BufferedReader br = null;6
7 publicSendRun(Socket client) {8 try{9 br = new BufferedReader(newInputStreamReader(System.in));10 dos = newDataOutputStream(client.getOutputStream());11 } catch(IOException e) {12 isStop = true;13 CloseUtil.closeAll(dos);14 }15 }16
17 private voidsendMessage(){18 try{19 dos.writeUTF(Thread.currentThread().getName()+"-->说:"+br.readLine());20 dos.flush();21 } catch(IOException e) {22 isStop = true;23 CloseUtil.closeAll(br,dos);24 }25 }26
27 @Override28 public voidrun() {29 while (!isStop){30 this.sendMessage();31 }32 }33 }
SendRun
Util类:
1 public classCloseUtil {2 public static voidcloseAll(Closeable ... closeables){3 for(Closeable clo: closeables) {4 if (clo!=null) {5 try{6 clo.close();7 } catch(IOException e) {8 e.printStackTrace();9 }10 }11 }12 }13 }
View Code