资料
  • 资料
  • 专题
基于C++从0到1手写Linux高性能网络编程框架-15章
推荐星级:
类别: 软件/EDA/IP
时间:2023-12-06
大小:3.8KB
阅读数:352
上传用户:学习菜鸟小弟弟
查看他发布的资源
下载次数
6
所需E币
0
ebi
新用户注册即送 300 E币
更多E币赚取方法,请查看
close
资料介绍
网络编程概述
管道(父子进程)、消息队列(内核经营消息队列)、共享内存(创建一个空间)、信号(通过pid号通信)、信号量(对临界资源,共享内存做P、V控制) 。
特点:依赖于Linux内核 A B两个通信基于内核。缺陷:无法多机通信 (不适用与两台不同的电脑)

TCP和UDP对比:
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前 不需 要建立连接
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
TCP首部开销20字节;UDP的首部开销小,只有8个字节
TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

传统的进程间通信借助内核提供的IPC机制进行,但是只能限于本机通信。若要跨机通信,就必须使用网络通信,这就需要用到内核提供给用户的socket API函数库。
2.1 网络字节序
大端字节序:也叫高端字节序(网络字节序),是高端地址存放低位数据,低端地址存放高位数据
小端字节序:也叫低端字节序,是低地址存放低位数据,高地址存放高位数据。
在application.yml文件中,填入SaToken的配置信息,如下:
sa-token:
  #HTTP请求头中哪个属性用来上传令牌
  token-name: token
  #过期时间(秒),设置为30天
  timeout: 2592000
  #临时有效期,设置为3天
  activity-timeout: 259200
  #不允许相同账号同时在线,新登陆的账号会挤掉原来登陆的账号
  allow-concurrent-login: false
  #在多人登陆相同账号的时候,是否使用相同的Token
  is-share: false
  token-style: uuid
  #是否读取Cookie中的令牌
  isReadCookie: false
  #同端互斥
  isConcurrent: false
  #SaToken缓存令牌用其他的逻辑库,避免业务数据和令牌数据共用相同的Redis逻辑库
  alone-redis:
    database: 1
    host: localhost
    port: 6379
    password: abc123456
    timeout: 10s
    lettuce:
      pool:
        # 连接池最大连接数
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 10s
        # 连接池中的最大空闲连接
        max-idle: 16
        # 连接池中的最小空闲连接
        min-idle: 8
Java语言允许我们自己封装异常类,我们可以自定义各种异常类,比如每种业务一个异常类,或者每个模块一个异常类。我这里不想做的那么复杂,不如我们创建一个通用的异常类,用来封装与业务有关的异常信息。

在com.example.his.api.exception包中,创建HisException.java类。
package com.example.his.api.exception;
import lombok.Data;

@Data
public class HisException extends RuntimeException {
    private String msg;
    private int code = 500;

    public HisException(Exception e) {
        super(e);
        this.msg = "执行异常";
    }

    public HisException(String msg) {
        super(msg);
        this.msg = msg;
    }

    public HisException(String msg, Throwable e) {
        super(msg, e);
        this.msg = msg;
    }

    public HisException(String msg, int code) {
        super(msg);
        this.msg = msg;
        this.code = code;
    }

    public HisException(String msg, int code, Throwable e) {
        super(msg, e);
        this.msg = msg;
        this.code = code;
    }

}
SpringBoot提供了全局处理异常的技术,只要我们给某个Java类用上@RestControllerAdvice注解,这个类就能捕获SpringBoot项目中所有的异常,然后统一处理(精简异常信息)再返回给前端项目。
在com.example.his.api.config包中,创建ExceptionAdvice.java类。
package com.example.his.api.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.felord.payment.PayException;
import cn.hutool.json.JSONObject;
import com.example.his.api.exception.HisException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
    /*
     * 捕获异常,并且返回500状态码
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public String exceptionHandler(Exception e) {
        JSONObject json = new JSONObject();
        if (e instanceof HttpMessageNotReadableException) {
            HttpMessageNotReadableException exception = (HttpMessageNotReadableException) e;
            log.error("error", exception);
            json.set("error", "请求未提交数据或者数据有误");
        } 
        else if (e instanceof MissingServletRequestPartException) {
            MissingServletRequestPartException exception = (MissingServletRequestPartException) e;
            log.error("error", exception);
            json.set("error", "请求提交数据错误");
        } 
        else if (e instanceof HttpRequestMethodNotSupportedException) {
            HttpRequestMethodNotSupportedException exception = (HttpRequestMethodNotSupportedException) e;
            log.error("error", exception);
            json.set("error", "HTTP请求方法类型错误");
        } 
        //Web方法参数数据类型转换异常,比如String[]数组类型的参数,你上传的数据却是String类型
        else if (e instanceof BindException) {
            BindException exception = (BindException) e;
            String defaultMessage = exception.getFieldError().getDefaultMessage();
            log.error(defaultMessage, exception);
            json.set("error", defaultMessage);
        }
        //没有通过后端验证产生的异常
        else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            json.set("error", exception.getBindingResult().getFieldError().getDefaultMessage());
        }
        //处理业务异常
        else if (e instanceof HisException) {
            log.error("执行异常", e);
            HisException exception = (HisException) e;
            json.set("error", exception.getMsg());
        } 
        //微信支付异常
        else if (e instanceof PayException) {
            PayException exception = (PayException) e;
            log.error("微信支付异常", exception);
            json.set("error", "微信支付异常");
        }
        //处理其余的异常
        else {
            log.error("执行异常", e);
            json.set("error", "执行异常");
        }
        return json.toString();
    }

    /*
     * 捕获异常,并且返回401状态码
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(NotLoginException.class)
    public String unLoginHandler(Exception e) {
        JSONObject json = new JSONObject();
        json.set("error", e.getMessage());
        return json.toString();
    }

}
因为Controller类用上@RestController注解之后,Web方法返回的对象会被自动转换成JSON对象,所以我们只需要声明一个封装类,让所有Web方法返回这个封装类的对象即可。除了公共属性之外,不同的Web方法要返回的业务数据也不尽相同,所以选择动态的结构才是最佳的方案,恰好HashMap允许我们随便添加数据,那就选择HashMap作为父类吧。在com.example.his.api.common包中,创建R.java类。
package com.example.his.api.common;

import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;

public class R extends HashMap<String, Object> {
    public R() {
        //默认创建的R对象中包含了公共的属性
        put("code", HttpStatus.SC_OK);
        put("msg", "success");
    }

    /*
     * 覆盖继承的put函数,添加Key-Value数据
     */
    public R put(String key, Object value) {
        super.put(key, value);
        //把自己返回,用于链式调用
        return this;
    }

    public static R ok() {
        return new R();
    }

    public static R ok(String msg) {
        R r = new R();
        r.put("msg", msg);
        return r;
    }

    public static R ok(Map<String, Object> map) {
        R r = new R();
        r.putAll(map);
        return r;
    }

    public static R error(int code, String msg) {
        R r = new R();
        r.put("code", code);
        r.put("msg", msg);
        return r;
    }

    public static R error(String msg) {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
    }

    public static R error() {
        return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
    }

}

版权说明:本资料由用户提供并上传,仅用于学习交流;若内容存在侵权,请进行举报,或 联系我们 删除。
相关评论 (下载后评价送E币 我要评论)
没有更多评论了
  • 可能感兴趣
  • 关注本资料的网友还下载了
  • 技术白皮书