基于C++从0到1手写Linux高性能网络编程框架-15章

giadnbhaytgw · · 766 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
参考资料地址1:https://pan.baidu.com/s/1i8FuLluEUV3BJFphjKWvhQ 提取码:zvet 参考资料地址2:https://pan.baidu.com/s/1MgD4BdeD6V6HfXkoMAZ5Hw 提取码:l5t4 网络编程概述 管道(父子进程)、消息队列(内核经营消息队列)、共享内存(创建一个空间)、信号(通过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, "未知异常,请联系管理员"); } }
766 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传