在服务器端应该包含多条线程,每个Socket对应一条线程,该线程负责读取Socket对应的输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一遍(将一个客户端发送的数据广播给其他客户端),因此需要在服务端使用List来保存所有的Socket。
服务器端提供两个类:
创建ServerSocket监听的主类;
处理每个Socket通信的线程类;
public class IServer {
public static ArrayList<Socket> socketList=new ArrayList<Socket>();
public static void main(String[] args) throws IOException{
ServerSocket ss=new ServerSocket(30000);
while(true) {
Socket s=ss.accept();
socketList.add(s);
new Thread(new Serverxian(s)).start();
}
}
}
服务器端只负责接受客户端Socket的连接请求,每当客户端Socket连接诶到该ServerSocket之后,程序将对应Socket加入socketList集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务。
public class Serverxian implements Runnable{
Socket s=null;
BufferedReader br=null;
public Serverxian(Socket s) throws IOException{
this.s=s;
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run() {
try {
String content=null;
while((content=readFromClient())!=null) {
for(Socket s:IServer.socketList) {
PrintStream ps=new PrintStream(s.getOutputStream());
ps.println(content);
}
}
}catch(IOException e) { }
}
private String readFromClient() {
try {
return br.readLine();
}catch(IOException e) {
IServer.socketList.remove(s);
}
return null;
}
}
捕获到异常,则说明客户端Socket出现了问题,删除掉;读到客户端数据之后遍历整个集合,转发数据。
每个客户端应包含的两条线程:
1、一条负责读取用户的键盘输入,并将用户输入的数据写入Socket对应的输出流中;
2、一条负责读取Socket对应输入流中的数据(从服务器发送过来的数据),并将爱那个这些数据打印输出。
public class ICilent {
public static void main(String[] args) throws IOException{
Socket s=new Socket("127.0.0.1",30000);
new Thread(new Clientxian(s)).start();
PrintStream ps=new PrintStream(s.getOutputStream());
String line=null;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
while((line=br.readLine())!=null) {
ps.println(line);
}
}
}
线程读到数据后,会将用户键盘输入的内容写入该Socket对应的输出流。当主线程使用Socket连接到服务器后,会启动Clientxian来处理该线程的Socket通信。
public class Clientxian implements Runnable{
private Socket s;
BufferedReader br=null;
public Clientxian(Socket s)throws IOException{
this.s=s;
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run() {
try {
String content=null;
while((content=br.readLine())!=null) {
System.out.println(content);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
线程处理文件,负责读取Socket输入流中的内容,并将这些内容在控制台打印出来。