ter = array_value($config, 'filter'); $arr = array_value($filter, $type); $enable = array_value($arr, 'enable'); $wordarr = array_value($arr, 'keyword'); if (0 == $enable || empty($wordarr)) return FALSE; foreach ($wordarr as $_keyword) { if (!$_keyword) continue; $r = strpos(strtolower($keyword), strtolower($_keyword)); if (FALSE !== $r) { $error = $_keyword; return TRUE; } } return FALSE; } // return http://domain.com OR https://domain.com function url_prefix() { $http = ((isset($_SERVER['HTTPS']) && 'on' == $_SERVER['HTTPS']) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://'; return $http . $_SERVER['HTTP_HOST']; } // 唯一身份ID function uniq_id() { return uniqid(substr(md5(microtime(true) . mt_rand(1000, 9999)), 8, 8)); } // 生成订单号 14位 function trade_no() { $trade_no = str_replace('.', '', microtime(1)); $strlen = mb_strlen($trade_no, 'UTF-8'); $strlen = 14 - $strlen; $str = ''; if ($strlen) { for ($i = 0; $i <= $strlen; $i++) { if ($i < $strlen) $str .= '0'; } } return $trade_no . $str; } // 生成订单号 16位 function trade_no_16() { $explode = explode(' ', microtime()); $trade_no = $explode[1] . mb_substr($explode[0], 2, 6, 'UTF-8'); return $trade_no; } // 当前年的天数 function date_year($time = NULL) { $time = intval($time) ? $time : time(); return date('L', $time) + 365; } // 当前年份中的第几天 function date_z($time = NULL) { $time = intval($time) ? $time : time(); return date('z', $time); } // 当前月份中的第几天,没有前导零 1 到 31 function date_j($time = NULL) { $time = intval($time) ? $time : time(); return date('j', $time); } // 当前月份中的第几天,有前导零的2位数字 01 到 31 function date_d($time = NULL) { $time = intval($time) ? $time : time(); return date('d', $time); } // 当前时间为星期中的第几天 数字表示 1表示星期一 到 7表示星期天 function date_w_n($time = NULL) { $time = intval($time) ? $time : time(); return date('N', $time); } // 当前日第几周 function date_d_w($time = NULL) { $time = intval($time) ? $time : time(); return date('W', $time); } // 当前几月 没有前导零1-12 function date_n($time = NULL) { $time = intval($time) ? $time : time(); return date('n', $time); } // 当前月的天数 function date_t($time = NULL) { $time = intval($time) ? $time : time(); return date('t', $time); } // 0 o'clock on the day function clock_zero() { return strtotime(date('Ymd')); } // 24 o'clock on the day function clock_twenty_four() { return strtotime(date('Ymd')) + 86400; } // 8点过期 / expired at 8 a.m. function eight_expired($time = NULL) { $time = intval($time) ? $time : time(); // 当前时间大于8点则改为第二天8点过期 $life = date('G') <= 8 ? (strtotime(date('Ymd')) + 28800 - $time) : clock_twenty_four() - $time + 28800; return $life; } // 24点过期 / expired at 24 a.m. function twenty_four_expired($time = NULL) { $time = intval($time) ? $time : time(); $twenty_four = clock_twenty_four(); $life = $twenty_four - $time; return $life; } /** * @param $url 提交地址 * @param string $post POST数组 / 空为GET获取数据 / $post='GET'获取连续跳转最终URL * @param string $cookie cookie * @param int $timeout 超时 * @param int $ms 设为1是毫秒 * @return mixed 返回数据 */ function https_request($url, $post = '', $cookie = '', $timeout = 30, $ms = 0) { if (empty($url)) return FALSE; if (version_compare(PHP_VERSION, '5.2.3', '<')) { $ms = 0; $timeout = 30; } is_array($post) and $post = http_build_query($post); // 没有安装curl 使用http的形式,支持post if (!extension_loaded('curl')) { //throw new Exception('server not install CURL'); if ($post) { return https_post($url, $post, $cookie, $timeout); } else { return http_get($url, $cookie, $timeout); } } is_array($cookie) and $cookie = http_build_query($cookie); $curl = curl_init(); // 返回执行结果,不输出 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //php5.5跟php5.6中的CURLOPT_SAFE_UPLOAD的默认值不同 if (class_exists('\CURLFile')) { curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); } else { defined('CURLOPT_SAFE_UPLOAD') and curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); } // 设定请求的RUL curl_setopt($curl, CURLOPT_URL, $url); // 设定返回信息中包含响应信息头 if (ini_get('safe_mode') && ini_get('open_basedir')) { // $post参数必须为GET if ('GET' == $post) { // 安全模式时将头文件的信息作为数据流输出 curl_setopt($curl, CURLOPT_HEADER, true); // 安全模式采用连续抓取 curl_setopt($curl, CURLOPT_NOBODY, true); } } else { curl_setopt($curl, CURLOPT_HEADER, false); // 允许跳转10次 curl_setopt($curl, CURLOPT_MAXREDIRS, 10); // 使用自动跳转,返回最后的Location curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); } $ua1 = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'; $ua = empty($_SERVER["HTTP_USER_AGENT"]) ? $ua1 : $_SERVER["HTTP_USER_AGENT"]; curl_setopt($curl, CURLOPT_USERAGENT, $ua); // 兼容HTTPS if (FALSE !== stripos($url, 'https://')) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); //ssl版本控制 //curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_setopt($curl, CURLOPT_SSLVERSION, true); } $header = array('Content-type: application/x-www-form-urlencoded;charset=UTF-8', 'X-Requested-With: XMLHttpRequest'); $cookie and $header[] = "Cookie: $cookie"; curl_setopt($curl, CURLOPT_HTTPHEADER, $header); if ($post) { // POST curl_setopt($curl, CURLOPT_POST, true); // 自动设置Referer curl_setopt($curl, CURLOPT_AUTOREFERER, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $post); } if ($ms) { curl_setopt($curl, CURLOPT_NOSIGNAL, true); // 设置毫秒超时 curl_setopt($curl, CURLOPT_TIMEOUT_MS, intval($timeout)); // 超时毫秒 } else { curl_setopt($curl, CURLOPT_TIMEOUT, intval($timeout)); // 秒超时 } //优先解析 IPv6 超时后IPv4 //curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_setopt($curl, CURLOPT_ENCODING, 'gzip'); // 返回执行结果 $output = curl_exec($curl); // 有效URL,输出URL非URL页面内容 CURLOPT_RETURNTRANSFER 必须为false 'GET' == $post and $output = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); curl_close($curl); return $output; } function save_image($img) { $ch = curl_init(); // 设定请求的RUL curl_setopt($ch, CURLOPT_URL, $img); // 设定返回信息中包含响应信息头 启用时会将头文件的信息作为数据流输出 //curl_setopt($ch, CURLOPT_HEADER, false); //curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER["HTTP_USER_AGENT"]); // true表示$html,false表示echo $html curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); $output = curl_exec($ch); curl_close($ch); return $output; } // 计算字串宽度:剧中对齐(字体大小/字串内容/字体链接/背景宽度/倍数) function calculate_str_width($size, $str, $font, $width, $multiple = 2) { $box = imagettfbbox($size, 0, $font, $str); return ($width - $box[4] - $box[6]) / $multiple; } // 搜索目录下的文件 比对文件后缀 function search_directory($path) { if (is_dir($path)) { $paths = scandir($path); foreach ($paths as $val) { $sub_path = $path . '/' . $val; if ('.' == $val || '..' == $val) { continue; } else if (is_dir($sub_path)) { //echo '目录名:' . $val . '
'; search_directory($sub_path); } else { //echo ' 最底层文件: ' . $path . '/' . $val . '
'; $ext = strtolower(file_ext($sub_path)); if (in_array($ext, array('php', 'asp', 'jsp', 'cgi', 'exe', 'dll'), TRUE)) { echo '异常文件:' . $sub_path . '
'; } } } } } // 一维数组转字符串 $sign待签名字符串 $url为urlencode转码GET参数字符串 function array_to_string($arr, &$sign = '', &$url = '') { if (count($arr) != count($arr, 1)) throw new Exception('Does not support multi-dimensional array to string'); // 注销签名 unset($arr['sign']); // 排序 ksort($arr); reset($arr); // 转字符串做签名 $url = ''; $sign = ''; foreach ($arr as $key => $val) { if (empty($val) || is_array($val)) continue; $url .= $key . '=' . urlencode($val) . '&'; $sign .= $key . '=' . $val . '&'; } $url = substr($url, 0, -1); $url = htmlspecialchars($url); $sign = substr($sign, 0, -1); } // 私钥生成签名 function rsa_create_sign($data, $key, $sign_type = 'RSA') { if (!function_exists('openssl_sign')) throw new Exception('OpenSSL extension is not enabled'); if (!defined('OPENSSL_ALGO_SHA256')) throw new Exception('Only versions above PHP 5.4.8 support SHA256'); $key = wordwrap($key, 64, "\n", true); if (FALSE === $key) throw new Exception('Private Key Error'); $key = "-----BEGIN RSA PRIVATE KEY-----\n$key\n-----END RSA PRIVATE KEY-----"; if ('RSA2' == $sign_type) { openssl_sign($data, $sign, $key, OPENSSL_ALGO_SHA256); } else { openssl_sign($data, $sign, $key, OPENSSL_ALGO_SHA1); } // 加密 return base64_encode($sign); } // 公钥验证签名 function rsa_verify_sign($data, $sign, $key, $sign_type = 'RSA') { $key = wordwrap($key, 64, "\n", true); if (FALSE === $key) throw new Exception('Public Key Error'); $key = "-----BEGIN PUBLIC KEY-----\n$key\n-----END PUBLIC KEY-----"; // 签名正确返回1 签名不正确返回0 错误-1 if ('RSA2' == $sign_type) { $result = openssl_verify($data, base64_decode($sign), $key, OPENSSL_ALGO_SHA256); } else { $result = openssl_verify($data, base64_decode($sign), $key, OPENSSL_ALGO_SHA1); } return $result === 1; } // Array to xml array('appid' => 'appid', 'code' => 'success') function array_to_xml($arr) { if (!is_array($arr) || empty($arr)) throw new Exception('Array Error'); $xml = ""; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . ""; } else { $xml .= "<" . $key . ">"; } } $xml .= ""; return $xml; } // Xml to array function xml_to_array($xml) { if (!$xml) throw new Exception('XML error'); $old = libxml_disable_entity_loader(true); // xml解析 $result = (array)simplexml_load_string($xml, null, LIBXML_NOCDATA | LIBXML_COMPACT); // 恢复旧值 if (FALSE === $old) libxml_disable_entity_loader(false); return $result; } // 逐行读取 function well_import($file) { if ($handle = fopen($file, 'r')) { while (!feof($handle)) { yield trim(fgets($handle)); } fclose($handle); } } // 计算总行数 function well_import_total($file, $key = 'well_import_total') { static $cache = array(); if (isset($cache[$key])) return $cache[$key]; $count = cache_get($key); if (NULL === $count) { $count = 0; $globs = well_import($file); while ($globs->valid()) { ++$count; $globs->next(); // 指向下一个 } $count and cache_set($key, $count, 300); } return $cache[$key] = $count; } $g_dir_file = FALSE; function well_search_dir($path) { global $g_dir_file; FALSE === $g_dir_file and $g_dir_file = array(); if (is_dir($path)) { $paths = scandir($path); foreach ($paths as $val) { $sub_path = $path . '/' . $val; if ('.' == $val || '..' == $val) { continue; } else if (is_dir($sub_path)) { well_search_dir($sub_path); } else { $g_dir_file[] = $sub_path; } } } return $g_dir_file; } ?>嵌入式软件技术笔记
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

