javascript练手-简单日历实现

样式表:

<style>
.cld-cur{
color:#6ac13c;
border:1px solid #6ac13c;
background:#e9f8df;
}
</style>

网页布局:

<div id=calendar></div>

JavaScript代码

//判断闰年
function runNian(_year) {
    if(_year%400 === 0 || (_year%4 === 0 && _year%100 !== 0) ) {
        return true;
    }
    else { return false; }
}
//判断某年某月的1号是星期几
function getFirstDay(_year,_month) {
    var allDay = 0, y = _year-1, i = 1;
    allDay = y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400) + 1;
    for ( ; i<_month; i++) {
        switch (i) {
            case 1: allDay += 31; break;
            case 2: 
                if(runNian(_year)) { allDay += 29; }
                else { allDay += 28; }
                break;
            case 3: allDay += 31; break;
            case 4: allDay += 30; break;
            case 5: allDay += 31; break;
            case 6: allDay += 30; break;
            case 7: allDay += 31; break;
            case 8: allDay += 31; break;
            case 9: allDay += 30; break;
            case 10: allDay += 31; break;
            case 11: allDay += 30; break;
            case 12: allDay += 31; break;
        }
    }
    return allDay%7;
}
//显示日历
function showCalendar(_year,_month,_day,firstDay) {
    var i = 0,
        monthDay = 0,
        showStr = "",
        _classname = "",
        today = new Date();
        //月份的天数
    switch(_month) {
        case 1: monthDay = 31; break;
        case 2:
            if(runNian(_year)) { monthDay = 29; }
            else { monthDay = 28; }
            break;
        case 3: monthDay = 31; break;
        case 4: monthDay = 30; break;
        case 5: monthDay = 31; break;
        case 6: monthDay = 30; break;
        case 7: monthDay = 31; break;
        case 8: monthDay = 31; break;
        case 9: monthDay = 30; break;
        case 10: monthDay = 31; break;
        case 11: monthDay = 30; break;
        case 12: monthDay = 31; break;
    }

    //输出日历表格,这部分因结构而异
    showStr = "<table class='cld-w'><thead>";
    //日历头部
    showStr += "<tr><th colspan='7'><div class='cld-hd'><span class='cld-pre'>&lt;</span><em id='showDate' value='" + _year + "-" + _month + "-" + _day + "'>" + _year + "年" + _month + "月" + _day + "日" + "</em><span class='cld-next'>&gt;</span></div></th></tr>";
    //日历星期
    showStr += "<tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr>";
    showStr += "</thead><tbody><tr>";
    //当月第一天前的空格
    for (i=1; i<=firstDay; i++) {
        showStr += "<td></td>";
    }
    //显示当前月的天数
    for (i=1; i<=monthDay; i++) {
        //当日的日期
        if(_year === today.getFullYear() && _month === today.getMonth()+1 && i === today.getDate()) {
            _classname = "cld-cur"; 
        } 
        //当日之前的日期(这个判断是因为我有工作需求,就是要求之前的日期不能点击)
        else if(_year < today.getFullYear() || (_year === today.getFullYear() && _month <= today.getMonth()) || (_year === today.getFullYear() && _month === today.getMonth()+1 && i < today.getDate()) ) {
            _classname = "cld-old";
        }
        //其他普通的日期
        else { _classname = "cld-day"; }
        //其他大于当月的月份的相同日期(为了让点击下一月的时候,相同的日期增加cld-cur类)
        if(_day === i && (_year > today.getFullYear() || _month > today.getMonth()+1)) { _classname = "cld-cur"; }
        //把日期存在对应的value       
        showStr += "<td class=" + _classname + " value='" + _year + "-" + _month + "-" + i + "'>" + i + "</td>";

        firstDay = (firstDay+1)%7;
        if(firstDay === 0 && i !== monthDay) {
            showStr += "</tr><tr>";
        } 
    }
    
    //剩余的空格
    if(firstDay!==0) {
        for (i=firstDay; i<7; i++) {
            showStr += "<td></td>";
        }
    }
        
    showStr +="</tr></tbody></table>";
    //插入calendar的页面结构里
    calendar.innerHTML = showStr;
}
//显示年月日
function showDate(_year,_month,_day) {
    var date = "", firstDay = getFirstDay(_year,_month,_day);
    if(_day !== 0) {
        date = _year + "年" + _month + "月" +_day + "日";
    }
    else { date = "No Choose."; }
    document.getElementById("showDate").innerHTML = date; //日历头部显示
    showCalendar(_year,_month,_day,firstDay);         //调用日历显示函数
}
//上一月
function preMonth(_year,_month,_day) {
    if(_month == 1) { showDate(_year - 1,12,_day); }
    else { showDate(_year,_month - 1,_day); }
}
//下一月
function nextMonth(_year,_month,_day) {
    if(_month == 12) { showDate(_year + 1,1,_day); }
    else { showDate(_year,_month + 1,_day); }
}
//初始化
var calendar = document.createElement('div');
calendar.setAttribute('id','showCld');
document.getElementById("calendar").appendChild(calendar); //增加到你的calendar里

//获取当天的年月日    
var today = new Date();
var _year = today.getFullYear(),
    _month = today.getMonth() + 1,
    _day = today.getDate();
var firstDay = getFirstDay(_year,_month);

//显示日历
showCalendar(_year,_month,_day,firstDay);


//日历点击的事件委托(可以查查js冒泡的应用)
calendar.onclick = function(e) {
    var e = e || window.event;
    var target = e.srcElement || e.target;
//把日历的头部的年月日分割成数组,这里保存在其value属性上
    dayArr = document.getElementById('showDate').getAttribute('value').split('-');
    if (target) {
        //如果是可点击的日期
        if ( target.className === "cld-day" || target.className === "cld-cur" ) {
            dateArr = target.getAttribute('value').split('-');
            //减0是把字符串转化成数值类型,以下一样            
            showDate(dateArr[0]-0,dateArr[1]-0,dateArr[2]-0);
            calendar.className = "";
        } 
        //如果是上一月的点击
        else if ( target.className === "cld-pre" ) {
            preMonth(dayArr[0]-0,dayArr[1]-0,dayArr[2]-0);
        }
        //如果是下一月的点击
        else if ( target.className === "cld-next" ) {
            nextMonth(dayArr[0]-0,dayArr[1]-0,dayArr[2]-0);
        }
    }
};

参考自:https://www.cnblogs.com/xinghh/p/3499375.html

bash-规范-特别要注意的和其他语言的不同点

一、shell脚本特别注意点

su root  可以切换成root 用户

shell编程

变量赋值时,等号两侧不能有空格!!!


注意 expr 运算符间要有空格 expr a + b

 条件判断 : [ a>b ]      []条件框 前后都要有空格
  注意:$[] 这个 是获取表达式结果   []前后 不需要空格 

(())  出现在 运算式  循环式 中


while 循环后面 别忘记 打空格
while [ 条件判断式 ] do
程序
done


