day2020/6/9

本文详细介绍如何使用Java在WebSocket中实现客户端与服务器的实时通信,包括ChatEndpoint类的创建、处理连接与消息的方法,以及与Tomcat的关系。同时介绍了Set接口、Session对象和原子操作类的作用。

学习了怎么实现webSocket:1.在src目录下新建ChatEntpoint.java类

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = “/websocket/chat”)
public class ChatEntpoint {
private static final String GUEST_PREFIX=“访客”;
private static final AtomicInteger connectionIds = new AtomicInteger(0);
//定义一个集合,用于保存所有接入的WebSocket客户端
private static final Set clientSet = new CopyOnWriteArraySet<>();
//定义一个成员变量,记录WebSocket客户端的聊天昵称
private final String nickname;
//定义一个成员变量,记录与WebSocket之间的会话
private Session session;
public ChatEntpoint() {
nickname=GUEST_PREFIX+connectionIds.getAndIncrement();
}

//当客户端连接进来时自动激发该方法
@OnOpen
public void start(Session session) {
    this.session = session;
    //将WebSocket客户端会话添加到集合中
    clientSet.add(this);
    String message = String.format("【%s %s】", nickname,"加入了!");
    //发送消息
    broadcast(message);
}

//当客户端断开连接时自动激发该方法
@OnClose
public void end() {
    clientSet.remove(this);
    String message = String.format("【%s %s】", nickname,"离开了!");
    //发送消息
    broadcast(message);
}

//当收到客户端消息时自动激发该方法
@OnMessage
public void incoming(String message) {
    String filterMessage = String.format("【%s %s】", nickname,filter(message));
    broadcast(filterMessage);
}

//当客户端通信发生错误时
@OnError
public void onError(Throwable t)throws Throwable {
    System.out.println("WebSocket服务器端报错"+t);
}

//实现广播消息的工具方法
public static void broadcast(String msg) {
    //遍历服务器关联的所有客户端
    for(ChatEntpoint client:clientSet) {
        try {
            synchronized(client) {
                //发送消息
                client.session.getBasicRemote().sendText(msg);
            }
        }catch(IOException e) {
            System.out.println("聊天错误,向客户端 "+client+" 发送消息出现错误");
            clientSet.remove(client);
            try {
                client.session.close();
            }catch(IOException el) {}
                String message = String.format("【%s %s】", client.nickname,"已经断开了连接!");

        }
    }
}

//定义一个工具方法,用于对字符串中的HTML字符标签进行转义
private static String filter(String message) {
    if(null == message) {
        return null;
    }
    char content[] = new char[message.length()];
    message.getChars(0, message.length(), content, 0);
    StringBuilder result = new StringBuilder(content.length+50);
    for(int i=0;i<content.length;i++) {
        //控制对尖括号等特殊字符进行转义
        switch(content[i]) {
        case '<':
            result.append("&lt");
            break;
        case '>':
            result.append("&gt");
            break;
        case '&':
            result.append("&amp");
            break;
        case '"':
            result.append("&quot");
            break;
        default:
            result.append(content[i]);
            break;
        }
    }
    return (result.toString());
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
2.在webContent下新建chat.html文件

Insert title here
———————————————— 版权声明:本文为优快云博主「596785154」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.youkuaiyun.com/zcn596785154/article/details/80734961

以及webSocket和tomcat得关系:伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询小了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。

Tomcat自7.0.5版本开始支持WebSocket,并且实现了Java WebSocket规范(JSR356 ),而在7.0.5版本之前(7.0.2版本之后)则采用自定义API,即WebSocketServlet。本文使用的是Tomcat9.0.6版本
————————————————
版权声明:本文为优快云博主「qq_39686941」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_39686941/article/details/104958717

学习了java set类:Interface Set 不包含重复元素的集合,并且最多一个空元素。

1.参数类型
E - 由此集合维护的元素的类型
2.Set接口除了继承自Collection接口的所有构造函数的合同以及add,equals和hashCode方法的合同。
3.
在这里插入图片描述
Class CopyOnWriteArraySet:
1.构造方法:CopyOnWriteArraySet():创建一个空集。

一、Session简单介绍
  在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。(用的时候需要导入包import javax.websocket.Session;)
  详细见https://www.cnblogs.com/xdp-gacl/p/3855702.html
 

java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。可以对基本数据、数组中的基本数据、对类中的基本数据进行操作。原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读-改-写操作。
————————————————
版权声明:本文为优快云博主「May的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/lmb55/article/details/79547685

@OnOpen:
WebSocket.onopen属性定义一个事件处理程序,当WebSocket 的连接状态readyState 变为“OPEN”时调用;这意味着当前连接已经准备好发送和接受数据。这个事件处理程序通过 事件(建立连接时)触发。
参考https://www.cnblogs.com/wgp13x/p/3812579.html

根据你提供的数据格式,可以看出原始 CSV 文件中包含完整的表头,并且时间信息存储在多个列中(如 `year`, `month`, `day`, `hour`, `minute`),或者一个组合的 `datetime` 字段。 我们需要对代码进行如下调整: --- ## ✅ 正确读取并解析数据 ### 📌 数据说明: - 列名包括:`open`, `close`, `high`, `low`, `vol`, `amount`, `year`, `month`, `day`, `hour`, `minute`, `datetime` - 时间信息完整,可以直接使用 `datetime` 列作为索引 - 无需跳过行,因为我们知道第一行为 header --- ## ✅ 修改后的 Python 代码示例: ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt # 1. 加载数据(正确识别header) file_path = r&#39;D:\tdxbase\pytdxdatabase\SZ#300595\SZ#300595.day.csv&#39; df = pd.read_csv(file_path) # 2. 转换 datetime 列为日期类型并设置为索引 df[&#39;datetime&#39;] = pd.to_datetime(df[&#39;datetime&#39;]) df.set_index(&#39;datetime&#39;, inplace=True) # 3. 计算基准值(以20日EMA为例) df[&#39;ema_20&#39;] = df[&#39;close&#39;].ewm(span=20, adjust=False).mean() # 4. 设定阈值h(以过去20日收盘价的标准差的2倍为例) window = 20 df[&#39;std&#39;] = df[&#39;close&#39;].rolling(window=window).std() h = 2 * df[&#39;std&#39;].mean() # 固定阈值,也可以用滚动窗口动态设置 # 5. 应用CUSUM算法(单边上涨检测) def cusum_filter(data, mu, threshold): S = np.zeros(len(data)) signals = np.zeros(len(data)) for i in range(1, len(data)): diff = data.iloc[i] - mu.iloc[i] S[i] = max(0, S[i-1] + diff) if S[i] > threshold: signals[i] = 1 S[i] = 0 # 重置CUSUM return signals df[&#39;cusum_signal&#39;] = cusum_filter(df[&#39;close&#39;], df[&#39;ema_20&#39;], h) # 6. 可视化 plt.figure(figsize=(14, 7)) plt.plot(df.index, df[&#39;close&#39;], label=&#39;Close Price&#39;, color=&#39;blue&#39;) plt.plot(df.index, df[&#39;ema_20&#39;], label=&#39;EMA 20&#39;, color=&#39;orange&#39;) # 标记异动点 anomaly_dates = df[df[&#39;cusum_signal&#39;] == 1].index anomaly_prices = df.loc[anomaly_dates, &#39;close&#39;] plt.scatter(anomaly_dates, anomaly_prices, color=&#39;red&#39;, label=&#39;Anomaly Detected&#39;, zorder=5) plt.title(&#39;CUSUM Filter for SZ#300595 Anomaly Detection&#39;) plt.xlabel(&#39;Date&#39;) plt.ylabel(&#39;Price&#39;) plt.legend() plt.grid(True) plt.tight_layout() plt.show() ``` --- ## 🔍 改进说明: | 操作 | 原因 | |------|------| | `pd.read_csv(file_path)` | 直接读取带 header 的文件,不需要指定列名 | | `pd.to_datetime(df[&#39;datetime&#39;])` | 使用已有的 `datetime` 列转换为标准时间格式 | | `set_index(&#39;datetime&#39;)` | 将时间设为索引,便于后续分析和绘图 | --- ## ✅ 示例输出验证: 你可以打印前几行确认是否加载成功: ```python print(df[[&#39;close&#39;, &#39;ema_20&#39;, &#39;cusum_signal&#39;]].head(10)) ``` 输出类似: ``` close ema_20 cusum_signal datetime 2020-01-02 15:00:00 47.4 NaN 0.0 2020-01-03 15:00:00 46.88 NaN 0.0 2020-01-06 15:00:00 46.55 NaN 0.0 2020-01-07 15:00:00 49.40 47.557508 0.0 2020-01-08 15:00:00 48.55 47.720006 0.0 ... ``` --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值