嵌入式软件技术笔记

运维笔记admin0浏览0评论

1、文件的简单读取操作

	FILE *file = fopen("1.txt","r"); //打开文件 
	if(file==NULL)//判断是否打开 
	{
		printf("file can not open\n");
	}else
	{
		printf("file open success!\n");
	}
	int c;
	while((c= fgetc(file))!=EOF) //逐字符读取文件 
	{
		printf("%c",c);
		//putchar(c); 输出单个字符 ,不需要解析格式化字符串,效率高 适合于输出大量字符, 
	}
	fclose(file);

2、输入

int fgetc(FILE* stream);//从指定文件中读取单个字符
char* fgets(char* str, int size, FILE* stream);
//从指定输入流(文件(FILE 类型的指针)/键盘(stdin))读取指定长度数据sizeof(input),并存放在input中。

3、字符串处理函数

char* strncpy(char* dest, const char* src, size_t n);
//将源字符串的前 n 个字符复制到目标字符串中。返回目标字符串 dest 的指针。

char* strcat(char* dest, const char* src);
//将一个字符串追加到另一个字符串的末尾。返回目标字符串 dest 的指针。用于字符串拼接

size_t strcspn(const char* str, const char* charset);
//计算字符串中不包含指定字符集的最长前缀长度。返回从字符串开头到第一个匹配字符的长度。
常用于去掉字符串末尾的换行符或其他特定字符。
例:char str[] = "Hello, World!\n";
    char charset[] = "\n"; // 要查找的字符集

    size_t len = strcspn(str, charset); // 查找换行符的位置
    str[len] = '\0'; // 去掉换行符