===================================

9.test或[]的使用,也不一定要有if

例如

#!/bin/bash

var1=20

var2=22


[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"

home=/home

[ -d $home ] || echo "$home directory does not exist"

 

注意:

&&:前一个操作失败,后一个就不再执行

||   : 前一个操作成功,后一个就不再执行
===================================

在实际使用时,下面两种写法都是正确的。
date    "+%Y_%m_%d_%H%M%S"
date     +%Y_%m_%d_%H%M%S




 ${ } 的一些特异功能:
${变量名} 和 $变量名   效果是一样的,只是为了显示好看点。

假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 .  及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 .  及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 .  及其右边的字符串:/dir1/dir2/dir3/my

 

mysql问题-启用ssl加密连接数据库时报错

本地网站连接本地mysql  ssl是支持的不会报错

jdbc.url=jdbc:mysql://localhost:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8&useSSL=true

本地网站连接别的主机的mysql时,出现报错:

jdbc.url=jdbc:mysql://112.112.112.112:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8&useSSL=true

The last packet successfully received from the server was 764 milliseconds ago.  The last packet sent successfully to the server was 757 milliseconds ago.] with root cause

sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)

mysql  useSSL=true 问题,因为安装 mysql的时候,它会在本机 导入本机mysql的证书,所以可以使用 ssl 连接本机mysql。但是当本机网站需要连接到别的主机时,本机没有对方的ssl证书,所以就报错了。

解决办法就是:去掉 &useSSL=true

jdbc.url=jdbc:mysql://112.112.112.112:3306/ssmcrud?useUnicode=true&characterEncoding=UTF-8

Tue Nov 06 15:51:39 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

redis安装配置-在centos上

一、redis安装

1、下载获得redis-3.0.4.tar.gz后将它放入我们的Linux目录/opt
2、/opt目录下,解压命令:tar -zxvf redis-3.0.4.tar.gz
3、解压完成后出现文件夹:redis-3.0.4,进入目录:cd redis-3.0.4
4、看到源码包中的 makefile ,直接控制台输入 make 命令编译源代码。
5、
报错1:找不到 gcc ,就直接yum安装 或者 用光盘安装,输入pwd 显示当前路径。
报错2:jomalloc/jomalloc.h 没有那个文件或目录,之前缺gcc编译报错留下残余文件造成的。make distclean 清除之前 make 失败生成的文件
6、编译成功后,输入 make install 安装命令。usr 目录是 程序安装目录 /usr/local/bin /etc 是配置文件目录。

二、编辑配置文件

1、找到redis的配置文件,编辑  成 damen=yes 【vim 进入行末尾 shift + 4 】
2、查找配置文件方法  –>    /etc/redis.conf

[root@superguy ~]# rpm -qa | grep -i redis
redis-3.2.12-1.el7.x86_64
[root@superguy ~]# rpm -ql redis-3.2.12-1.el7.x86_64
/etc/logrotate.d/redis
/etc/redis-sentinel.conf
/etc/redis.conf
/etc/systemd/system/redis-sentinel.service.d
/etc/systemd/system/redis-sentinel.service.d/limit.conf
/etc/systemd/system/redis.service.d
/etc/systemd/system/redis.service.d/limit.conf
/usr/bin/redis-benchmark
/usr/bin/redis-check-aof
/usr/bin/redis-check-rdb
/usr/bin/redis-cli
/usr/bin/redis-sentinel
/usr/bin/redis-server
/usr/lib/systemd/system/redis-sentinel.service
/usr/lib/systemd/system/redis.service
/usr/libexec/redis-shutdown
/usr/share/doc/redis-3.2.12
/usr/share/doc/redis-3.2.12/00-RELEASENOTES
/usr/share/doc/redis-3.2.12/BUGS
/usr/share/doc/redis-3.2.12/CONTRIBUTING
/usr/share/doc/redis-3.2.12/MANIFESTO
/usr/share/doc/redis-3.2.12/README.md
/usr/share/licenses/redis-3.2.12
/usr/share/licenses/redis-3.2.12/COPYING
/usr/share/man/man1/redis-benchmark.1.gz
/usr/share/man/man1/redis-check-aof.1.gz
/usr/share/man/man1/redis-check-rdb.1.gz
/usr/share/man/man1/redis-cli.1.gz
/usr/share/man/man1/redis-sentinel.1.gz
/usr/share/man/man1/redis-server.1.gz
/usr/share/man/man5/redis-sentinel.conf.5.gz
/usr/share/man/man5/redis.conf.5.gz
/var/lib/redis
/var/log/redis
/var/run/redis
[root@superguy ~]# 

三、运行redis服务

redis-server /etc/redis.conf

四、使用redis客户端

[root@superguy ~]# redis-cli
127.0.0.1:6379> exit
[root@superguy ~]# 

 

http协议-html与http的区别

大白话:html协议是  保存信息的  文档协议,http协议 是 传输信息的 传输协议。

在Web服务中,信息一般是使用HTML格式以超文本和超媒体方式传送的,所使用的Internet协议是HTTP协议。

HTTP  意为超文本传输协议(全称是Hypertext Transfer Protocol)。是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示等(如文本先于图形显示)。这就是我们为什么在浏览器中看到的网址都是以“http://”开头的原因。

HTML  释为超文本标记语言(全称是Hypertext Markup Language),是用于WWW上文档的格式化语言。使用HTML语言可以创建文本文档,该文档可以从一个平台移植到另一个平台。HTML文件是带有嵌入代码(由标记表示)的ASCII文本文件,它用来表示格式化和超文本链接。HTML文件的内容通过一个页面展示出来,不同页面通过超链接关联起来。

 

tomcat安装配置-基础入门

一、centos 安装tomcat软件包

# yum 安装
yum install tomcat
# 查看安装目录
rpm -ql tomcat

#发现 /var/lib/tomcat/webapps/  这个目录下面是空的

也就是说:centos安装的tomcat,是没有欢迎界面的。一开始打开浏览器访问,找不到tomcat的欢迎页,其实是服务器默认就没有欢迎页。

二、centos 安装tomcat源码包

Installing Apache Tomcat 9

We’ll have to create a system user and group before proceeding with the installation process of Tomcat so create a user and group named tomcat to run below-given command to do so:

groupadd tomcat useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat

The options used in the above command perform the following:

-s /bin/false will disable shell access -g tomcat will assign a new user to the group tomcat -d /opt/tomcat will define the home directory for the user

Downloading and Installing Apache Tomcat

First, go to the directory /opt and download Apache Tomcat server using wgetcommand from http://tomcat.apache.org as shown below:

cd /opt/

This will change your current directory to directory /opt/

If in any case you haven’t installed wget command on your system then first of all install it using this command:

yum install wgetwget http://www-eu.apache.org/dist/tomcat/tomcat-9/v9.0.0.M15/bin/apache-tomcat-9.0.0.M15.tar.gz

