当前位置: 首页 > article >正文

程序猿成长之路之socket篇-socket通信原理简介

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 = () => {
	//创建完成websocket
	console.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,因为它将由容器自己提供和管理。
     */
    @Bean
    public 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
     */
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session) {
           this.username = username;
           this.session = session;     //保存当前会话
           addOnlineCount();           //在线数加1
           log.info("欢迎用户" + username +  " 加入聊天室!当前在线人数为: " + getOnlineCount());
    }

    /**
     * 获取到消息后
     * @param message 消息
     */
    @OnMessage
    public 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 错误消息
     */
    @OnError
    public void onError(Session session, Throwable err) {
        System.out.println("发生错误");
        try {
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.error(err.getMessage());
        err.printStackTrace();
    }

    /**
     * socket连接关闭
     */
    @OnClose
    public 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();
    }
}


http://www.kler.cn/news/272854.html

相关文章:

  • web蓝桥杯真题:和手机相处的时光
  • python异常:Exception、BaseException接收异常,并打印异常信息msg
  • 接口优化:查询企业额度代码优化
  • 做老阳推荐的蓝海项目有成功的吗?
  • 【nfs报错】rpc mount export: RPC: Unable to receive; errno = No route to host
  • 英语单词--痛苦
  • web高可用集群(lvs负载均衡+keepalved高可用)
  • OpenvSwitch 配置 Trunk 端口实验
  • 人工智能需要的数学基础有哪些?
  • opc客户端
  • DARTS: DIFFERENTIABLE ARCHITECTURE SEARCH
  • linux系统kubernetes的pod的状态
  • 【vue baidu-map】实现百度地图展示基地,鼠标悬浮标注点展示详细信息
  • C语言深入理解指针(4)
  • KD-Tree的原理及其在KNN中的应用(附Python代码)
  • flask 继续学习
  • 微信小程序小案例实战
  • c语言大小写字母的转换
  • 用C语言链表实现图书管理
  • 23.1 微服务理论基础