4、计算机网络学习

4.0.0 以太网

  • 以太网是当今局域网(LAN)采用的最通用的通信协议标准,以太网是指遵循IEEE802.3标准组成的局域网。该标准主要规定了物理层、和数据链路层中的MAC层。应用于家庭、校园网络,工业环境中通过以太网连接自动化设备、实习数据中心内部设备的互联。
  • IEEE还有其他标准,如IEEE802.11是无线局域网,即WIFI。 IEEE802.15是个人域网,即蓝牙技术。
  • 以太网通信结构OSI模型:应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层。。。OSI模型是理想分层,一般的网络系统只是涉及其 中几层
  • 以太网物理层中规定了以太网使用的传输介质、传输速度、数据编码方式、冲突检测机制等,他是通过一个PHY芯片实现。:传输介质有双绞线、同轴电缆、光纤。编码采用曼彻斯特编码:每个位周期都有电压变化。4B/5B编码:每四位由5位进行表示。CSMA/CD(载波监听多路访问/冲突检测):早期以太网是多节点连接到一条总线上的,存在信道竞争问题。现在以太网多使用星型网络,一个设备接入到一个独立的交换机中组成星型网络。
  • MAC子层是数据链路层的下半部分,主要负责和物理层进行数据交接,它自动对来自上层的数据包加上一些控制信息交给物理层。接收方得到正确数据后,自动去除MAC控制信号,把该数据包交给上层。

4.0.1集线器与交换机

  • 集线器(Hub):半双工设备,所有数据都广播,只能用cdma/cd检测广播域,已经被淘汰
  • 交换机:用于在局域网中连接多个设备并根据数据帧的目的地址智能转发数据,是全双工设备,工作在OSI模型的第二层。功能:①帧转发:根据帧目的MAC地址,将数据转发到正确端口。②维护一个MAC地址表:记录每个设备的MAC地址。③冲突域隔离:交换机的每个接口都可以提供一个独立的冲突域,减少冲突,能实现各个设备同时收发数据,全双工通信。④支持虚拟局域网(VLAN):将网络划分为多个逻辑子网,优化网络管理。

交换机只能将一个网络中的数据进行转发,如果要将数据从一个网络转发到另一个网络,这时候就需要路由器进行IP地址选择,转发。

  • 路由器:是一种网络设备:用于在不同的网络中转发数据包,工作在OSI模型中第三层(网络层),根据数据包目的IP地址进行路由选择。功能:①路由选择:根据路由表中内容,选择最佳路径转发数据到目标网络。②子网划分:可以将一个网络划分为多个子网。③NAT(网络地址转换);允许多个设备共享一个公共IP地址,节约IP地址资源④防火墙功能:许多路由器内置防火墙,可以过滤数据包并提供网络保护。⑤协议转换:支持多种网络协议转换,如在以太网和wiFI之间转发数据。

