hello,各位小伙伴们大家好,上次以RSA加解密算法介绍作为密码学篇的结尾后,时光飞逝,转眼到了新一年的春季,这次将介绍一下socket通信和编程原理。
什么是socket(套接字)?
socket(套接字)是网络传输的一种工具,它是介于应用层与传输层之间,了解过七层OSI协议的同学应该知道,socket是基于TCP/IP协议进行网络传输的。socket分为server端和client端,它支持全双工式网络通信。
socket(套接字)有哪些用途?
说起socket的用途,大家可能首先会联想到聊天室,没错,这个就是socket的一类应用。由于全双工式的通信,socket可以支持双向的信息发送与接收。此外,socket还可以编写服务端向客户端主动发送消息。总之,有了socket,网络通信就变得容易了。
socket(套接字)其他知识
socket 生命周期
什么是websocket?
WebSocket是一种在单个TCP连接上进行全双工通信的协议。它允许客户端和服务器之间进行简单而有效的双向数据传输。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。这个握手过程是通过HTTP/1.1协议的101状态码进行的。
websocket实现方式
websocket client端
const host = 'localhost'//设置自己的socket host
const port = 8888 //设置自己的socket port
const ws = new WebSocket(`ws://${host}:${port}/websocket/${username}`)
ws.onopen = () => {//创建完成websocketconsole.log('client opened')
}ws.onmessage = (msg) => {//接收到消息console.log(msg);
}ws.onerror = (err) => {//出错console.log(err);
}ws.onclose = () => {//websocket关闭时执行console.log("client closed")
}
websocket server端(node.js版)
onst ws = require('ws');const wss = new ws.Server({port:8888});wss.on('connection',function onConnection(ws) {ws.on('open',function onOpen(){console.log('connected!');ws.send("hello");});ws.on('message',function onMessage(msg){//批量群发wss.clients.forEach(function each(client) {//如果socket 为连接状态就发送消息if (client.readyState === ws.OPEN) {client.send(msg);}})})ws.on('close',function onOpen(){console.log('closed!');});
})
websocket server端(java版)
配置类:
/*** WebSocket配置类。开启WebSocket的支持*/
@Configuration
public class WebSocketConfig {/*** bean注册:会自动扫描带有@ServerEndpoint注解声明的Websocket Endpoint(端点),注册成为Websocket bean。* 要注意,如果项目使用外置的servlet容器,而不是直接使用springboot内置容器的话,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
websocket 消息 实体类
/*** 消息实体类* @author zygswo*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@ToString
public class Message implements Serializable {/*** 来源*/private String from;/*** 目标*/private String to;/*** 正文*/private String message;/*** 发送时间*/private String date;/*** 是否系统消息*/private boolean sysmsg;
}
websocket实现类:
package com.myhouse.common.utils.myWebsocket;import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/*** ServerEndpoint注解表示开启websocket并且参数表示websocketserver 路径*/
@Component
@Slf4j
@Getter
@ServerEndpoint("/websocket/{username}")
public class MyWebSocket {/*** 在线人数*/private static AtomicInteger totalNb = new AtomicInteger(0);/*** websocket列表*/private static Map<String,MyWebSocket> socketMap = new ConcurrentHashMap<>();/*** 在线人数*/private Session session;/*** 用户名*/private String username;/*** 开启服务* @param username 用户名称* @param session session*/@OnOpenpublic void onOpen(@PathParam("username") String username, Session session) {this.username = username;this.session = session; //保存当前会话addOnlineCount(); //在线数加1log.info("欢迎用户" + username + " 加入聊天室!当前在线人数为: " + getOnlineCount());}/*** 获取到消息后* @param message 消息*/@OnMessagepublic void onMessage(String message) {Message msg = JSON.parseObject(message, Message.class);try {if (msg.getTo().equalsIgnoreCase("all")) {for (MyWebSocket socket : socketMap.values()) {socket.sendMessage(message);}} else {socketMap.get(msg.getTo()).sendMessage(message);}}catch (IOException e) {e.printStackTrace();}}/*** 发送消息* @param message 消息*/private void sendMessage(String message) throws IOException {this.session.getBasicRemote().sendText(message);}/*** 获取到消息后* @param session session* @param err 错误消息*/@OnErrorpublic void onError(Session session, Throwable err) {System.out.println("发生错误");try {session.close();} catch (IOException e) {e.printStackTrace();}log.error(err.getMessage());err.printStackTrace();}/*** socket连接关闭*/@OnClosepublic void onClose() {log.info(this.username + "退出聊天室!当前在线人数为" + getOnlineCount());socket.sendMessage(msg);socketMap.remove(this.username);}/*** 新增在线人数*/private static void addOnlineCount() {totalNb.incrementAndGet();}/*** 减少在线人数*/private static void substractOnlineCount() {totalNb.decrementAndGet();}/*** 获取在线人数* @return 在线人数*/public static int getOnlineCount() {return totalNb.get();}
}