Now extract using tar command as below :

tar -xzvf apache-tomcat-9.0.0.M15.tar.gz

Move all the files that are in the apache-tomcat-9.0.0.M15 directory to the tomcatdirectory to do so run following command :

mv apache-tomcat-9.0.0.M15/* tomcat/

Now change the proper ownership using the following command:

chown -hR tomcat:tomcat tomcat

Testing Tomcat

We recommend you to run a short testing on Tomcat to make sure that there is no error and it is installed successfully so follow the below-given process.

Run below given command :

cd /opt/tomcat/bin/ ./startup.sh

Currently, Tomcat is using port number 8080 so check the open port using netstat command as shown:

netstat -plntu

You can check this using a web browser with http://yourserver_IP:8080 then you’ll see the homepage of Apache Tomcat Server but we recommend you to use browser later at final testing because we will run Tomcat with a systemd service file in the final configuration.

Now run following commands :

cd /opt/tomcat/bin/./shutdown.shchown -hR tomcat:tomcat /opt/tomcat/

Creating a systemd Service File

Now you’ll need to create a systemd service file to run Apache Tomcat as a tomcat user. Creation of a systemd service file is recommended for easy starting and stopping the service.

Run following command :

nano /etc/systemd/system/tomcat.service

Add the content below into nano text editor, you can simply copy/paste this into the file:

[Unit]
Description=Apache Tomcat 8 Servlet Container
After=syslog.target network.target[Service]
User=tomcat
Group=tomcat
Type=forking
Environment=CATALINA_PID=/opt/tomcat/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
Restart=on-failure

[Install] WantedBy=multi-user.target

Save and close the file then run the following commands to start the Tomcat service and enable Tomcat service to start on boot:

systemctl daemon-reload systemctl start tomcat systemctl enable tomcat

Once again check for the open port using netstat command shown below:

netstat -plntu

Now run the command below and make sure that service is active as shown below:

systemctl status tomcat

Configure Tomcat Users

Run following command to edit tomcat-users.xml file using any text editor here we are using nano :

cd /opt/tomcat/conf/ nano tomcat-users.xml

Create a new line under line 43 and add following content, again you can simply copy-paste this into file like you’ve done before:

<role rolename="manager-gui"/>
<user username="admin" password="password" roles="manager-gui,admin-gui"/>

Save the file and exit text editor.

Now you’ll have to edit context.xml file using following commands:

cd /opt/tomcat/webapps/manager/META-INF/nano context.xml

Now you’ll have to comment out line 19 and 20 as shown below:

   <Context antiResourceLocking="false" privileged="true" >
    <!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
    </Context>

Save the file and exit nano text editor .

Now once again edit the context.xml file but this time it is in host-manager directory so run below given commands :

cd /opt/tomcat/webapps/host-manager/META-INF/nano context.xml

Comment out again line 19 and 20.

  <Context antiResourceLocking="false" privileged="true" >
    <!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
    </Context>

Save the file and exit nano text editor .

Now you’ll have to restart the tomcat and to do so run following command:

systemctl restart tomcat

Configure Firewalld

If in any case you haven’t installed firewalld on your system then install it first using yum command as shown below:

yum install firewalld

You’ll have to start firewalld and add it to start at boot time, to do so run following command:

systemctl start firewalldsystemctl enable firewalld

Now you’ll have to use firewall-cmd command to add apache tomcat port number 8080 to the firewall so simply enter below-given command:

firewall-cmd --zone=public --permanent --add-port=8080/tcp

You’ll see a result as “success”.

Now reload the firewall service using the following command:

firewall-cmd --reload

We recommend you to check for all service available and port 8080 is open and there is no error, to do so run following command:

firewall-cmd --list-portsfirewall-cmd --list-services

 


参考:

How to Install Apache Tomcat 9 on CentOS 7

网络原理-计算机网络详解-各类包长度及抓包分析

大白话:局域网 mtu 1500;Internet  mtu 576

对于UDP协议来说,整个包的最大长度为65535,其中包头长度是20字节(包括了伪首部:这个伪首部其实是属于ip头部的部分,里面有源ip地址和目标ip地址)所以UDP实际可用携带的最大数据是:65515字节长度。【udp协议里面:长度占了2个字节,16位。能够表示的范围是2^16-1 即 0-65515】

去除20字节的IP首部和8个字节的UDP首部,UDP数据报中用户数据的最长长度为65507字节。但是,大多数实现所提供的长度比这个最大值小。
我们将遇到两个限制因素。第一,应用程序可能会受到其程序接口的限制。socket API提供了一个可供应用程序调用的函数,以设置接收和发送缓存的长度。对于UDP socket,这个长度与应用程序可以读写的最大UDP数据报的长度直接相关。现在的大部分系统都默认提供了可读写大于8192字节的UDP数据报(使用这个默认值是因为8192是NFS读写用户数据数的默认值)。
第二个限制来自于TCP/IP的内核实现。可能存在一些实现特性(或差错),使IP数据报长度小于65535字节。
在SunOS 4.1.3下使用环回接口的最大IP数据报长度是32767字节。比它大的值都会发生差错。
但是从BSD/386到SunOS 4.1.3的情况下,Sun所能接收到最大IP数据报长度为32786字节(即32758字节用户数据)。
在Solaris 2.2下使用环回接口,最大可收发IP数据报长度为65535字节。
从Solaris 2.2到AIX 3.2.2,发送的最大IP数据报长度可以是65535字节。很显然,这个限制与源端和目的端的实现有关。
主机必须能够接收最短为576字节的IP数据报。在许多UDP应用程序的设计中,其应用程序数据被限制成512字节或更小,因此比这个限制值小。

由于IP能够发送或接收特定长度的数据报并不意味着接收应用程序可以读取该长度的数据。因此,UDP编程接口允许应用程序指定每次返回的最大字节数。如果接收到的数据报长度大于应用程序所能处理的长度,那么会发生什么情况呢?不幸的是,该问题的答案取决于编程接口和实现。
典型的Berkeley版socket API对数据报进行截断,并丢弃任何多余的数据。应用程序何时能够知道,则与版本有关(4.3BSD Reno及其后的版本可以通知应用程序数据报被截断)。
SVR4 下的socket API(包括Solaris 2.x) 并不截断数据报。超出部分数据在后面的读取中返回。它也不通知应用程序从单个UDP数据报中多次进行读取操作。TLI API不丢弃数据。相反,它返回一个标志表明可以获得更多的数据,而应用程序后面的读操作将返回数据报的其余部分。在讨论TCP时,我们发现它为应用程序提供连续的字节流,而没有任何信息边界。TCP以应用程序读操作时所要求的长度来传送数据,因此,在这个接口下,不会发生数据丢失。

对于TCP协议来说,整个包的最大长度是由最大传输大小(MSS,Maxitum Segment Size)决定,MSS就是TCP数据包每次能够传 输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值 ,确定为这次连接的最大MSS值。

IP层:
对于IP协议来说,IP包的大小由MTU决定(IP数据包长度就是MTU-28(包头长度)。 MTU值越大,封包就越大,理论上可增加传送速率,但 MTU值又不能设得太大,因为封包太大,传送时出现错误的机会大增。

UDP 包的大小就应该是 1500 – IP头(20) – UDP头(8) = 1472(BYTES)
TCP 包的大小就应该是 1500 – IP头(20) – TCP头(20) = 1460 (BYTES)

当我们发送的UDP数据大于1472的时候会怎样呢?这也就是说IP数据报大于1500字节,大于 MTU.这个时候发送方IP层就需要分片(fragmentation).把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报.将导致丢弃整个UDP数据报。
因此,在普通的局域网环境下,我建议将UDP的数据控制在1472字节以下为好.
进行Internet编程时则不同,因为Internet上的路由器可能会将MTU设为不同的值.如果我们假定MTU为1500来发送数据的,而途经的某个网络的MTU值小于1500字节,那么系统将会使用一系列的机制来调整MTU值,使数据报能够顺利到达目的地,这样就会做许多不必要的操作.

一般默认的设置,PPPoE连接的最高MTU值是1492, 而以太网 (Ethernet)的最高MTU值则是1500,而在Internet上,默认的MTU大小是576字节。

鉴于 Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.最好将UDP的数据长度控件在548字节 (576-8-20)以内.


许多服务器将最大的UDP数据包限制为512字节(如dns)

IPv4 最小重组缓冲区大小是576,IPv6在1500处。从这里减去标头大小。请参阅W. Richard Stevens的UNIX网络编程

576字节是最小的缓冲区大小,即每个实现必须能够重组至少那个大小的分组。有关详细信息,请参阅IETF RFC 1122

安全UDP的有效载荷最大是508字节。这是一个数据包大小为576,减去最多60个字节的IP标头和8个字节的UDP标头。任何这个规模或更小的UDP有效载荷都保证可以通过IP交付(尽管不能保证完整的交付)。由于其他原因,在路由的过程中可能会丢失。除了仅IPv6路由,最大有效载荷为1,212字节。正如其他人所提到的,在某些情况下可以添加额外的协议头。取而代之的是300-400字节的存储空间。

任何UDP数据包都可能被分割。这并不重要,因为丢失一个数据包与丢失一个未分组的数据包具有相同的效果:使用UDP,整个分组被丢弃的这种种情况是可能发生的。

一个典型 IPv4报头为20个字节,和UDP头部为8个字节。但是又包含IP选项,这可以将IP报头的大小增加到60个字节。另外,有时中间节点需要将数据报封装在另一个协议中,如IPsec(用于VPN等),以便将数据包路由到目的地。因此,如果你不知道MTU特定网络路径的话,最好为其他标题信息留下合理的存储空间,可能这些信息并不是你预期的。通常认为UDP的有效载荷是512字节,即使这样处理也不能为最大尺寸的IP标头留下足够的存储空间。


抓包实测 – UDP/TCP数据包分析

经测试,局域网环境下,UDP包大小为1024*8,速度达到2M/s,丢包情况理想.
外网环境下,UDP包大小为548,速度理想,丢包情况理想.

本文旨在分析使用抓包工具抓取到的数据包。

(一)抓包工具

tcpdump:linux下的抓包利器

wireshark:带GUI的抓包工具,其前身是大名鼎鼎的Ethereal

(二)抓包

这里只简述tcpdump的一般用法,详细资料可参考tcpdump使用手册。

wireshark带有GUI,操作比较简单,暂不赘述。

tcpdump -i eth1 tcp -Xnlps0 port 16815 src host 192.168.0.0 and dst net 192.168.0.1
tcpdump -i eth1 -Xnlps0 dst net 172.23.9.155 and port 37861
tcpdump -i eth1 -Xnlps0 dst net 172.23.9.155 and port 37861 -w yourfile

PS:可以使用wireshark分析tcpdump抓取的数据包

tcpdump -w output.cap -s0

wireshark可以在图形界面下分析应用层按照TCP/IP四层结构显显示数据包,
第一行是数据链路层的信息,
第二行是网络层信息(IP协议),
第三行是传输层信息(TCP协议),
第四行是应用层信息(HTTP协议),
可以展开每一行用来观察具体的内容

(三)TCP/UDP数据包结构

抓包分析,装载udp的ip包和装载tcp的ip包,查明ip包首部都没有添加可选项。

PS:后面的数据分析都是带IP头的数据包。

(四)UDP数据包分析

0x0000:  4500 0054 9a08 4000 4011 b88d ac17 8639  E..T..@.@……9
0x0010:  ac17 099b e317 93e5 0040 e854 0000 0065  ………@.T…e
0x0020:  012d d668 0000 0000 0000 0000 0000 0038  .-.h………..8
0x0030:  3030 3030 3030 3030 3030 3030 3030 3030  0000000000000000
0x0040:  0000 0001 0000 0000 0000 0000 0000 0000  …………….
0x0050:  0000 0000

4500        [4: ipv4], [5: header length, *4 ==> 20], [00: Type of Service(TOS)]
0054        [total length: 0x54(84), ip header(20) + udp header(8) + packlen(56) -> 84]
9a08        id
4000        3bits(ip flags), 40 -> do not flag, 5bits: fragment offset
4011        [ttl: 40], [protocol: 0x11(17) ==> udp]
b88d        checksum
ac17 8639   source ip: 172.23.134.57

ac17 099b   dest ip: 172.23.9.155
e317        sourc port: 58135 (ntohs(0xe317)) [exchange]
93e5        dest port: 37861
0040        length: 64
e854        checksum

0000 0065…  data

 

(五)TCP数据包分析

0x0000:  4500 0073 cdc5 4000 4006 6285 ca6e 4099  E..s..@[email protected]@.
0x0010:  7474 8abe 1f40 070a 6d88 acdd 23d7 a448  tt…@..m…#..H
0x0020:  5018 16d0 0aa0 0000 0100 8000 0000 0047  P…………..G
0x0030:  3004 8000 0016 8117 04d7 cd00 000b 0006  0……………
0x0040:  4500 1a4d 6bd0 180a 909a bc08 883d edea  E..Mk……..=..
0x0050:  091f                                     ..

4500        [4: ipv4] [5: ip header length, 4*5 -> 20] [00 TOS]
0073        [total length: 0x73(115), ip header(20) + tcp header(20) + packlen(75) -> 115]
cdc5        id(ignore it)
4000        3bits(ip flags), 40 -> do not flag, 5bits: fragment offset
4006        [40 ttl] [06 protocol, 0x06 -> tcp]
6285        checksum
ca6e 4099   source ip: 202.110.64.153

7474 8abe   dest ip: 116.116.138.190
1f40        sourc port: 8000 (ntohs(0x401f)) [exchange]
070a        dest port: 1802
6d88 acdd   32 bits sequence number(ignore)
23d7 a448   32 bits ack(ignore)

5018        [5: tcp header length 5 * 4 -> 20] [018: 0000 00/01 1000: reserved 6bit -> ACK+PUSH] (URG|ACK|PSH|RST|SYN|FIN)
16d0        16bit window size: 5840
0aa0        16bit tcp checksum(ignore)
0000        16bit urgent pointer
———————

抓包工具:科来网络分析系统

https://blog.csdn.net/cybertan/article/details/5961049

参考:

https://blog.csdn.net/wirror800/article/details/6977421

https://blog.csdn.net/buptzwp/article/details/5055487

网络原理-计算机网络详解-网线传递数字信号的原理

家用的网线:传递的数字信号,原理是:

(1)和电线传输电的原理一样,只不过网线上传输的就是脉冲电信号,而且遵守一定的电器规则。
(2)计算机上的数据都是用0和1来保存的,所以在网线上传输时就要用一个电压表示数据0,用另一个电压表示数据1。
(3)网线上传输的是数字信号。
(4)网线在传输数据就是传输电信号,就会有电流通过,那么就会产生电磁场,几根线之间的电磁场就会互相干扰,会影响电压,使得数据失真,所以把绞在一起就可以有效的抵消掉这种线之间的互相电磁干扰。

总结来说:网线就是传递的脉冲电信号,在一个脉冲中,即有电压变化,又有电流变化。
网线传输信号是数字信号,方波,相当脆弱,容易受到周边磁场和自身的干挠。所以双绞的原理就是为了尽可能的消除其干挠。
我们日常使用最多的网线就是双绞线,但网线不能过长,电脑能识别的语言就只有0和1,网络得传输信号就是0和1。这些信号通过网线的时候变成了电流,而网线的电流强度是-15v和+15v之间,电流通过网线传输的时候会有电阻。所以,根据高压输电原理,线路越长,就要用越大的电压等级来输电。如果网线过长,但是这么低的电压,就会导致信号减弱,直至丢失。因此网线不宜过长,一般来说,网线超过一百米,另一头就接收不到信号了。

rj45网线中,单方向传输信号都是一对导线,里面用的是差分信号,传递给对方的是电压变化 信号。【双绞线 可以 屏蔽 外界的 电磁干扰,抗干扰强】

如果差分信号电路中的源和接收器阻抗相等,则外部电磁干扰往往会同样影响两个导体。由于接收电路仅检测导线之间的差异,因此与具有未配对参考(接地)的一个导体相比,该技术抵抗电磁噪声。该技术适用于模拟信号,如平衡音频和数字信号,如RS-422,RS-485,双绞线以太网,PCI Express,DisplayPort,HDMI和USB。【来自维基百科】

数字电路:从 单端信号 发展到 差分信号

单端信号与同轴电缆一起使用,其中一根导线完全屏蔽另一根导线与环境。所有屏幕(或屏蔽)都组合成一块材料,形成一个共同的地面。差分信号与平衡的导体对一起使用。对于短电缆和低频,这两种方法是等效的,因此具有公共接地的廉价单端电路可以与廉价电缆一起使用。

单端信号
早期的数字总线大部分使用单端信号做信号传输,如TTL/CMOS信号都是单端信号。所谓单端信号,是指用一根信号线的高低电平的变化来进行0、1信息的传输,这个电平的高低变化是相对于其公共的参考地平面的。单端信号由于结构简单,可以用简单的晶体管电路实现,而且集成度高、功耗低,因此在数字电路中得到最广泛的应用。

大白话:单端信号 用一根线 接地,另一根 传递 电压 高低变化,当然也是 单方向 传输啦。

======================================================

差分传输是一种信号传输的技术,区别于传统的一根信号线一根地线的做法,差分传输在这两根线上都传输信号,这两个信号的振幅相同,相位相反。在这两根线上的传输的信号就是差分信号。信号接收端比较这两个电压的差值来判断发送端发送的逻辑状态。在电路板上,差分走线必须是等长、等宽、紧密靠近、且在同一层面的两根线。

差分信号是用一个数值来表示两个物理量之间的差异。差分信号又称差模信号,是相对共模信号而言的。


网线传输原理

一般情况下,网络从上至下分为五层:应用层、传输层、网络层、数据链路层、物理层。每一层都有各自需要遵守的规则,称之为“协议”。TCP/IP协议就是一组最常用的网络协议。
网线在网络中属于物理层,计算机中所需要传输的数据根据这些协议被分解成一个一个数据包(其中包括本地机和目的机的地址)后,按照一定的原则最后通过网线传输给目的机。通俗讲,和我们去寄信的道理一样,先写好信的内容(计算机上的数据)、装信封然后在封面上写地址(打包成数据包,里面包含本地机和目的机的地址)、寄出(传输),那么网线就相当于你的地址和你要寄到的地址之间的路。
(1)如上所述,和电线传输电的原理一样,只不过网线上传输的就是脉冲电信号,而且遵守一定的电气规则。
(2)计算机上的数据都是用0和1来保存的,所以在网线上传输时就要用一个电压表示数据0,用另一个电压表示数据1。
(3)网线上传输的是数字信号
(4)网线在传输数据就是传输电信号,就会有电流通过,那么就会产生电磁场,几根线之间的电磁场就会互相干扰,会影响电压,使得数据失真,所以把绞在一起就可以有效的抵消掉这种线之间的互相电磁干扰。
网线传输信号是数字信号,方波,相当脆弱,容易受到周边磁场和自身的干挠。所以双绞的原理就是为了尽可能的消除其干挠。
明白了网线所接的水晶头:rj45接口原理就自然明白了网线的原理:
RJ-45各脚功能(10BaseT/100BaseTX):
1、传输数据正极   Tx+
2、传输数据负极   Tx-
3、接收数据正极   Rx+
4、备用(当1236出现故障时,自动切入使用状态)
5、备用(当1236出现故障时,自动切入使用状态)
6、接收数据负极   Rx-
7、备用(当1236出现故障时,自动切入使用状态)
8、备用(当1236出现故障时,自动切入使用状态)
网线中传输的是数字信号,网卡工作在物理层,是将数据根据OSI的七层协议,从要传输的数据一级一级的转换成帧数据,用电信号的方式传输出去,接收方依同样的原理,转换成对方的原始数据。
RJ-45的接头实现了网卡和网线的连接。它里面有8个铜片可以和网线中的4对双绞(8根)线对应连接。其中100M的网络中1、2是传送数据的,3、6是接收数据的。1、2之间是一对差分信号,也就是说它们的波形一样,但是相位相差180度,同一时刻的电压幅度互为正负。这样的信号可以传递的更远,抗干扰能力强。同样的,3、6也一样是差分信号。
网线中的8根线,每两根扭在一起成为一对。我们制作网线的时候,一定要注意要让1、2在其中的一对,3、6在一对。否则长距离情况下使用这根网线的时候会导致无法连接或连接很不稳定。
首先说一下差分方式传输。所谓差分方式传输,就是发送端在两条信号线上传输幅值相等相位相反的电信号,接收端对接受的两条线信号作减法运算,这样获得幅值翻倍的信号。其抗干扰的原理是:假如两条信号线都受到了同样(同相、等幅)的干扰信号,由于接受端对接受的两条线的信号作减法运算,因此干扰信号被 基本抵消,那么怎样才能保证两条信号线受到的干扰信号尽量是同相、等幅的呢?办法之一那就要将两根线扭在一起,按照电磁学的原理分析出:可以近似地认为两条信号线受到的干扰信号是同相、等幅的。 两条线交在一起后,既会抵抗外界的干扰也会防止自己去干扰别人。一般常用的就是双绞线。
大多数局域网使用非屏蔽双绞线(UTP—Unshielded Twisted Pair)作为布线的传输介质来组网,网线由一定距离长的双绞线与RJ45头组成。双绞线由8根不同颜色的线分成4对绞合在一起,成队扭绞的作用是尽可能减少电磁辐射与外部电磁干扰的影响,双绞线可按其是否外加金属网丝套的屏蔽层而区分为屏蔽双绞线(STP)和非屏蔽双绞线(UTP)。在EIA/TIA-568A标准中,将双绞线按电气特性区分有:三类、四类、五类线。网络中最常用的是三类线和五类线,超五类,目前已有六类以上线。第三类双绞线在LAN中常用作为10Mbps以太网的数据与话音传输,符合IEEE802.3 10Base-T的标准。第五类双绞线目前占有最大的LAN市场,最高速率可达100Mbps,符合IEEE802.3 100Base-T的标准。做好的网线要将RJ45水晶头接入网卡或HUB等网络设备的RJ45插座内。相应地RJ45插头座也区分为三类或五类电气特性。RJ45水晶头由金属片和塑料构成,特别需要注意的是引脚序号,当金属片面对我们的时候从左至右引脚序号是1-8, 这序号做网络联线时非常重要,不能搞错。双绞线的最大传输距离为100米。 EIA/TIA的布线标准中规定了两种双绞线的线序568B与568A。
标准568B:橙白–1,橙–2,绿白–3,蓝–4,蓝白–5,绿–6,棕白–7,棕–8
标准568A:绿白–1,绿–2,橙白–3,蓝–4,蓝白–5,橙–6,棕白–7,棕–8
568A和568B两者有何区别呢?后者是前者的升级和完善,但是后者还处于草案阶段,包含永久链路的定义和六类标准。另外在综合布线的施工中,有着568A和568B两种不同的打线方式,两种方式对性能没有影响,但是必须强调的是在一个工程中只能使用一种打线方式。
至于5类和超5类的不同主要是应用的不同。5类系统在使用过程中只是使用其中的两对线缆,采用的是半双工,而超5类为了满足千兆以太网的应用,采用四对全双工传输。因而远端串扰(FEXT),回波损耗(RL)、综合近端串扰(PSNEXT)、综合ACR和传输延迟也成为必须考虑的参数。所以超5类比5类有着更高的性能要求。6类和5类实质的区别在于它们的带宽不同,5类只有100MHz,六类是250MHz。它们支持的应用也因为性能的不同而不同,6类支持更高级别的应用。在性能上6类也比5类有更高的要求,为了提高性能,在结构上6类比5类也要复杂一些RJ45接头的8个接脚的识别方法是,铜接点朝自己,头朝右,从上往下数,分别是1、2、3、4、5、6、7、8。
在整个网络布线中应用一种布线方式,但两端都有RJ-45 的网络联线无论是采用568A,还是568B, 在网络中都是通用的。规定双工方式下本地的1、2两脚为信号发送端,3、6两脚为信号接收端,所以讲,这两对信号必须分别使用一对双绞线进行信号传输。在做线时要特别注意。现在100M网一般使用568B方式,1、2两脚使用橙色的那对线,其中白橙线接1脚;3、6两脚使用绿色的那对线,其中白绿线接3脚,绿线接6脚,剩下的两对线在10M、100M快速以太网中一般不用,通常将两个接头的4、5和7、8两接头分别使用 一对双绞线直连,4、5用蓝色的那对线,4为蓝色,5为白蓝色;7、8用棕色的那对线,7为白棕色、8为棕色。如果网线两头都按一种方式这么做的话就叫做直连缆方式或直通线方式。
如果网线的两头不按一种方式,一头是568B,另一头是568A,那么这种做法叫交*缆,其实就是只须将其中一个 头在568B的基础上1、2和3、6对调一下就行。不同的做法用在不同的环境,后面会讨论。
很多人以为做直连缆时将线排成,这是错误的。这既不是568A也不是568B。这种做法3、6信号线未绞在一起,失去了双绞线的屏蔽作用。虽然在传输距离近时能正常使用不容易被发现,当传输距离远时会出现丢包,或者导致局域网速度慢,很多人会怀疑网卡质量和网线质量,往往不会想到是线做的有问题。
当网线作为局域网线路时,电压不超过3伏
作为电话线路时,电话在待机状态(即没拿起来时)供电电压为-48V(反向电位) 当电话被打通需要震铃时,供电电压为+48V(正向电位)并且叠加24V 25HZ交流,使其成为72V交流25HZ震荡信号。这样就会震铃了。 当拿起电话后(无论是对方打来还是你自己拿起)电压从-48V下降并转换为+8—+18V(这个由你线路距离局端设备远近而不同) 电话是以恒流方式供电。也就是,电流一定,功率越大,电压越高。并且除了震铃之外,其他的全部为直流送电,包括脉冲直流 并且,如果是之后新装的线路中,大多地区已经使用数字模拟混合接入,即若你的电话为06年之后购买并符合标准的,则为数字信号,用载波模式装载到线路中传输,若为之前的或者局端设备还没有更新,那么则是模拟信号,用电流高低震荡的方式传送。
作为电口出来的网线时,网线供电器的输出电压一般是24V或者48V,INTEL的设备就是24V,CISCO和神脑的设备就是48V,这样经过100米的网线传输后,电压还是足够的,而这些网络设备内部还有一个转换电路,将这些可能高于要求的电压降到正常范围内。
数字信号从Internet上下载下来,通过ISP接入你所在区域的交换机,通过D/A变换变成模拟信号,经过4线至2线的变换后,传到你的调制解调器,再经过一次A/D变换,还原成计算机可接受的数字信号。


无线网快还是插网线快?

同一个路由器下,绝大多数情况下,网线比无线网快。

不敢说绝了,因为上网情况不太,实际上网速度也有略有影响。

正常来说,插网线的网络损耗比较少,在局域网中常见的网线主要有双绞线、同轴电缆、光缆三种。 双绞线,是由许多对线组成的数据传输线。它的特点就是价格便宜,所以被广泛应用,如我们常见的电话线等。它是用来和RJ45水晶头相连的。

我们日常使用最多的网线就是双绞线,但网线不能过长,电脑能识别的语言就只有0和1,网络得传输信号就是0和1。这些信号通过网线的时候变成了电流,而网线的电流强度是-15v和+15v之间,电流通过网线传输的时候会有电阻。所以,根据高压输电原理,线路越长,就要用越大的电压等级来输电。如果网线过长,但是这么低的电压,就会导致信号减弱,直至丢失。因此网线不宜过长,一般来说,网线超过一百米,另一头就接收不到信号了。

而我们正常使用网线的一般只有几米,损耗是非常少的。

无线网络损耗比较大的原因比较多,如建筑物对网络的损耗,特别是建筑物中的承重墙对网络损耗会比较大。由于wifi信号有特定的信道,这些信道就如同告诉公路,如果附件多个路由器发射出来的wifi都在一个信道传输,也会导致网络变慢。

在家中使用PC用网线连接路由器比wifi连接网速还是要更好的。

其实路由器端是没有太大问题的,虽然标称300m的2.4gWIFI有大半虚标,但实际值还是比有线的100m快的。但是问题就在于你的笔记本电脑,手机和便宜的无线网卡速率都是54m!

这就产生瓶颈制约,路由器标称给你6碗饭,实际给你3碗饭,但你只吃得下1碗!

现在的电脑配置也有问题,机械硬盘标称和测速都显示130m/s以上,但实际上使用起来持续速度只有40m/s左右,因为机械盘早期写入的是缓存,缓存再写入碟片,但测速软件测的是写入缓存的速度而非写入盘片的速度。测速450m/s的ssd真实持续写入速度其实也就95m/s。

40m/s换算为速率就是480mbps,所以,你的电脑根本上来说就只能用480m的网速,什么千兆网卡都是噱头,因为根本没这能力跑!ssd会好一些,但是也只能勉强跑满千兆!

千兆有线的设备成本比较低,而你如果想用千兆WIFI,光路由器和接收器的投资就不低于2500元,而且还要专用,不能通用。

总之,这是这个时代的科技局限,你手机无线接收模块就只54mbps,速度上限就7m/s,5g的会好点,但也只能到15m/s左右的上限。你用再好的路由器都没用!

包括现在的小米用了黑科技双WIFI,但也只能增加WIFI信号强度而不能增加速度。

总结:现在普遍使用百兆有线的情况下,有线是要比无线快的,想要无线比有线快,要等高标准的WIFI接收模块普及了才行。

首先有两个概念。

我们常说的网速:“XX兆光纤”,对应到一个专业词汇叫“网络带宽”。指的是单位时间的传输效率,一般运营商给的这个值是理论最大值。实际情况往往到不了这个大小。一个比较好的类比是,带宽越大,就好像一个高速公路修得越宽,车道越多。
第二个生活化的词汇是“网好卡”,对应到专业词汇叫“网络延迟”,延迟有很多部分组成,也受很多因素影响。但最终用户感受到的是一个网络请求从开始到收到结果的时间间隔。可以类比为高速公路上的车跑的快慢。
所以上面我们可以看出,网络“卡不卡”是有两个指标衡量的,在不同的使用场景下时有不同的判断依据的。

下面举例两个场景。

用手机或者电脑打游戏的时候,往往游戏需要发生的网络请求很频繁但是数据量并不大。这个时候我们需要网络延迟很低,但是并不需要有很大的网络带宽。所以我们经常能看到,隔壁老王家10兆的网络比你家100兆的网络打游戏更加顺畅。类比到高速公路上,就是相当于有很多赛车一辆接一辆在两个地方往返,这个时候路面是不是很宽其实大家不太在乎,在乎的是“路好不好走”,也就是延迟是不是很低。
在线观看视频或者下载资料的时候,电脑会从网络上不断的下载信息,放到本地,供我们观看。这些信息相对是非常大的,这时候我们就需要很宽的公路去运送这些资源到本地来,路面稍微难走一点也没有关系。这个场景下我们需求的是大的带宽,对延时没有太高的要求。
说完了啥叫网络卡,以及不同场景下的不同需求,我们来看一看有线连接和无线连接的区别。(这只讨论家用路由器和日常使用设备之间的连接形式)。

顾名思义有线连接就是信息由路由器到主机之间用光缆连接以传输信息,信息传输过程是先将电信号转化为光信号在光缆中传输,然后另一端接收到结果后再由光信号转换为电信号。完成传输。在光缆内传输的好处是,受到外界干扰很小,而且本身带宽也足够大(现在市面上光缆的传输带宽都是远大于我们家用网络带宽的)。
而无线连接则是,路由器和主机之间,将电信号通过调制解调器转换,以电磁波为载体在端与端之间传输。优势在于方便。但是劣势也很明显,例如电磁波比较容易受到干扰,传输带宽和发射功率有关,以及多个无线网信道之间相互干扰等等
所以从理论上看,相应其他条件下,有线连接会比无线连接在网络带宽和网络延时上都更具有优势一些。

至于其他答案中提到的2.4G和5G标准相关的内容,其实都是这个标准下用了全新不易冲突的电磁波频段以及新的硬件标准使得相同功率下传输效率更高。但是现阶段而言,不太可能突破有线连接的速度。

再顺便提及一下某些朋友可能的疑虑,电脑接有线,手机用无线,体验上手机比电脑更加流畅。这个问题其实很简单,做对比要控制好变量,很可能体验上的差别是由其他东西导致的。比如运营商在晚高峰的时候承诺的带宽达不到,或者晚高峰网络拥塞整体延时都增加了等等。

你们见过数据中心用无线传业务数据吗?!

1.无线工作方式为半双工,类似于以前那种很老的hub(冲突检测,载波侦听,就是我在用的时候你就得等着我把数据传完你再传)。

2.无线的吞吐看起来参数比千兆有线还高(1200Mbps甚至5300Mbps),但他的工作方式决定了它在多用户的环境下性能损失非常大,特别是多用户大吞吐的时候,抖动增大和速率下降都会非常利害,信号也容易受到干扰还不安全。

3.现在高端一点的无线路由器在硬件层面有mimo数据流的多入多出,链路聚合,专用无线处理芯片等技术,但其实性能提升也有限,原因还是看第一点他的工作原理决定的。软件层面会有一些专业的商业公司出的专用操作系统比如aruba,Cisco,huawei等,但也只是在稳定性,安全性和部署维护上进行了优化。

4.有线的路由器或者交换机会有专门的处理芯片来处理三层的路由数据和二层的交换数据,一般都能达到线速转发。比如48口的交换机背板宽带宽228Gbps,实际上只要用到96Gbps就足够让这48台终端同时上下行并发吞吐数据了,而且延时抖动和速率下降并不明显,如果是无线分分钟死给你看。但是呢即使是dlink tplink fast 腾达之流,瞎标参数,千兆有线也比大牌的千兆无线快和稳定,但不用说那种专业厂商的设备。

个人经验,高端点的ac无线路由器单纯的作为接入点30人左右的接入会有比较好的用户体验,尽管他可能支持128或者更高的接入,但能连接和可以用可是二码事。一分钱一分货,那种几十块的就不用说了,家庭3到5个人,要求不高,也能用。

所以,至少一段时间来看无线都只是作为接入层的扩展设备而存在,因为他不用布线方便啊

参考链接:

https://www.bilibili.com/read/cv1166002/

https://www.diangon.com/thread-17307-1-1.html

java安装配置-centos平台

在centos下,默认装的是openjdk的 jre版本。

可以使用java 但不能使用 javac

[root@superguy ~]# rpm -qa | grep jdk 
java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64
java-1.7.0-openjdk-headless-1.7.0.191-2.6.15.4.el7_5.x86_64
copy-jdk-configs-3.3-10.el7_5.noarch
java-1.7.0-openjdk-1.7.0.191-2.6.15.4.el7_5.x86_64
java-1.8.0-openjdk-headless-1.8.0.181-3.b13.el7_5.x86_64
[root@superguy ~]# java -version
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
[root@superguy ~]# javac
bash: javac: command not found...
Similar command is: 'java'
[root@superguy ~]# java
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)
where options include:
    -d32	  use a 32-bit data model if available
    -d64	  use a 64-bit data model if available
    -server	  to select the "server" VM
                  The default VM is server.

    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A : separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -D<name>=<value>
                  set a system property
    -verbose:[class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -version:<value>
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  require the specified version to run
    -showversion  print product version and continue
    -jre-restrict-search | -no-jre-restrict-search
                  Warning: this feature is deprecated and will be removed
                  in a future release.
                  include/exclude user private JREs in the version search
    -? -help      print this help message
    -X            print help on non-standard options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions with specified granularity
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions with specified granularity
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions
    -agentlib:<libname>[=<options>]
                  load native agent library <libname>, e.g. -agentlib:hprof
                  see also, -agentlib:jdwp=help and -agentlib:hprof=help
    -agentpath:<pathname>[=<options>]
                  load native agent library by full pathname
    -javaagent:<jarpath>[=<options>]
                  load Java programming language agent, see java.lang.instrument
    -splash:<imagepath>
                  show splash screen with specified image
See http://www.oracle.com/technetwork/java/javase/documentation/index.html for more details.
[root@superguy ~]#

后来查询发现需要装 openjdk 的devel 版本

[root@superguy ~]# yum list |grep jdk
copy-jdk-configs.noarch                  3.3-10.el7_5                   @updates
java-1.7.0-openjdk.x86_64                1:1.7.0.191-2.6.15.4.el7_5     @updates
java-1.7.0-openjdk-headless.x86_64       1:1.7.0.191-2.6.15.4.el7_5     @updates
java-1.8.0-openjdk.x86_64                1:1.8.0.191.b12-0.el7_5        @updates
java-1.8.0-openjdk-headless.x86_64       1:1.8.0.191.b12-0.el7_5        @updates
java-1.6.0-openjdk.x86_64                1:1.6.0.41-1.13.13.1.el7_3     base    
java-1.6.0-openjdk-demo.x86_64           1:1.6.0.41-1.13.13.1.el7_3     base    
java-1.6.0-openjdk-devel.x86_64          1:1.6.0.41-1.13.13.1.el7_3     base    
java-1.6.0-openjdk-javadoc.x86_64        1:1.6.0.41-1.13.13.1.el7_3     base    
java-1.6.0-openjdk-src.x86_64            1:1.6.0.41-1.13.13.1.el7_3     base    
java-1.7.0-openjdk-accessibility.x86_64  1:1.7.0.191-2.6.15.4.el7_5     updates 
java-1.7.0-openjdk-demo.x86_64           1:1.7.0.191-2.6.15.4.el7_5     updates 
java-1.7.0-openjdk-devel.x86_64          1:1.7.0.191-2.6.15.4.el7_5     updates 
java-1.7.0-openjdk-javadoc.noarch        1:1.7.0.191-2.6.15.4.el7_5     updates 
java-1.7.0-openjdk-src.x86_64            1:1.7.0.191-2.6.15.4.el7_5     updates 
java-1.8.0-openjdk.i686                  1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-accessibility.i686    1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-accessibility.x86_64  1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-accessibility-debug.i686
java-1.8.0-openjdk-accessibility-debug.x86_64
java-1.8.0-openjdk-debug.i686            1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-debug.x86_64          1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-demo.i686             1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-demo.x86_64           1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-demo-debug.i686       1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-demo-debug.x86_64     1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-devel.i686            1:1.8.0.191.b12-0.el7_5        updates 
java-1.8.0-openjdk-devel.x86_64          1:1.8.0.191.b12-0.el7_5        updates

先更新 openjdk的jre版本,然后下载最新的 openjdk的devel版本。这个版本可以运行 javac

yum install java-1.8.0-openjdk-devel


参考国外教程

一、Installing Java

Before installing Tomcat we will have to install Java Development Kit (JDK) on our system but it is recommended that you update the system and available packages before installing JDK. Run the following command to update system.

yum -y update

Now once the system is updated install JDK and to do so run following command:

yum -y install java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64

The above command will take some time to install JDK so you should wait until the installation process has finished.

When Java is installed check the java version with the following command:

java -version

You’ll see a result similar to this :

[root@ip-172-31-16-36 ~]# java -version
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-b15)
OpenJDK 64-Bit Server VM (build 25.111-b15, mixed mode)
[root@ip-172-31-16-36 ~]#

二、Java Home Environment

Before you configure Java Home Environment we recommend you to check where the Java directory is and to do so run following command:

sudo update-alternatives --config java

Now edit the environment file with any text editor here we are using nano editor but you can choose anyone you wish.

nano /etc/environment

Now add the Java Home Environment variable as shown below :

JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-1.b15.el7_2.x86_64/jre"

You can simply copy/paste this to your file.

After adding Java Home Environment save and exit from the editor.

Now we’ll have to edit the .bash_profile so run the command given below:

nano ~/.bash_profile

Now add the Home Environment variable as shown below:

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-1.b15.el7_2.x86_64/jre export PATH=$JAVA_HOME/bin:$PATH

Save file and exit from the editor.

We recommend you reload the .bash_profile, to do so run following command:

source ~/.bash_profile

We recommend you make sure there is no error in configuring Home Environment variable and also check the Java Home environment variable :

echo $JAVA_HOME

You will see output similar to this containing the path to java directory :

[root@ip-172-31-16-36 ~]# nano ~/.bash_profile
[root@ip-172-31-16-36 ~]# source ~/.bash_profile
[root@ip-172-31-16-36 ~]# echo $JAVA_HOME
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-1.b15.el7_2.x86_64/jre
[root@ip-172-31-16-36 ~]#