程序猿成长之路之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();
    }
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zygswo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值