Ajax与Socket多线程通信

软件层面的网络通信底层均有Socket实现,这里尝试使用Ajax与Socket进行通讯。
出于简化,省略掉了IO流和Socket的关闭。

页面设计

Ajax与Socket多线程通信_第1张图片
页面设计了两个按钮,通过ajax以post方式向端口发送消息,消息内容分别为action A和action B,便于接收端区分。


<html>
<head>
    <title>Machi | Hometitle>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <meta name="keywords" content="Machi">
    <script src="jq/jquery-3.3.1.min.js" type="text/javascript">script>

    <script type="text/javascript">
        function ASendByAjax() {
            $.ajax({
                url: 'http://localhost:10000/',
                type: 'post',
                data: {
                    "action": "A",
                },
                dataType: "json",
                success: function (info) {
                    console.log("A success:"+info) 
                },
                error: function (error, Msgerror) {
                    console.log("B error:"+Msgerror)
                }
            })
        }
    script>

        <script type="text/javascript">
        function BSendByAjax() {
            $.ajax({
                async: true,
                url: 'http://localhost:10000/',
                type: 'post',
                data: {
                    "action": "B",
                },
                dataType: "json",
                success: function (info) {
                    console.log("A success:"+info)
                },
                error: function (error, Msgerror) {
                    console.log("B error:"+Msgerror)
                }
            })
        }
    script>
head>

<body>
    <button style="width:300px;height:100px;font-size:30px" onclick="ASendByAjax()">
        Ajax发送信息A
    button>
    <button style="width:300px;height:100px;font-size:30px" onclick="BSendByAjax()">
        Ajax发送信息B
    button>
body>
html>

服务器编写

服务器绑定端口并接收来自网络的请求,响应被封装在了实现了Runnable的Action类,并由线程池启动。
相关说明见注释,这个程序存在很多问题,都与阻塞IO有关。

package pers.machi.tomdog.tomrun;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Tomrun {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10000);
        //监听端口号10000
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        //定容线程池
        int i = 0;
        while (true) {
            Socket socket = serverSocket.accept();
            System.out.println("----------\n" + "socket\n" + socket.toString());
            //接收到一个socket连接请求并打印相关信息
            fixedThreadPool.execute(new Thread(new Action(socket), "thread" + i));
           	//创建Action实例,每个实例对应一个socket,实例之间并不存在资源的竞争
            i++;
        }
    }
}

//下面是Action类,封装了socket
class Action implements Runnable {
    Socket socket;

    public Action(Socket socket) {
        this.socket = socket;
    }
		
     public void receive() throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            StringBuffer buffer = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                buffer.append(line + "\r\n");
            }
            System.out.println("----------\n" + "request information");
            System.out.println(buffer.toString());
    }
    // receive函数用来读取ajax通过post发送的信息,打印出消息后可以看到html协议的相关内容

     public void feedback() throws IOException {
         System.out.println("feedback started");
        PrintWriter pw = new PrintWriter(socket.getOutputStream());
        String content = "123456789";
        String html =
                "http/1.1 200 ok\r\n" +
                        "Access-Control-Allow-Origin:*\r\n" +
                        "Access-Control-Allow-Headers:*\r\n" +
                        "Content-Type: text/html; charset=utf-8\r\n" +
                        "Content-Length:" + content.length() +
                        "\r\n\r\n" + content;
        pw.println(html);
        pw.flush();
        System.out.println("feedback has been finished");
    }
    //feedback函数向ajax写入消息,这里只是简单的回复"123456789"。注意回复的内容要拼接成符合html响应体的格式。
    //注意设置Access-Control-Allow-Origin
    //存在一个重要问题,那就是content的内容必须能被ajax解码,目前这个程序只能回复0~9组成的数字字符串,还需要进一步了解ajax解码的相关知识。

    public void run() {
        try {
            feedback();
            receive();
			/**
			并发运行feedback和receive函数,这里有个问题,如果先receive后feedback,ajax控制台无法接受回复的消息。
			而先feedback后receive,则没有问题。这可能是一个IO阻塞的问题。待学习。
            先receive后feedback不会报错,但是ajax无法接受回复,莫名其妙。
            receive();
            feedback();
            */
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

结果

server端接收ajax发送的消息,socket包含了客户端的ip,端口信息。
先feedback,然后接收post消息,可以看到请求体协议相关内容。
Ajax与Socket多线程通信_第2张图片

ajax的控制台输出。
Ajax与Socket多线程通信_第3张图片

你可能感兴趣的:(多线程,前端学习,ajax,socket)