Socket编程
两个核心类:

ServerSocket——基站类
public ServerSocket(int port)//在本机根据指定端口号创建服务器
public Socket accept()//侦听并接收连接到本服务器的客户端连接,
//此方法会一直阻塞,直到有一个客户端成功连接,返回此连接。

Socket——客户端类
public Socket(String host,int port)//根据指定ip和端口号创建套接字并连接到远程服务器端。
public InputStream getInputStream()//返回此套接字的输入流
public OutputStream getOutputStream()//返回此套接字的输出流

单线程聊天室

服务器类:

import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class singleThreadServer {
    public static void main(String[] args) throws Exception {
        //1.建立基站
        ServerSocket server = new ServerSocket(6666);
        //2.等待客户端连接
        System.out.println("等待客户端连接");
        Socket socket = server.accept();
        //3.建立连接后,进行数据的输入输出
        PrintStream printStream = new PrintStream(socket.getOutputStream(),true,"UTF-8");
        printStream.println("hello,i am server!");
        Scanner scanner = new Scanner(socket.getInputStream());
        if (scanner.hasNext()){
            System.out.println("客户端发来的信息为:"+scanner.nextLine());
        }
        //关闭流
        printStream.close();
        scanner.close();
        socket.close();
    }
}

客户端类:

import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class singleThreadClient {
    public static void main(String[] args) throws Exception {
        //1.建立连接
        Socket socket = new Socket("127.0.0.1",6666);
        //2.进行数据的输入输出
        Scanner scanner = new Scanner(socket.getInputStream());
        if (scanner.hasNext()){
            System.out.println("从服务器发来的信息为:"+scanner.nextLine());
        }
        PrintStream printStream = new PrintStream(socket.getOutputStream(),true,"UTF-8");
        printStream.print("hello,i am client!");
        //3.关闭流
        printStream.close();
        scanner.close();
        socket.close();
    }
}

多线程聊天室

客户端:

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
//读线程
class ReadFromServer implements Runnable{
    private Socket client;
    public ReadFromServer(Socket client) {
        this.client = client;
    }
    @Override
    public void run() {
        try {
            //获取输入流来取得服务器发来的信息
            Scanner in = new Scanner(client.getInputStream());
            while (true){
                if (client.isClosed()){
                    System.out.println("客户端已经关闭");
                    in.close();
                    break;
                }
                if(in.hasNext()){
                    String msgFromServer = in.nextLine();
                    System.out.println("服务器发来的信息为:"+msgFromServer);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

//写线程
class SendMsgToServer implements Runnable{
    private Socket client;
    public SendMsgToServer(Socket client) {
        this.client = client;
    }
    @Override
    public void run() {
        try {
            PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
            Scanner in = new Scanner(System.in);
            while (true){
                System.out.println("请输入要向服务器发送的信息..");
                String strFromUser = "";
                if (in.hasNext()){
                    strFromUser = in.nextLine();
                }
                //向服务器发送信息
                out.println(strFromUser);
                //byebye
                if (strFromUser.contains("byebye")){
                    System.out.println("当前客户端退出聊天室");
                    out.close();
                    in.close();
                    client.close();
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class MutilThreadClient {
    public static void main(String[] args) throws IOException {
        //根据指定ip及端口号建立连接
        Socket client = new Socket("127.0.0.1",6666);
        //启动读线程和写线程
        Thread readThread = new Thread(new ReadFromServer(client));
        Thread sendThread = new Thread(new SendMsgToServer(client));
        readThread.start();
        sendThread.start();
    }
}

服务器:

import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Set;

public class MutilThreadServer {

    private static Map<String,Socket> clientLists = new ConcurrentHashMap<>();
    //专门用来处理每个客户端的输入,输出请求
    private static class ExecuteClientRequest implements Runnable{
        private Socket client;
        public ExecuteClientRequest(Socket client) {
            this.client = client;
        }
        @Override
        public void run() {
            try {
                //获取用户输入流,读取用户发来的信息
                Scanner in = new Scanner(client.getInputStream());
                String strFromClient = "";
                while (true){
                    if (in.hasNext()){
                        strFromClient = in.nextLine();
                    }
                    //windows下消除用户输入自带的\r
                    Pattern pattern = Pattern.compile("\r");
                    Matcher matcher = pattern.matcher(strFromClient);
                    strFromClient = matcher.replaceAll("");

                    /* 注册:username:xxx
                     * 群聊:G:群聊内容
                     * 私聊:P:用户名-私聊内容
                     * 用户退出:byebye*/
                    //注册流程
                    if (strFromClient.startsWith("username:")){
                        String username = strFromClient.split("\\:")[1];
                        Register(username,client);
                    }
                    //群聊流程
                    if (strFromClient.startsWith("G:")){
                        String groupMsg = strFromClient.split("\\:")[1];
                        groupChat(groupMsg);
                    }
                    //私聊
                    if (strFromClient.startsWith("P:")){
                        String username = strFromClient.split("\\:")[1].split("\\-")[0];
                        String privateMsg = strFromClient.split("\\:")[1].split("\\-")[2];
                        privateChat(username,privateMsg);
                    }
                    //用户退出:1:byebye
                    if(strFromClient.contains("byebye")){
                        String username = strFromClient.split("\\:")[0];
                        userOffLine(username);
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private void Register(String username,Socket socket){
            clientLists.put(username,socket);
            System.out.println("用户"+username+"上线了!当前聊天室人数为:"+clientLists.size());
            try {
                PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8");
                out.println("注册成功");
                out.println("当前聊天室人数为:"+clientLists.size());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //群聊——遍历map,向每个客户端输出一遍
        private void groupChat(String groupMsg) throws IOException {
            Set<Map.Entry<String,Socket>> clientEntry = clientLists.entrySet();
            Iterator<Map.Entry<String,Socket>> iterator = clientEntry.iterator();
            while (iterator.hasNext()){
                //取出每一个客户端实体
                Map.Entry<String,Socket> client = iterator.next();
                //拿到客户端输出流输出群聊信息
                PrintStream out = new PrintStream(client.getValue().getOutputStream(),
                        true,"UTF-8");
                out.println("群聊信息为:"+groupMsg);
            }

        }
        //私聊
        private void privateChat(String username,String privateMsg) throws IOException {
            //取出username对应的Socket
            Socket client = clientLists.get(username);
            PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
            out.println("私聊信息为:"+privateMsg);
        }
        private void userOffLine(String username){
            //删除map中的用户实体
            clientLists.remove(username);
            System.out.println("用户"+username+"已下线");

        }
    }
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(6666);
        //使用线程池来同时处理多个客户端连接
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        System.out.println("等待客户端连接");
        for (int i=0;i<20;i++){
            Socket client = serverSocket.accept();
            System.out.println("有新的客户端连接,端口号为:"+client.getPort());
            executorService.submit(new ExecuteClientRequest(client));
        }
        //关闭线程池与服务端
        executorService.shutdown();
        serverSocket.close();
    }
}