【计算机网络】网络编程接口 Socket API 解读(7)
Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。
本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。
send
send() 遵循 POSIX.1 - 2008
MSG_CONFIRM 是 Linux 扩展
1.库
标准 c 库,libc, -lc
2.头文件
<sys/socket.h>
3.接口定义
ssize_t send(int sockfd, const void buf[.len], size_t len, int flags);ssize_t sendto(int sockfd, const void buf[.len], size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
4.接口描述
send()、sendto()、sendmsg() 调用用来向另一个套接字发送消息。
send() 通常只能用在连接状态(即接收者已知)的套接字上,send() 和 write(2) 的唯一不同是 send() 存在 flags 标记。当标记为 0 时,send() 和 write(2) 等效。同样的,下面的两个调用也是等效的。
send(sockfd, buf, len, flags);
sendto(sockfd, buf, len, flags, NULL, 0);
sockfd 参数是 发送套接字的文件描述符。
如果sendto() 用在连接模式(SOCK_STREAM、SOCK_SEQPACKET)的套接字上,那么参数 dest_addr 和 addrlen 将被忽略(当它们不是 NULL 或者 0时,会返回 EISCON 错误),并且当套接字没有连接时,会返回 ENOTCONN 错误。否则需要给定 addrlen 指定长度的 dest_addr 目标地址,目标地址由 msg.msg_name 给定,长度是 msg.msg_namelen 指定。
对于 send() 和 sendto(),发送的消息放在 len 长度的 buf 中。对于 sendmsg(),消息由 msg.msg_iov 数组元素指定,sendmsg() 调用同时允许发送一些辅助数据(也称为控制信息)。
如果消息太大以至于不能自动的透传给底层协议,调用会返回 EMSGSIZE 错误,该消息不会被发送。
send() 调用没有显示的关于传输失败的指示,在内部检测到这类错误时也只会返回 -1。
当消息不能装进套接字的发送缓冲区时,send() 正常会阻塞,除非套接字放进了非阻塞 I/O 模式,这种情况在非阻塞模式下会报告 EAGAIN 或者 EWOULDBLOCK 错误。这时可以使用 select(2) 来检测什么时候可以发送更多数据。
flags 参数
flags 参数可以是下面值的位或:
MSG_CONFIRM(Linux 2.3.15 后)
告诉链路层有进展发生:从对端收到了一个成功的回复。如果链路层没有收到这个,那么它通常会在骚扰邻居(通过 ARP 单播)。这个标记只在IPv4/IPv6 的 SOCK_DGRAM 和 SOCK_RAW 套接字中可用,详细信息可以参考 arp(7)。
MSG_DONTROUTE
不要使用向网关发送我们的数据包,只发给和我们直接连接的主机。这个通常只有诊断或者路由程序使用。这个只用于支持路由的协议家族,packet 套接字不支持。
MSG_DONTWAIT(Linux 2.2 后)
开启非阻塞操作。如果操作想要阻塞,那么就会返回 EAGAIN 或者 EWOULDBLOCK 错误。这个行为和设置 O_NONBLOCK 标记(通过 fcntl(2) F_SETFL 操作)行为类似,但是 MSG_DONTWAIT 只对当前调用生效,而 O_NONBLOCK 是设置到打开文件描述上(参考 open(2)),这会影响调用进程中的所有线程以及其他持有指向该打开文件描述的文件描述符的进程。
MSG_EOR(Linux 2.2 后)
结束一个记录(当支持该语义时,用于 SOCK_SEQPACKET 类型的套接字)
MSG_MORE(Linux 2.4.4 后)
调用者有更多数据要发送。这个标记用在 TCP 套接字中来获得和 TCP_CORK 套接字选项意向的效果,区别是这个标记只对当前调用生效。
MSG_NOSIGNAL(Linux 2.2 后)
如果对端关闭了流套接字,不要生成 SIGPIPE 信号,不过仍然会返回 EPIPE 错误。这和使用 sigaction(2) 来忽略 SIGPIPE 效果差不多,还是 MSG_NONSIGNAL 只对当前调用生效,并且忽略 SIGPIPE 设置的是进程属性,会影响进程中的所有线程。
MSG_OOB
在支持该带外数据的套接字(比如 SOCK_STREAM)上发送带外数据。 底层协议必须也支持带外数据传输。
MSG_FASTOPEN(Linux 3.7 后)
尝试 TCP 快速打开(RFC7413)并发送在 SYN 中发送数据,就像 connect(2) 和 write(2) 合并一样,进行了隐式的 connect(2) 操作。它会一直阻塞知道数据被缓存并且握手结束。对于一个非阻塞套接字,它会返回缓存数据的大小并且发送一个 SYN 包。如果本地 cookie 不可用,它会返回 EINPROGRESS,并自动发送一个 SYN 带着快速打开 cookie 请求。调用者需要在新连接的套接字上重新发送数据。发生错误时,它会在握手失败时设置和 connect(2) 相同的 errno。这个标记需要 sysctl net.ipv4.tcp_fastopen 来开启 TCP 快速打开客户端支持。
参考 tcp(7) TCP_FASTOPEN_CONNECT 套接字选项来查看一些可选的方法。
sendmsg()
sendmsg() 使用的 msghdr 结构定义如下:
struct msghdr {void *msg_name; /* Optional address */socklen_t msg_namelen; /* Size of address */struct iovec *msg_iov; /* Scatter/gather array */size_t msg_iovlen; /* # elements in msg_iov */void *msg_control; /* Ancillary data, see below */size_t msg_controllen; /* Ancillary data buffer len */int msg_flags; /* Flags (unused) */};
msg_name 字段用来指定非连接数据包类型套接字的目标地址,它指向一个包含地址的缓冲区,msg_namelen 字段应该设置为地址的大小。对于连接套接字,这些字段应该对应的设置为 NULL 和 0。
msg_iov 和 msg_ivolen 字段指定了 scatter-gether 区域,和 writev(2) 类似。
我们可以使用 msg_control 和 msg_controllen 成员发送控制信息(辅助数据),内核能够处理套接字最大的控制缓冲区大小由 /proc/sys/net/core/optmem_max 指定,参考 socket(7)。对于其他域套接字关于辅助数据的信息,可以参考 unix(7) 和 ip(7)。
msg_flags 字段忽略。
5.返回值
调用成功时,返回已发送数据的字节数。
发生错误时,返回 -1,并设置errno 来指示错误类型。
下面这些标准错误值是由套接字层生成的,其他错误可能会由底层协议模块产生并返回,具体可以参考对应的手册页。
错误值定义如下:
EACCESS | (特定于由路径指定的 UNIX 域套接字)目的套接字写权限被拒绝,或者在目录前缀下的搜索权限被拒绝 |
EAGAIN/EWOULDBLOCK | 套接字被设置为非阻塞,但是请求操作打算阻塞。POSIX.1-2021 允许随意哪个错误都可以,并且不假定两个值相等,所以移植程序应该对每个值都进行判断。 |
EAGAIN | (网络域数据报套接字)sockfd 指定的套接字还没有绑定到地址,并且在尝试绑定到临时端口时,临时端口用尽了。可以看 /proc/sys/net/ipv4/ip_local_port_rang 的讨论 |
EALREADY | 另一个快速打开(Fast Open)正在进行中 |
EBADF | sockfd 不是一个打开的文件描述 |
ECONNRESET | 对端重置了连接 |
EDESTADDRREQ | 套接字不是连接模式,并且没有设置对端地址 |
EFAULT | 参数中指定了用户空间不合法的地址 |
EINTR | 数据发送完成前有信号发生,参考 signal(7) |
EINVAL | 参数不合法 |
EISCONN | 连接模式的套接字早已经连接过了,但是又指定了接收者。(目前要么返回这个错误,要么直接忽略掉接收者参数) |
EMSGSIZE | 套接字类型要求消息自动发送,但是消息的大小却使得这个无法完成 |
ENOBUFS | 网络接口输出队列满了。这个通常指示接口已经停止发送,但可能导致传输堵塞。(正常情况下,这个不会在 Linux 上发生,当设备队列溢出时,数据包会偷偷的被丢掉。) |
ENOMEM | 没有内存了 |
ENOTCONN | 套接字没连接,也没有指定目标地址 |
ENOTSOCK | sockfd 文件描述符没有指向一个套接字 |
EOPNOTSUPP | flags 里面有些位设置不正确 |
EPIPE | 面向连接的套接字在本地被关闭,这种情况下,进程也会收到 SIGPIP 信号,除非我们设置了 MSG_NOSIGNAL。 |
6.注意
参考 sendmmsg(2) 来查阅更多 Linux 系统用于一次调用传输多个数据包的信息。
Linux 系统可能返回 EPIPE 而不是 ENOTCONN。
7.代码
Server program#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/types.h>#include <unistd.h>#define BUF_SIZE 500intmain(int argc, char *argv[]){int sfd, s;char buf[BUF_SIZE];ssize_t nread;socklen_t peer_addrlen;struct addrinfo hints;struct addrinfo *result, *rp;struct sockaddr_storage peer_addr;if (argc != 2) {fprintf(stderr, "Usage: %s port\n", argv[0]);exit(EXIT_FAILURE);}memset(&hints, 0, sizeof(hints));hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */hints.ai_protocol = 0; /* Any protocol */hints.ai_canonname = NULL;hints.ai_addr = NULL;hints.ai_next = NULL;s = getaddrinfo(NULL, argv[1], &hints, &result);if (s != 0) {fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}/* getaddrinfo() returns a list of address structures.Try each address until we successfully bind(2).If socket(2) (or bind(2)) fails, we (close the socketand) try the next address. */for (rp = result; rp != NULL; rp = rp->ai_next) {sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (sfd == -1)continue;if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)break; /* Success */close(sfd);}freeaddrinfo(result); /* No longer needed */if (rp == NULL) { /* No address succeeded */fprintf(stderr, "Could not bind\n");exit(EXIT_FAILURE);}/* Read datagrams and echo them back to sender. */for (;;) {char host[NI_MAXHOST], service[NI_MAXSERV];peer_addrlen = sizeof(peer_addr);nread = recvfrom(sfd, buf, BUF_SIZE, 0,(struct sockaddr *) &peer_addr, &peer_addrlen);if (nread == -1)continue; /* Ignore failed request */s = getnameinfo((struct sockaddr *) &peer_addr,peer_addrlen, host, NI_MAXHOST,service, NI_MAXSERV, NI_NUMERICSERV);if (s == 0)printf("Received %zd bytes from %s:%s\n",nread, host, service);elsefprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));if (sendto(sfd, buf, nread, 0, (struct sockaddr *) &peer_addr,peer_addrlen) != nread){fprintf(stderr, "Error sending response\n");}}}
Client program#include <netdb.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/types.h>#include <unistd.h>#define BUF_SIZE 500intmain(int argc, char *argv[]){int sfd, s;char buf[BUF_SIZE];size_t len;ssize_t nread;struct addrinfo hints;struct addrinfo *result, *rp;if (argc < 3) {fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);exit(EXIT_FAILURE);}/* Obtain address(es) matching host/port. */memset(&hints, 0, sizeof(hints));hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */hints.ai_flags = 0;hints.ai_protocol = 0; /* Any protocol */s = getaddrinfo(argv[1], argv[2], &hints, &result);if (s != 0) {fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);}/* getaddrinfo() returns a list of address structures.Try each address until we successfully connect(2).If socket(2) (or connect(2)) fails, we (close the socketand) try the next address. */for (rp = result; rp != NULL; rp = rp->ai_next) {sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);if (sfd == -1)continue;if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)break; /* Success */close(sfd);}freeaddrinfo(result); /* No longer needed */if (rp == NULL) { /* No address succeeded */fprintf(stderr, "Could not connect\n");exit(EXIT_FAILURE);}/* Send remaining command-line arguments as separatedatagrams, and read responses from server. */for (size_t j = 3; j < argc; j++) {len = strlen(argv[j]) + 1;/* +1 for terminating null byte */if (len > BUF_SIZE) {fprintf(stderr,"Ignoring long message in argument %zu\n", j);continue;}if (write(sfd, argv[j], len) != len) {fprintf(stderr, "partial/failed write\n");exit(EXIT_FAILURE);}nread = read(sfd, buf, BUF_SIZE);if (nread == -1) {perror("read");exit(EXIT_FAILURE);}printf("Received %zd bytes: %s\n", nread, buf);}exit(EXIT_SUCCESS);}
相关文章:
【计算机网络】网络编程接口 Socket API 解读(7)
Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。…...
crypto++下载、安装(VS2017)及加解密使用
crpto 下载按个人喜好下载,我使用了图中框选的8.8.0 Release.解压 安装打开修改以适应本机配置整理至标准库 调用加解密使用 Crypto(也称为Crypto Library或Crypto STL)是一个C密码学库,它提供了各种密码学算法和安全编程工具&…...
R语言画图
简单记录一下 plot(lad_profile_relative$lad, lad_profile_relative$height, type"l", lwd1.5, xlabexpression(paste("LAD ", "(", m^2, m^-3, ")" )), ylab"Height (m)")X轴数据, Y轴数据 type, 标记类型 lw…...
redis 核心数据结构
一、简述 redis是一个开源的使用C语言编写的一个kv存储系统,是一个速度非常快的非关系远程内存数据库。它支持包括String、List、Set、Zset、hash五种数据结构。 除此之外,通过复制、持久化和客户端分片等特性,用户可以很方便地将redis扩展…...
RabbitMQ消息可靠性(一)-- 生产者消息确认
前言 在项目中,引入了RabbitMQ这一中间件,必然也需要在业务中增加对数据安全性的一层考虑,来保证RabbitMQ消息的可靠性,否则一个个消息丢失可能导致整个业务的数据出现不一致等问题,对系统带来巨大的影响,…...
9 种方法使用 Amazon CodeWhisperer 快速构建应用
Amazon CodeWhisperer 是一款很赞的生成式人工智能编程工具。自从在工作中使用了 CodeWhisperer,我发现不仅代码编译的效率有所提高,应用开发的工作也变得快乐起来。然而,任何生成式 AI 工具的有效学习都需要初学者要有接受新工作方式的心态和…...
性能测试-性能工程落地的4个阶段(21)
性能工程按照不同的内容和目的划分为4个阶段,分别是线下单系统压测分析阶段、线下全链路压测分析阶段、生产只读业务压测及容量评估阶段、生产读写业务全链路压测及容量评估阶段。(也可以理解为一个企业性能测试体系的发展阶段) 线下单系统压测分析阶段 针对单系统的性能…...
小程序 navigateBack 携带参数返回的三种方式(详细)
如果觉着主图好看,点个赞,你早晚也会看到这么好看的景色! 第一种方式 getCurrentPages 获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。不要尝试修改页面栈,会导致路由以及页面状态错误。不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page …...
通过内网穿透实现远程连接群晖Drive,轻松实现异地访问群晖NAS
文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…...
vue3 + vite常用工具
1. plop 1.1 安装 yarn add plop -D1.2 使用 1.2.1 package.json 配置脚本命令 "scripts": {"dev": "vite --mode dev","build": "vue-tsc --noEmit && vite build","serve": "vite preview"…...
Vue框架分享与总结
总结开发中最常用的vue语法,以及对特定语法的理解。vue官网 文章目录 一、创建vue项目1、使用开发工具创建2、使用命令行创建3、vue框架结构4、Vue文件结构 二、Vue 常用模板语法1、v-if、v-show2、v-for3、v-on4、v-bind5、v-model 三、组件通信1、父组件给子组件传…...
声音生成评价指标——使用声音分类模型评价生成声音质量(基于resnetish、VGGish、AlexNet)
文章目录 引言正文数据预处理将wav转成log-mel频谱图进行保存创建dataset类保存数据 模型定义模型训练过程训练代码定义loss为nan从AlexNet到ResNetloss上下剧烈波动——使用学习率衰减策略学习率调整——根据准确率来调整学习率数据处理问题 模型的测试 总结 引言 这篇文章主要…...
HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 六)
AppStorage:应用全局的UI状态存储 AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。 和LocalStorage不同的是,LocalStorage是页面级的&…...
SPA首屏加载速度慢
什么是首屏加载 首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容 首屏加载可以说是用…...
JVM执行流程
一、Java为什么是一种跨平台的语言? 通常,我们编写的java源代码会被JDK的编译器编译成字节码文件,再由JVM将字节码文件翻译成计算机读的懂得机器码进行执行;因为不同平台使用的JVM不一样,所以不同的JVM会把相同的字节码…...
laravel 凌晨0点 导出数据库
一、创建导出模型 <?php namespace App\Models;use Illuminate\Support\Facades\DB;class DbBackup {private $table;public function __construct(){$this->table env(DB_DATABASE);}public function run($file ){$file !$file ? public_path($this->t…...
mysql MVCC多版本并发控制
mvcc的概念 mvcc 的实现依赖于: 隐藏字段 行格式(row_id,trx_id,roll_ponter)UndologRead view innodb 存储引擎的表来说,聚集索引记录中都包含两个必要的隐藏字段,row_id(如果没有聚集索引,才会创建的) …...
new/delete, malloc/free 内存泄漏如何检测
区别: 首先new/delete是运算符,malloc/free是库函数。malloc/free只开辟内存不初始化;new/delete及开辟内存也初始化。抛出异常的方式:new/delete开辟失败使用抛出bad_alloc;malloc/free通过返回值判断。malloc和new区…...
Java开发推荐关注的网站
一、开发者社区 阿里云开发者社区:https://developer.aliyun.com/腾讯云开发者社区:https://cloud.tencent.com/developer 二、开发规范 阿里巴巴Java开发规范 github地址:https://github.com/alibaba/p3c gitcode地址:https:/…...
OpenHarmony社区运营报告(2023年8月)
本月快讯 2023年8月3日,OpenAtom OpenHarmony(以下简称“OpenHarmony”)发布了Beta2版本。OpenHarmony 4.0 Beta2在系统能力、应用框架、分布式通信、媒体功能、安全性等方面进行了全面升级。其中,ArkUI增强了界面组件能力&#x…...
Web学习笔记-React(路由)
笔记内容转载自 AcWing 的 Web 应用课讲义,课程链接:AcWing Web 应用课。 CONTENTS 1. Web分类2. Route组件3. URL中传递参数4. Search Params传递参数5. 重定向6. 嵌套路由 本节内容是如何将页面和 URL 一一对应起来。 1. Web分类 Web 页面可以分为两…...
MySQL无法查看系统默认字符集以及校验规则
show variables like character_set_database; show variables like collation_database;这个错误信息表示MySQL在尝试访问performance_schema.session_variables表时,发现该表不存在。这个问题可能是由于MySQL的版本升级导致的。解决这个问题的一种方法是运行mysql…...
不负昭华,前程似锦,新一批研发效能认证证书颁发丨IDCF
亲爱的认证学员, 恭喜你成功获得由国家工业和信息化部教育与考试中心颁发的职业技术证书——《研发效能(DevOps)工程师国家职业技术认证》。你的努力和才华得到了官方的认可,这是你职业生涯中的一个重要的里程碑。 这个证书不仅代表着你的专业知识和技…...
深入理解ES6模块化:语法、特性与最佳实践
目录 一、前言 二、ES6模块化基础 1. 模块的定义与导出 2. 模块的导入与使用 3. 模块默认导出与命名导出 4. 模块的循环引用与解决方案 三、模块化语法进阶 1. 模块的命名导出与默认导出的混合使用 2. 模块的别名导出与导入 3. 命名空间的使用与作用 4. 动态导入模块…...
Matlab图像处理-HSI模型
HSI模型 HSI模型是从人的视觉系统出发,直接使用颜色三要素色调(Hue)、饱和度(Saturation)和亮度(Intensity)来描述颜色。 亮度是指人眼感知光线的明暗程度。光的能量越大,亮度就越大。 色调是颜色最重要的属性。 它决定了颜色的…...
【Springboot】Springboot如何优雅停机?K8S中Pod如何优雅停机?
什么是优雅停机: 就是对应用进程发送停止指令之后,执行的一系列保证应用正常关闭的操作。这些操作往往包括等待已有请求执行完成、关闭线程、关闭连接和释放资源等 就是对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响&#x…...
伦敦银一手是多少?
伦敦银是以国际现货白银价格为跟踪对象的电子合约交易,无论投资者通过什么地方的平台进入市场,执行的都是统一国际的标准,一手标准的合约所代表的就是5000盎司的白银,如果以国内投资者比较熟悉的单位计算,那约相当于15…...
Language Adaptive Weight Generation for Multi-task Visual Grounding 论文阅读笔记
Language Adaptive Weight Generation for Multi-task Visual Grounding 论文阅读笔记 一、Abstract二、引言三、相关工作3.1 指代表达式理解3.2 指代表达式分割3.3 动态权重网络 四、方法4.1 总览4.2 语言自适应权重生成语言特征聚合权重生成 4.3 多任务头4.4 训练目标 五、实…...
面试算法4:只出现一次的数字
题目 输入一个整数数组,数组中只有一个数字出现了一次,而其他数字都出现了3次。请找出那个只出现一次的数字。例如,如果输入的数组为[0,1,0,1,0,1,100],则只…...
#与##的用法
# 作用: 左右加双引号,使其变成字符串 #的作用:是在形参左右各加双引号,使它变成字符串。#define STR(param) #paramchar *pStr STR(hello); // 展开后 char *pStr “hello”; ## 作用:胶水,使…...
怎样做音乐网站/2024年新冠第三波症状分析
js连接字符串的方法有:使用字符串连接符运算“”、使用concat()方法、使用join()方法。在JavaScript中,我们可以把两个或两个以上的字符串连接形成一个新字符串,本篇文章就给大家介绍js连接字符串的方法,让大家对字符串连接有一定…...
阿拉伯文网站怎么做/个人在线网站推广
IT系统应用于企业管理:架构模式,领域分析,项目管理。非常好的一本书,第一次读完一遍后想立即再读一遍的书。同类的书中也是最好的那类。第一章,大型网站架构演化初始阶段的网站架构应用服务和数据服务分离使用缓存改善…...
企业网站建设的核心/2345网址导航官网官方电脑版下载
原标题:Win10的隐藏小秘密,被我发现了今天的小硕要来给大家分享一些小秘密!当然,这可不是小硕自己的小秘密,是关于你电脑的小秘密哦!知道吗?Windows10每一次升级更新,都会伴随着新功…...
软件开发工具也叫什么工具/郑州网站建设专业乐云seo
单片机C语言编程串行口通讯第7章 MCS-51单片机串行口 第7章 MCS-51单片机串行口 目 录 7.1 串行通信基本知识 7.2 串行口结构及控制 7.3 串行口工作方式 7.4 串行口应用举例 7.5 单片机与PC机通信的接口电路 本章要点 本章主要讲述MCS-51单片机串行口的结构、工作原理以及应用。…...
免费做网站手机/体球网足球世界杯
电子信息类专业与信息社会密切相关,是实用性非常强的专业,下设18个本科专业,分别是电子信息工程、电子科学与技术、通信工程、微电子科学与工程、光电信息科学与工程、信息工程、广播电视工程、水声工程、电子封装技术、集成电路设计与集成系…...
南宁手机网站建设/网站优化培训学校
最近需要对表加一个字段,同时觉得前期建立表的时候有点粗暴,没有加很对限制,比如有些字符串长度是有限制的,在创建表时字段也没有对其进行限制。所以想借着这次加字段对表字段也进行一个优化,在优化之前先看了点理论知…...