1.群聊

客户端

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {


        // 1. 创建Socket对象,并把请求与服务端的端口连接
        Socket socket = new Socket("127.0.0.1", 8888);
        new ClientReaderThread(socket).start();//启动一个线程来读取服务端的响应

        // 2. 从socket通信管道中得到一个字节输出流,用来发送数据给服务端的数据
        OutputStream os = socket.getOutputStream();

        // 3. 把低级的字节输出流包装成数据输出流
        DataOutputStream dos = new DataOutputStream(os);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请说:");
            String msg = sc.nextLine();

            // 一旦用户输入了exit,就退出客户端程序
            if ("exit".equals(msg)) {
                System.out.println("欢迎您下次光临!退出成功!");
                dos.close();
                socket.close();
                break;
            }

            // 4. 开始写数据出去
            dos.writeUTF(msg);
            dos.flush();
        }

    }
}

客户端线程

package com.lzk.test;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ClientReaderThread extends Thread {
    private Socket socket;

    public ClientReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        try {
            InputStream inputStream = socket.getInputStream();
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            while (true) {
                try {
                    String message = dataInputStream.readUTF();
                    System.out.println("Server received message: " + message);

                } catch (IOException e) {
                    System.out.println("自己下线了." + socket.getRemoteSocketAddress());

                    dataInputStream.close();
                    inputStream.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
        }
    }
}

服务端

package com.lzk.test;

import java.net.*;
import java.util.ArrayList;
import java.util.List;


public class server {
    public static List<Socket> onLineSocket = new ArrayList<Socket>();
    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(8080);


        // 5. 使用数据输入流读取客户端发送过来的消息
        while (true) {

        Socket socket = serverSocket.accept();
        System.out.println( socket.getRemoteSocketAddress() + "客户端连接成功");
        onLineSocket.add(socket);//将客户端的socket添加到在线socket列表中
        new ServerReaderThread(socket).start();


    }
}



    }

服务端线程

package com.lzk.test;

import java.io.*;
import java.net.Socket;

public class ServerReaderThread extends Thread {
    private Socket socket;

    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        try {
            InputStream inputStream = socket.getInputStream();
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            while (true) {
                try {
                    String message = dataInputStream.readUTF();
                    System.out.println("Server received message: " + message);
                    sendMessageToAllClients(message);
                } catch (IOException e) {
                    System.out.println("Server reader thread stopped." + socket.getRemoteSocketAddress());
                    server.onLineSocket.remove(socket);//从在线列表中移除
                    dataInputStream.close();
                    inputStream.close();
                    socket.close();
                    break;
                }
            }
        } catch (IOException e) {
        }
    }

    private void sendMessageToAllClients(String message) throws IOException {
        for (Socket onLineSocket : server.onLineSocket) {
            OutputStream os = onLineSocket.getOutputStream();
            DataOutputStream dos = new DataOutputStream(os);
            dos.writeUTF(message);
            dos.flush();

        }
    }
}

2.实现一个简易的BS架构

只需要开发服务端,不需要开发浏览器。

要求:从浏览器中访问服务器,并让服务器响应一个很简单的网页给浏览器展示,内容是“123456”.

注意:服务器必须给浏览器响应HTTP协议规定的数据格式,否则浏览器不识别返回的数据。

通信案例_System

客户端

public class server {
    public static List<Socket> onLineSocket = new ArrayList<Socket>();
    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(8080);


        // 5. 使用数据输入流读取客户端发送过来的消息
        while (true) {

        Socket socket = serverSocket.accept();
        System.out.println( socket.getRemoteSocketAddress() + "客户端连接成功");
        onLineSocket.add(socket);//将客户端的socket添加到在线socket列表中
        new ServerReaderThread(socket).start();


    }
}



    }

接口

import java.io.*;
import java.net.Socket;

public class ServerReaderThread extends Thread {
    private Socket socket;

    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        try {
            OutputStream os = socket.getOutputStream();
            PrintStream ps = new PrintStream(os);
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println(); // 必须换行
            ps.println("<div style='color:red;font-size:120px;text-align:center;'>123456</div>");
            ps.close();
            socket.close();

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


}

3.拓展知识

每次请求都开一个新线程在高并发时,容易宕机。

可以使用线程池来改进,代码比上面其实改动不大。

public class server {
    public static List<Socket> onLineSocket = new ArrayList<Socket>();

    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(8080);

        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                24,
                24,
                2,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<>(8),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        while (true) {
            Socket socket = serverSocket.accept();
            pool.execute(new ServerReaderRunnable(socket));
        }


    }

}

实现类

public class ServerReaderRunnable implements Runnable {
    private Socket socket;

    public ServerReaderRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        try {
            OutputStream os = socket.getOutputStream();
            PrintStream ps = new PrintStream(os);
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println(); // 必须换行
            ps.println("<div style='color:red;font-size:120px;text-align:center;'>123456</div>");
            ps.close();
            socket.close();

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


}