4.0.2 MAC地址与IP地址

  • MAC地址:在网络中唯一标识一个网卡,每个网卡有全球唯一的一个MAC地址(网络设备的物理地址)。有48位组成,通常以冒号或连字符分隔(如00:1A:2B:3C:4D:5E)。它是由设备制造商在生产时烧录到网络接口卡(NIC)中的,是全球唯一的。​​​​​​​作用:MAC地址用于在数据链路层(OSI模型的第二层)标识设备,并实现同一网络中的设备之间的通信。它主要用于局域网(LAN)内的设备识别和帧转发。MAC数据包由前导字段、帧起始定界符、目标地址、源地址、数据包类型、数据域、填充域、校验和域组成。
  • IP地址:是在互联网协议网络中标识设备的逻辑地址,它是一个32位(IPv4)或128位(IPv6)的数字,通常以点分十进制(如192.168.1.1)或冒号分十六进制(如2001:0db8:85a3:0000:0000:8a2e:0370:7334)格式表示。IP地址用于在网络层(OSI模型的第三层)标识设备,并实现设备之间的通信。它支持路由功能,允许数据包在不同网络之间传输。IP地址是可变的。
  • IP地址配置方式

    • 手动配置:可以通过网络管理员手动分配。

    • 自动配置:可以通过动态主机配置协议(DHCP)自动分配。

  • 交换机如何减少网络冲突?   ​​​​​​​​​​​​​​

 划分冲突域、智能帧转发、存储转发机制、动态学习、老化机制、流量控制机制

  • TCP/IP是一组用于互联通信的协议族 包括多个协议如TCP、UDP、IP、ICMP、ARP等。TCP/IP混合模型主要可分为五层,它实际与TCP/IP 四层模型是相通的,只是把网络访问层拆成数据链路层和物理层。:
  • 为什么需要协议栈?物理层主要定义物理介质性质,MAC子层负责与物理层进行数据交接,这两部分是与硬件紧密 联系的。如果所有设备都约定使用一种互联方式, 在软件上加一些层次来封装,这样不同系统、不同的设备通讯就变得相对容易了。在各种协议栈中 TCP/IP 协议栈得到了最广泛使用。
  • 在TCP/IP协议栈中:用以太网和Wi-Fi作例子,它们的MAC子层和物理层有较大的区别,但在MAC之上的LLC层、 网络层、传输层和应用层的协议,是基本相同的,这几层协议由软件实现,并对各层进行封装。根据TCP/IP协议,各层的要实现的功能如下:
  1. 物理层
  2. (数据链路层的)MAC层   。(数据链路层的)LLC层:处理传输错误,协调收发双方速度,主要使用数据链路协议。传输数据帧.如以太网、ATM、PPP。
  3. 网络层(IP层):LLC层主要负责将数据从线一端传到另一端,但当设备位于不同网络中时,需要网络层来解决子网路由拓扑问题、路径选择问题。主要有Ip协议、ICMP协议。负责网络地址的分配和路由选择。
  4. 传输层:有网络层处理好网络传输路径之后,端到端的路径就建立起来了。传输层负责处理端到端的通信。主要有TCP协议、UDP协议。
  5. 应用层:经过前面三层,网络完全建立起来了,应用层可以通过调用传输层的接口来编写特定的应用程序。。而TCP/IP协议一般也会包含一些简单的应用程序如Telnet远程登录、FTP文件传输、 SMTP邮件传输协议。为用户提供网络服务。

        实际上,在发送数据时,经过网络协议栈的每一层,都会给来自上层的数据添加上一个数据包的 头,再传递给下一层。在接收方收到数据时,一层层地把所在层的数据包的头去掉,向上层递交 数据,

4.1.0常见的网络协议

常见的几种网络协议

协议名称

功能

工作层次

应用场景

DNS:域名系统

将域名转为IP地址。

应用层

网页浏览、电子邮件发送时

SMTP:简单电子邮件发送协议

定义了收发双方之间的通信规则

应用层

电子邮件的收发

HTTP:超文本传输协议

用于传输超文本如(HTML页面)。明文传输,不加密。数据容易被窃听和篡改。

应用层

网页浏览、Web 应用程序通信。协议简单,适用于快速传输网页内容。非敏感信息传输

HTTPS:

通过 SSL/TLS协议对数据进行加密。使用数字证书验证服务器身份

应用层

HTTPS 是 HTTP 的安全版本。适用于敏感信息传输(如登录信息、支付信息)

FTP:文件传输协议

允许用户在客户端和服务器之间上传和下载文件

应用层

文件传输,如网站维护、文件共享等

TCP:传输控制协议

面向连接的、可靠的传输层协议。它通过确认、重传机制、流量控制和拥塞控制等技术,确保数据的可靠传输。

传输层

对数据可靠性要求较高的应用,如 HTTP、FTP、SMTP

UDP:用户数据报协议

无连接的、不可靠的传输层协议。它不保证数据的可靠传输,但协议简单,开销小,适合对实时性要求较高的应用。

传输层

对实时性要求较高的应用,如语音通话(VoIP)、视频流、在线游戏等

IP:互联网协议

将数据包从源主机路由到目标主机。它提供了主机之间的逻辑地址(IP 地址),并负责数据包的分片和重组。

网络层

是 TCP/IP 协议族的基础。

ICMP:因特网控制报文协议

用于发送错误消息和操作信息的网络层协议。用于诊断网络问题,例如检测主机或网络是否可达(如 ping 命令)。

网络层

网络诊断和管理

IGMP:互联网组播管理协议

用于管理主机和路由器之间的组播组成员关系。优化组播流量的传输避免不必要的广播。网络层优化游戏中的组播通信、优化游戏中的组播通信

