加入多线程
前面Server和Client只是进行了简单的通信操作服务器接收到客户端连接之后服务器向客户端输出一个字符串而客户端也只是读取服务器的字符串后就退出了实际应用中的客户端则可能需要和服务器端保持长时间通信即服务器需要不断地读取客户端数据并向客户端写入数据客户端也需要不断地读取服务器数据并向服务器写入数据
当我们使用传统BufferedReader的readLine()方法读取数据时当该方法成功返回之前线程被阻塞程序无法继续执行考虑到这个原因因此服务器应该为每个Socket单独启动一条线程每条线程负责与一个客户端进行通信
客户端读取服务器数据的线程同样会被阻塞所以系统应该单独启动一条线程该线程专门负责读取服务器数据
下面考虑实现一个命令行界面的C/S聊天室应用服务器端则应该包含多条线程每个Socket对应一条线程该线程负责读取Socket对应输入流的数据(从客户端发送过来的数据)并将读到的数据向每个Socket输出流发送一遍(将一个客户端发送的数据广播给其他客户端)因此需要在服务器端使用List来保存所有的Socket
下面是服务器端的实现代码程序为服务器提供了个类一个是创建ServerSocket监听的主类一个是负责处理每个Socket通信的线程类
程序清单codes///MultiThread/server/MyServerjava
public class MyServer
{
//定义保存所有Socket的ArrayList
public static ArrayList<Socket> socketList = new ArrayList<Socket>()
public static void main(String[] args)
throws IOException
{
ServerSocket ss = new ServerSocket()
while(true)
{
//此行代码会阻塞将一直等待别人的连接
Socket s = ssaccept()
socketListadd(s)
//每当客户端连接后启动一条ServerThread线程为该客户端服务
new Thread(new ServerThread(s))start()
}
}
}
上面程序是服务器端只负责接受客户端Socket的连接请求每当客户端Socket连接到该ServerSocket之后程序将对应Socket加入socketList集合中保存并为该Socket启动一条线程该线程负责处理该Socket所有的通信任务如程序中四行粗体字代码所示服务器端线程类的代码如下
程序清单codes///MultiThread/server/ServerThreadjava
//负责处理每个线程通信的线程类
public class ServerThread implements Runnable
{
//定义当前线程所处理的Socket
Socket s = null;
//该线程所处理的Socket所对应的输入流
BufferedReader br = null;
public ServerThread(Socket s)
throws IOException
{
thiss = s;
//初始化该Socket对应的输入流
br = new BufferedReader(new InputStreamReader(sgetInputStream()))
}
public void run()
{
try
{
String content = null;
//采用循环不断从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null)
{
//遍历socketList中的每个Socket
//将读到的内容向每个Socket发送一次
for (Socket s : MyServersocketList)
{
PrintStream ps = new PrintStream(sgetOutputStream())
psprintln(content)
}
}
}
catch (IOException e)
{
//eprintStackTrace()
}
}
//定义读取客户端数据的方法
private String readFromClient()
{
try
{
return brreadLine()
}
//如果捕捉到异常表明该Socket对应的客户端已经关闭
catch (IOException e)
{
//删除该Socket
MyServersocketListremove(s) //①
}
return null;
}
}
上面服务器端线程类不断读取客户端数据程序使用readFromClient()方法来读取客户端数据如果读取数据过程中捕获到IOException异常则表明该Socket对应的客户端Socket出现了问题(到底什么问题我们不管反正不正常)程序就将该Socket从socketList中删除如readFromClient()方法中①号代码所示
[] []