Java IO和网络编程(续)

作者:陆金龙    发表时间:2024-02-24 05:49   

关键词:  

17.3 基于TCP协议的网络编程



public class MyServer
{
    // 定义保存所有SocketArrayList,并将其包装为线程安全的
    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();
}
}
}

// 负责处理每个线程通信的线程类
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());
                ps.println(content);
            }
        }
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}
// 定义读取客户端数据的方法
private String readFromClient()
{
    try
    {
        return br.readLine();
    }
        // 如果捕捉到异常,表明该Socket对应的客户端已经关闭
    catch (IOException e)
    {
        // 删除该Socket        MyServer.socketList.remove(s);      // ①
    }
    return null;
}
}

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);
}
}
}

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();
    }
}
}