ARP:地址解析协议

将 IP 地址解析为 MAC 地址的协议数据链路层与网络层之间局域网内的 IP 地址到 MAC 地址的解析

4.2.0三层路由协议:

        路由协议用于决定数据包在网络中的传输路径。

1、静态路由协议:

        由网络管理员手动配置的路由条目,指定到达特定网络的路径。

特点:手动配置、配置简单、适于小型简单网络、无法自适应网络拓扑变化,网络故障时不能自动选择路由。但不会受到动态路由协议的潜在安全威胁。

2、动态路由协议

2.1、OSPF 开放式最短路径优先:基于最短路径优先算法,适于大型网络,能快速适应拓扑变化。通过定期交换链路状态信息,动态更新路由表,确保网络中的设备能够快速适应拓扑变化

2.2、RIP 路由信息协议:简单,适于小型网络,跳数限制为15跳,超过15跳的网络被视为不可达。

3、静态路由与动态路由的比较

4、虚拟路由冗余协议:

VRRP 是一种虚拟路由冗余协议,用于提高网络的可靠性。它通过配置多个路由器为一个虚拟路由器,确保在主路由器故障时,备用路由器能够无缝接管

4.3 SOCKET编程:

socket是一套用于不同主机间通信的API,他工作在TCP/IP协议栈之上。浏览器、手机应用、等场景都有应用。要通过socket进行不同主机之间的通信,只需要指定主机的端口号和ip地址。端口号用于区分数据应该发送到哪一个应用上,IP地址用于唯一标识你的网络设备。

1、TCP套接字:

        基于 TCP(Transmission Control Protocol)协议的套接字。TCP 是一种面向连接的、可靠的、基于字节流的传输层协议。

                                        TCP 服务器

import socket

# 创建 TCP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_socket.bind(('localhost', 12345))

# 监听连接
server_socket.listen(5)
print("Server is listening on port 12345...")

# 接受连接
client_socket, client_address = server_socket.accept()
print(f"Connection from {client_address}")

# 接收数据
data = client_socket.recv(1024)
print(f"Received data: {data.decode()}")

# 发送响应
client_socket.sendall("Hello from server".encode())

# 关闭连接
client_socket.close()
server_socket.close()

                                    TCP 客户端

import socket

# 创建 TCP 套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
client_socket.connect(('localhost', 12345))

# 发送数据
client_socket.sendall("Hello from client".encode())

# 接收响应
data = client_socket.recv(1024)
print(f"Received response: {data.decode()}")

# 关闭连接
client_socket.close()




2、UDP套接字:

        基于 UDP(User Datagram Protocol)协议的套接字。UDP 是一种无连接的、不可靠的传输层协议。

                                        UDP 服务器
import socket

# 创建 UDP 套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 绑定地址和端口
server_socket.bind(('localhost', 12345))
print("Server is listening on port 12345...")

# 接收数据
data, client_address = server_socket.recvfrom(1024)
print(f"Received data from {client_address}: {data.decode()}")

# 发送响应
server_socket.sendto("Hello from server".encode(), client_address)

# 关闭套接字
server_socket.close()

                                            UDP 客户端
import socket

# 创建 UDP 套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 发送数据
server_address = ('localhost', 12345)
client_socket.sendto("Hello from client".encode(), server_address)

# 接收响应
data, server_address = client_socket.recvfrom(1024)
print(f"Received response from {server_address}: {data.decode()}")

# 关闭套接字
client_socket.close()

1、什么是网络编程?

编写程序使两台联网的计算机相互交换数据,利用操作系统提供的套接字进行编程。又称为套接字编程。主要工作:在发送端把信息提供规定好的协议进行组装包,在接受端按照规定的协议把包进行解析,从而提取对应的信息。主要是:数据包的组装,过滤、捕获、分析。

2、什么是套接字?

在网络编程中,socket是通讯的基础,通过它可以在网络中进行数据传输实现在不同主机之间的应用程序之间通信。(需指定主机IP地址和端口号)可以看作计算机网络应用程序之间的一个接口。套接字被封装为一个文件描述符,可以使用系统函数来创建、绑定、监听和连接套接字。套接字提供了一种面向TCP(流)或数据报(UDP)的通信方式。

3、TCP和UDP区别是什么?

连接性:TCP面向连接,在通讯之前要建立连接,并保持连接状态到通信结束。UDP无连接,因此减少了开销和建立连接的时延。

可靠性:TCP提供可靠的数据传输,通过确认、重传、和流量控制等机制确保数据的准确性和顺序性。UDP不保证可靠交付、尽最大努力交付,对于数据丢失或乱序现象,应用程序需要自行处理。

速度:由于TCP提供的可靠性保证机制较多(),在网络环境良好情况下,可能会导致一定延迟。UDP没有这些机制,在延迟要求较高、或带宽利用率更重要的场景中更适用。

数据量限制:TCP对数据进行分段并管理拥塞控制,可以处理任意大小的数据流。UDP没有拥塞控制 ,对数据包大小有一定限制(如IPv4限制为65,507字节)。超限时需要分片处理。

⑤面向对象:TCP面向字节流,TCP把应用程序交下来的数据仅看作一串无结构的字节流。UDP面向报文,对应用程序交下来的报文在添加首部后就向下交付IP层,既不合并也不拆分。

通信方式:TCP是全双工通信,允许双方应用任何时候都能发送数据,TCP两端都设有发送缓存和接收缓存,来存放临时数据,上层的应用在合适时候读取缓存。UDP是半双工。

