MyServer.java
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
public class MyServer{
//定义保存所有Socket的ArrayList,并将其包装为线程安全的
public static List<Socket> socketList
= Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) throws IOException{
ServerSocket ss = new ServerSocket(30000);
while(true){
//此行代码会阻塞,将一直等待别人的连接
Socket s = ss.accept();
socketList.add(s);
//每当客户端连接后启动一个ServerThread线程为该客户端服务
new Thread(new ServerThread(s)).start();
}
}
}
ServerThread
import java.net.Socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
//负责处理每个线程通信的线程类
public class ServerThread implements Runnable{
//定义当前线程所处理的Socket
Socket s = null;
//该线程所处理的Socket对应的输入流
BufferedReader br = null;
public ServerThread(Socket s) throws IOException{
this.s = s;
//初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}
public void run(){
try{
String content = null;
//采用循环不断地从Socket中读取客户端发过来的数据
while((content = readFromClient()) != null){
//遍历socketList中的每个Socket
//将读到的内容向每个Socket发送一次
for(Socket s : MyServer.socketList){
PrintStream ps = new PrintStream(s.getOutputStream());
System.out.println(content);
ps.println(content);
}
}
}catch (IOException e){
e.printStackTrace();
}
}
//定义读取客户端数据的方法
private String readFromClient(){
try{
Thread.sleep(10000);
return br.readLine();
}
//如果捕获到异常,则表明该Socket对应的客户端已经关闭
catch(Exception e){
//删除该Socket
MyServer.socketList.remove(s);
}
return null;
}
}
MyClient
import java.net.Socket;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MyClient{
public static void main(String[] args) throws Exception{
Socket s = new Socket("127.0.0.1", 30000);
//客户端启动ClientThread线程不断地读取来自服务器的数据
new Thread(new ClientThread(s)).start();
//获取该Socket对应的输出流
PrintStream ps = new PrintStream(s.getOutputStream());
String line = null;
//不断地读取键盘输入
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
while((line = br.readLine()) != null){
//将用户的键盘输入内容写入Socket对应的输出流
ps.println(line);
}
}
}
ClientThread
import java.net.Socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ClientThread implements Runnable{
//该线程负责处理的Socket
private Socket s;
//该线程所处理的Socket对应的输入流
BufferedReader br = null;
public ClientThread(Socket s) throws IOException{
this.s = s;
br = new BufferedReader(
new InputStreamReader(s.getInputStream()));
}
public void run(){
try{
String content = null;
//不断地读取Socket输入流中的内容,并将这些内容打印输出
while((content = br.readLine()) != null){
System.out.println(content);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
照着书敲得,实现一个命令行聊天。
问题是:MyClient中控制台输入阻塞,当我输入数据时,ServerThread可以通过Socket的输入流获取数据,而ClientThread中的Socket的输入流不能(这里的输入流是为了获取ServerThread中输出数据的时候才用上)。