Java 使用Socket实现多线程发送 POST json 请求

多个线程对服务器发送POST请求,每个线程使用不同的端口(已修正)

并统计总响应时间、成功请求数、平均响应时间

更新日志:

  • socketPostRaw 中将注释掉的行改为红色行。若 new Socket 时不绑定发送端 ip 和 port 则为短连接,绑定为长连接,导致端口长时间不被释放,必须超时才会释放。
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

import net.minidev.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PostSender {
    private static final Logger log = LoggerFactory.getLogger(PostSender.class);

    final String targetHost = "127.0.0.1";
    final String requestUrl = "/kill/kill/execute/unlock";
    final int portBegin = 21000;
    final int threadNum = 10000;

    public void threadTest() {
        CountDownLatch cdLatch = new CountDownLatch(threadNum);
        Map<Integer, Double> responseTimeMap = new ConcurrentHashMap<>();

        long start = System.currentTimeMillis();
        for (int i = 1; i <= threadNum; i++) {
            Thread thread = new Thread(new MyRunnable(i, responseTimeMap, cdLatch));
            thread.start();
        }

        try {
            cdLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        long end = System.currentTimeMillis();

//        System.out.println("\nall response time:");
        double timesum = 0.0;
        for (Integer uid :
                responseTimeMap.keySet()) {
            double time = responseTimeMap.get(uid);
            timesum += time;
//            System.out.printf("%.0f\n", time);
        }

        Double avgTime = timesum / responseTimeMap.keySet().size();
        System.out.println("\ntotal time: " + (end - start));
        System.out.println("successful connection: " + responseTimeMap.size());
        System.out.printf("avg response time: %.0f\n", avgTime);
    }

    public static void main(String[] args) {
        PostSender ps = new PostSender();
        ps.threadTest();
    }


    class MyRunnable implements Runnable {
        private final int userId;
        private final Map<Integer, Double> timeMap;
        private final CountDownLatch latch;

        public MyRunnable(int userId, Map<Integer, Double> timeMap, CountDownLatch cdLatch) {
            this.userId = userId;
            this.timeMap = timeMap;
            this.latch = cdLatch;
        }

        @Override
        public void run() {
            socketPostRaw();
            latch.countDown();
        }

        public void socketPostRaw() {
            try (Socket socket = new Socket(InetAddress.getLocalHost(), 8092);
// Socket socket = new Socket(InetAddress.getLocalHost(), 8092, InetAddress.getLocalHost(), portBegin + userId);
                 OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8);
                 BufferedReader in = new BufferedReader(new InputStreamReader(new BufferedInputStream(socket.getInputStream()), StandardCharsets.UTF_8));
            ) {

                JSONObject obj = new JSONObject();
                obj.put("killId", "3");
                obj.put("userId", String.valueOf(userId));

                String data = obj.toJSONString();

                out.write("POST " + requestUrl + " HTTP/1.1\r\n");
                out.write("Host: " + targetHost + "\r\n");
                out.write("Content-Length: " + data.length() + "\r\n");
                out.write("Content-Type: application/json; charset=UTF-8\r\n");
//            out.write("Content-Type: application/x-www-form-urlencoded\r\n");
                out.write("\r\n");
                out.write(data);
                out.flush();
                out.write("\r\n");
                out.flush();
                socket.shutdownOutput();


                //开始计时
                long start = System.currentTimeMillis();

//            //打印响应
                String line = "";
                while ((line = in.readLine()) != null) {
//                    System.out.println(line);
                }

                long end = System.currentTimeMillis();
                long time = end - start;
                timeMap.put(userId, (double) time);


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

    }


}