连接:每一个TCP连接只能有两个端点(点对点)。UDP支持一对一、一对多、多对多。

⑧应用场景TCP常用于对可靠性要求较高、顺序要求严格、传输规模较大的应用,例如网页浏览、文件传输和电子邮件等。UDP常用于实时性要求较高、丢失一些数据不会对应用造成严重影响的应用,例如音频/视频传输、实时游戏和DNS查询等。

4、解释TCP的三次握手和四次挥手过程。

TCP的三次握手和四次挥手过程是为了建立和终止TCP连接而设计的。。。

①三次握手:

  1. 初始时客户端A服务器B均处于CLOSED状态。
  2. A向B发送一个SYN同步标志数据包,主动请求打开连接,客户端进入 SYN_SENT 状态。此时B进入收听(LISTEN)状态。B收到请求后,确认收到并返回一个带有ACK(确认信号)和SYN标志的数据包作为响应。此时服务器B还会分配资源用于接收客户端A的数据。此时服务器B进入 SYN_RCVD 状态。
  3. 客户端A收到B的响应后,发一个带ACK的数据包作为最终确认,此时A、B均进入 ESTABLISHED(已建立)状态,可以开始传输数据。

②四次挥手:

数据传输结束后双方都可以释放连接。

当客户端A想要结束连接时:

  1. 客户端发送一个带有FIN(结束)标志的数据包给服务器。此时客户端进入FIN-WAIT-1状态。服务器A接收到关闭请求后,回复一个ACK标志的数据来确认,之后服务器进入CLOSE-WAIT状态等待关闭信号。此时TCP连接属于半关闭状态(half-close)。(服务器到客户端的连接仍未关闭)。
  2. 客户端收到服务器的确认后,进入FIN-WAIT-2(终止等待2)状态.等服务器发来连接释放报文段。若服务器已没有要发送的数据给客户端,则其应用进程就通知TCP释放连接。即服务器确定自己已经完成所有传输任务后,发送一个带有 FIN 标志的数据包给客户端。此时服务器进入 LAST_ACK 状态。
  3. 客户端收到服务器的关闭请求后,发送一个 ACK 标志的数据包进行确认。此时客户端和服务器都进入 CLOSED(已关闭)状态。

5、环形队列:

在逻辑上是环形的,但在物理上是一个定长的数组。他是先进先出的,队尾进行插入、队头进行删除。

  1. 优点是:当队列满时,可以通过覆盖队列头部的元素来继续存储新数据,节省存储空间。
  2. 缺点:无法在任意位置插入、删除元素,只能在两端进行操作。需要额外的指针进行维护队列状态,增加了复杂度。队列大小难以动态调整
  3. 应用于计算机中的任务调度、打印机任务队列、网络通信、循环播放音频等。

初始状态下:tail和head都是指向数据下标0,每写入一个元素,tail往后移动一个指针,每读取一个元素head往后读取一个指针。

判断是否为空:(rb->head == rb->tail) && !rb->is_full

判断是否为满:在写入操作之后进行判断,rb->tail == rb->head

写入数据时:尾指针后移rb->tail= (rb->tail+ 1) % maxSize

读出数据时:头指针后移rb->head= (rb->head+ 1) % maxSize

#define BUFFER_SIZE 30
typedef struct{
	unsigned char buffer[BUFFER_SIZE];
	unsigned char head;
	unsigned char tail;
	unsigned char length;
	bool is_full;
	
}RingBuffer;

void ring_buffer_init(RingBuffer *rb)
{
	rb->head=0;
	rb->tail=0;
	rb->length=0; 
	rb->is_full=false;
}

//写数据到环形队列
bool ring_buffer_write(RingBuffer *rb,unsigned char data)
{
	//判断写入前队列是否满
	if(rb->is_full == true)
	{
		return false;
	 } 
	 rb->buffer[rb->tail]=data;
	 rb->tail = (rb->tail+1) % BUFFER_SIZE ;
	 rb->length++;
	 //判断写入后缓冲区是否已满 
	 if(rb->tail == rb->head) //写指针追上读指针 
	 {
	 	rb->is_full=true;
	 }
	 return true;
	 
}
//从环形队列读数据 
bool ring_buffer_read(RingBuffer *rb,unsigned char* data)
{

	//判断缓冲区是否为空 
	if((rb->head == rb->tail) && !rb->is_full )
	{
		return false;
	 } 
	 *data = rb->buffer[rb->head];
	// rb->buffer[rb->head]=0; 不用清除,后续会自动覆盖的 
	 rb->head = (rb->head+1) % BUFFER_SIZE ;
	 rb->length--;
	 
   	rb->is_full=false;//一旦读取,缓冲区就不满 
	 return true;
	 
}
int main()
{
  RingBuffer rb;
    ring_buffer_init(&rb);

    // 写入数据
    for (int i = 0; i < 30; i++) {
        if (!ring_buffer_write(&rb, i)) {
            printf("写入失败,队列已满\n");
            break;
        }
    }

    // 读取数据
    unsigned char data;
    while (ring_buffer_read(&rb, &data)) {
        printf("读取数据:%d\n", data);
    }

}

6、Make file:

是用来管理和编译工程的。在大工程中会有多个.c .h文件,比如在linux系统中一个一个进行编译再链接 会严重降低工作效率,这时候可以使用make命令进行编译。

  • 说白了就是把你要做的好多事情预先写好,当我们make 目标的时候,它会自动执行那些目标下的命令。

7、Linux入门

7.1 vim编程

vi编辑器是一款文本编辑器,vim是vi编辑器的增强版,他们的使用方法是一样的,只是增强了一些新的功能和改进。应用:代码编写、编辑配置文件(.vimrc)等:编写和编辑各种编程语言的代码,如 Python、C、Java 等。

  • 有关vim编辑器的命令:
1、vi/vim进入vim界面,vi/vim + 文件名:打开这个文件,如果文件不存在就会自动创建这个文件
2、:heli查看帮助信息
3、:q退出vim,  :wq 保存并退出,  
4、vim中有三种常用模式:命令模式、插入模式、尾行模式。默认进入是命令模式
5、命令模式下:可以浏览、复制、粘贴、查找、删除文件。(命令模式下输入i/I a/A o/O进入)--->插入模式:编辑文件。按下键盘ESC键会退出插入模式进入命令模式。a/i/o等决定了编辑时光标的初始位置。
6、ls:当前目录下的文件、文件夹
7、cat  文件名 :查看文件内容
8、在vi编辑器中,键盘h/j/k/l分别表示将光标左移、下移、上移、右移一个单位。"^" :跳转到当前行首,
 “$” :跳转到当前行尾。“yy”:复制一行内容。“p”:将复制的内容粘贴到光标下一行。“dd”:删除一行内容。
“p”:将刚刚删除的内容粘贴到光标下一行。“2yy”:复制两行内容,即这几个命令前加上数字,可以操作多行。
9、“:set number”/“:set nu”:为文件加上行号 “:set nonumber”:关闭行号显示
10、"ctrl+f"/"ctrl+b":快速向前/向后翻页
11、“G”:跳到文件最后一行,“gg/g”:跳到文件第一行,“10G”/“:10”:跳转到文件第十行
12、命令模式下,“/查找内容”:向下找,“?/查找内容”:向上找 
13、“u”:撤销操作
14、“vi .vimrc”:保存vi编辑器的一些配置信息,可以设置快捷键、插件等。
15、

7.2shell编程:

  • shell是一个命令行解释器,它可以接收用户输入的命令,然后调用操作系统的内核去执行这些命令,再把执行的结果返回给用户。shell脚本可以用来编写一些自动化的任务,比如安装软件、定时运行任务、文件操作等。也可以进行系统管理。一般来说  shell文件以.sh结尾。shell编程支持分支、判断、循环等,也可以定义函数、变量以及调用系统其他程序、文件读写。
  1. 什么是shell变量?Shell 变量是用来存储数据的命名位置。每个变量都有一个名称(标识符)和一个对应的值。在 Shell 中,变量可以存储字符串、数字或任何有效的数据类型。
  2. 使用变量的值需要在变量名前面加上美元符号($)
  3. 除了用户定义的变量,Shell 还提供了一些特殊的预定义变量,如: 

  • $HOME:当前用户的主目录路径。
  • $USER:当前用户的用户名。
  • $PATH:执行命令时搜索的路径列表。
  • $PWD:当前工作目录的路径。
  • $0:当前脚本或命令的名称。
  1. 在 Shell 中,通过特定的变量名来获取传递给脚本的参数。这些变量如下:
  • $0:脚本本身的名称。
  • $1, $2, …, $n:分别是传递给脚本的第一个、第二个直到第 n 个参数。
  • $@:表示所有的参数列表,每个参数被视为一个单独的字符串。
  • $#:传递给脚本的参数个数。
  • #!/bin/bash
    
    echo "Script name: $0"
    echo "First parameter: $1"
    echo "Second parameter: $2"
    echo "All parameters: $@"
    echo "Number of parameters: $#"
    

    在这个示例中,假设脚本名为 example.sh,执行如下命令:./example.sh hello world

  • 输出将会是:

    Script name: ./example.sh
    First parameter: hello
    Second parameter: world
    All parameters: hello world
    Number of parameters: 2
    

7.3 一些linux命令:

1、cd 切换当前目录,它的参数是要切换到的目录的路径,可以是绝对路径,也可以是相对路径
2、mkdir <目录名>  创建目录
3、rm  file1 删除文件
4、rmdir dir1 删除’dir1’⽬录
5、pwd 显示工作路径
6、ls 查看目录中的文件
7、cp 复制文件
8、cat 查看文件内容
9、find 查找指定文件/目录
10、chomd 修改文件权限
11、chowm 改变文件所有者
12、sort 排序两个文件
13、paste 查看两个文件合并后内容
14、comm 比较两个文件并删除指定内容
15、tar 打包文件
/********************************************关机、注销、重启*****************************/
查看进程端口号:netstat -tunlp|grep 端口号 
ss -tnl  查看正在已使用的端口
shutdown -h now 关闭系统(1) 即刻关机
shutdown -h 10 10分钟后关机
shutdown -h 11:00  11:00 关机
shutdown -h +10 预定时间关机(10分钟后关机)
shutdown -c  取消指定时间关机
shutdown -f now 重启
shutdown -r 10  10分钟后重启
shutdown -r 11:00   定时重启
reboot 重启
init 6 重启
init 0 即刻关机
telinit 0 关机
poweroff   立刻关机
halt 关机
sync  buff数据同步到磁盘
logout 退出登录Shell
time 测算一个命令(即程序)的执行时间
/********************************************磁盘和分区***********************************/
# 查看所属有磁盘分区
fdisk -l
# 查看所有交换分区
swapon -s
# 查看磁盘使用情况及挂载点
df -h
# 查看磁盘使用情况及挂载点
df -hl
# 查看指定某个目录大小
du -sh /dir
# 从高到底依次显示文件和目录大小
du -sk * | sort -rn
# 查看内存
free -h
# 查看CPUs
cat /proc/cpuinfo


# 挂在hda2盘
mount /dev/hda2 /mnt/hda2
# 指定⽂件系统类型挂载(如ntfs)
mount -t ntfs /dev/sdc1 /mnt/usbhd1
# 挂载iso⽂件
mount -o loop xxx.iso /mnt/cdrom
# 挂载usb盘/闪存设备
mount /dev/sda1 /mnt/usbdisk
# 通过设备名卸载
umount -v /dev/sda1
# 通过挂载点卸载
umount -v /mnt/mymnt
# 强制卸载(慎⽤)
fuser -km /mnt/hda1
/**********************************用户和用户组*******************************************/
# 创建用户
useradd ss
# 查看所用系统用户
cut -d: -f1 /etc/passwd
# 删除用户
userdel -r ss
# 创建用户组
groupadd group_name
# 查看系统所有组
cut -d: -f1 /etc/group
# 删除用户组
groupdel group_name
# 修改用户的组
usermod -g group_name user_name
# 将用户添加到组
usermod -aG group_name user_name
# 修改用户 ss 的登录 Shell、主目录及用户组
usermod -s /bin/ksh -d /home/codepig –g dev ss
# 查看 ss 用户所在的组
groups ss
# 切换到另一个用户环境
su user_name
# 修改口令
passwd
# 修改用户密码
passwd ss
# 查看用户活动
w
# 查看指定用户 ss 的信息
id ss
# 查看用户登录日志
last
# 查看当前用户的计划任务
crontab -l
/***************************网络和进程管理*************************************************/
# 查看网络接口属性
ifconfig
# 查看某网卡的配置
ifconfig eth0
# 查看路由表
route -n
# 查看所有监听端⼝
netstat -lntp
# 查看已经建立连接的TCP连接
netstat -antp
# 查看TCP/UDP的状态信息
netstat -lutp
# 启⽤eth0⽹络设备
ifup eth0
# 禁⽤eth0⽹络设备
ifdown eth0
# 查看iptables规则
iptables -L
# 配置ip地址
ifconfig eth0 192.168.1.1 netmask 255.255.255.0
# 以dhcp模式启⽤eth0
dhclient eth0
# 配置默认⽹关
route add -net 0/0 gw Gateway_IP
# 配置静态路由到达⽹络'192.168.0.0/16'
route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1
# 删除静态路由
route del 0/0 gw Gateway_IP
# 查看主机名
hostname
# 解析主机名
host 主机名  例如:host www.baidu
# 查询DNS记录,查看域名解析是否正常
nslookup 主机名  例如:nslookup wwww.baidu
# 查看所有进程
ps -ef
# 过滤出你需要的进程
ps -ef|grep redis
# kill指定名称的进程
kill -s name
# kill指定pid的进程
kill -s pid
/*********************************查看文件大小******************************************/
# 查看当前目录总大小
du -sh
# 查看当前目录所有子目录大小
du -sh *
# 查看当前目录和所有子目录大小,最后一行会显示当前目录的总大小,不包括隐藏文件
du -ach *
du -h –max-depth=0 *
# 指定文件夹显示层次深度
du -h --max-depth=0
/*********************************系统信息和性能查看***************************************/
# 查看系统的详细信息
lsb_release -a
# 查看内核/OS/CPU信息
uname -a 
# 查看内核版本
uname -r
# 查看处理器架构
uname -m
# 查看处理器架构
arch
# 查看主机名称
hostname
# 显示当前登录系统的用户
who
# 显示登陆时的用户名
who am i
# 显示当前用户名
whoami
# 查看 linux 版本信息
cat /proc/version
# 查看 CPU 信息
cat /proc/cpuinfo
# 查看中断
cat /proc/interrupts
# 查看系统负载
cat /proc/loadavg
# 查看系统运行时间、用户数、负载
uptime
# 查看系统的环境便令
env
# 查看系统PCI设备信息
lspci -tv
# 查看已加载的系统模块
lsmod
# 查看内存总量
grep MemTotal /proc/meminfo
# 查看空闲内存量
grep MemFree /proc/meminfo
# 查看内存用量和交换区用量
free -m
# 显示系统时间
date
# 显示2021日历表
cal 2021
# 动态显示cpu/内存/进程情况
top
# 每1秒采一次系统状态,采20次
vmstat 1 20 
# 查看io读写/cpu使用情况
iostat
# 查看 cpu 使用情况(1秒1次,共10次)
sar -u 1 10
# 查询磁盘性能
sar -d 1 10

# 找出占用内存资源最多的前 10 个进程
ps -auxf | sort -nr -k 4 | head -10
# 找出占用 CPU 资源最多的前 10 个进程
ps -auxf | sort -nr -k 3 | head -10
# 查看 cpu 内存占用情况
ps -eo pid,ppid,cmd,%cpu,%mem --sort=-%cpu | head

 8、C语言的编译过程详解​​​​​​​

  • 预处理器执行删除注释、宏扩展、文件包含。这些命令在编译过程的第一步执行。
  • 编译器可以提高程序的性能,并将中间文件转换为汇编文件。
  • 汇编程序有助于将汇编文件转换为包含机器代码的对象文件。
  • 链接器用于将库文件与对象文件链接。这是编译中生成可执行文件的最后一步。
发布评论

评论列表(0)

  1. 暂无评论