shell 工具箱 总结平时用到的一些shell函数 方便复用

回复

问答jintianfree 回复了问题 • 1 人关注 • 6 个回复 • 29 次浏览 • 2019-10-25 13:38 • 来自相关话题

nginx access log 很多转义字符串 类似\x22text\x22:\x22\xE7\x83\x98\x\xAE\x22 怎么转回来

问答jintianfree 发表了文章 • 0 个评论 • 71 次浏览 • 2019-10-25 12:03 • 来自相关话题

很简单 使用python str的decode函数,注意参数使用'string-escape'
python2测试OK



print (" {\x0A \x22campaign\x22: \x22c181518671956.820106\x22,\x0A \x22platform\x22:1,\x0A \x22price\x22:0,\x0A \x22materials\x22:[{\x22file_type\x22:1,\x22img_url\x22:\x22http://staging.trylemonade.com ... 1.jpg\x22}],\x0A \x22content\x22: \x22\xE6\xB8\xAC\xE8\xA9\xA6submit\x22,\x0A \x22tags\x22: [{\x22tag_type\x22:\x22#\x22,\x22text\x22:\x22\xE7\x83\x98\xE7\x88\x90\xE5\x9C\xB0\xE5\x8D\x97\xE5\xB1\xB1\xE7\xA6\x8F\xE5\xBE\xB7\xE5\xAE\xAE\x22},{\x22tag_type\x22:\x22#\x22,\x22text\x22:\x22\xE6\x8B\x9C\xE6\x8B\x9C\xE6\x84\x9B\xE7\x94\xA8\xE9\x96\x8B\xE9\x81\x8B\xE6\x8B\x9B\xE8\xB2\xA1\xE5\x8C\x85\x22}],\x0A \x22influencer\x22:\x0A {\x22third_party_token\x22:\x22EAAXNnbIx0GoBAJ0n6pJO3o0M5buUaEnXOfyMXryuQdqRUGHPSlhUNZCZAdWHABqntpWf2cXZCMWbdLYSLF0POA9uUrZCQAGIVxMl983P20n247BQerZBnUvwRkujZCGa6monlNVj9tW6hZAam5zQZA6VqcoQT8ugTOvd1fBM09GQsgZDZD\x22,\x22fan_count\x22:1264,\x22third_party_id\x22:\x221389525994710539\x22,\x22third_party_type\x22:1,\x22user_avatar\x22:\x22https://scontent.xx.fbcdn.net/ ... B2DD4\x22,\x22user_name\x22:\x22\xE6\x84\x9B\xE6\xAD\xA3\xE5\xA6\xB9\x22}\x0A}".decode('string-escape'))





{

"campaign": "c181518671956.820106",

"platform": 1,

"price": 0,

"materials": [{

"file_type": 1,

"img_url": "http://www.baidu.com/media/upl ... ot%3B

}],

"content": "測試submit",

"tags": [{

"tag_type": "#",

"text": "烘爐地南山福德宮"

}, {

"tag_type": "#",

"text": "拜拜愛用開運招財包"

}],

"influencer": {

"third_party_token": "EAAXNnbIx0GoBAJ0n6pJO3o5buUaEnXOfyMXryuQdqRUGHPSlhUNZCZAdWHABqntpWf2cXZCMWbdLYSLF0POA9uUrZCQAGIVxMl983P20n247BQerZBnUvwRkujZCGa6monlNVj9tW6hZAam5zQZA6VqcoQT8ugTOvd1fBM09GQsgZDZD",

"fan_count": 1264,

"third_party_id": "13895294710539",

"third_party_type": 1,

"user_avatar": "https://scontent.xx.fbcdn.net/ ... ot%3B,

"user_name": "正妹"
}
} 查看全部
很简单 使用python str的decode函数,注意参数使用'string-escape'
python2测试OK


 
print (" {\x0A \x22campaign\x22: \x22c181518671956.820106\x22,\x0A \x22platform\x22:1,\x0A \x22price\x22:0,\x0A \x22materials\x22:[{\x22file_type\x22:1,\x22img_url\x22:\x22http://staging.trylemonade.com ... 1.jpg\x22}],\x0A \x22content\x22: \x22\xE6\xB8\xAC\xE8\xA9\xA6submit\x22,\x0A \x22tags\x22: [{\x22tag_type\x22:\x22#\x22,\x22text\x22:\x22\xE7\x83\x98\xE7\x88\x90\xE5\x9C\xB0\xE5\x8D\x97\xE5\xB1\xB1\xE7\xA6\x8F\xE5\xBE\xB7\xE5\xAE\xAE\x22},{\x22tag_type\x22:\x22#\x22,\x22text\x22:\x22\xE6\x8B\x9C\xE6\x8B\x9C\xE6\x84\x9B\xE7\x94\xA8\xE9\x96\x8B\xE9\x81\x8B\xE6\x8B\x9B\xE8\xB2\xA1\xE5\x8C\x85\x22}],\x0A \x22influencer\x22:\x0A {\x22third_party_token\x22:\x22EAAXNnbIx0GoBAJ0n6pJO3o0M5buUaEnXOfyMXryuQdqRUGHPSlhUNZCZAdWHABqntpWf2cXZCMWbdLYSLF0POA9uUrZCQAGIVxMl983P20n247BQerZBnUvwRkujZCGa6monlNVj9tW6hZAam5zQZA6VqcoQT8ugTOvd1fBM09GQsgZDZD\x22,\x22fan_count\x22:1264,\x22third_party_id\x22:\x221389525994710539\x22,\x22third_party_type\x22:1,\x22user_avatar\x22:\x22https://scontent.xx.fbcdn.net/ ... B2DD4\x22,\x22user_name\x22:\x22\xE6\x84\x9B\xE6\xAD\xA3\xE5\xA6\xB9\x22}\x0A}".decode('string-escape'))





{

"campaign": "c181518671956.820106",

"platform": 1,

"price": 0,

"materials": [{

"file_type": 1,

"img_url": "http://www.baidu.com/media/upl ... ot%3B

}],

"content": "測試submit",

"tags": [{

"tag_type": "#",

"text": "烘爐地南山福德宮"

}, {

"tag_type": "#",

"text": "拜拜愛用開運招財包"

}],

"influencer": {

"third_party_token": "EAAXNnbIx0GoBAJ0n6pJO3o5buUaEnXOfyMXryuQdqRUGHPSlhUNZCZAdWHABqntpWf2cXZCMWbdLYSLF0POA9uUrZCQAGIVxMl983P20n247BQerZBnUvwRkujZCGa6monlNVj9tW6hZAam5zQZA6VqcoQT8ugTOvd1fBM09GQsgZDZD",

"fan_count": 1264,

"third_party_id": "13895294710539",

"third_party_type": 1,

"user_avatar": "https://scontent.xx.fbcdn.net/ ... ot%3B,

"user_name": "正妹"
}
}

批量SSH操作工具---OmniTTY linux 批量管理工具

回复

问答wenda 发起了问题 • 1 人关注 • 0 个回复 • 60 次浏览 • 2019-10-25 11:30 • 来自相关话题

shell date 时间字符串转换

回复

问答wenda 回复了问题 • 1 人关注 • 1 个回复 • 74 次浏览 • 2017-11-01 12:37 • 来自相关话题

wecenter 设置伪静态

博客blog 发表了文章 • 0 个评论 • 28 次浏览 • 2017-10-31 20:43 • 来自相关话题

1、编辑网站根目录 .htaccess 文件 添加以下代码
RewriteBase / 需不需要加看情况 如果不生效 则加上
我的网站托管到000webhost上 需要添加这一行


RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]



2、网站后台管理 站点功能配置处
选择开启伪静态
在自定义路由处填写

/article/(:any)===/article_(:any).html
/question/(:any)===/question_(:any).html



3、观察效果
随便打开一个问题或文章 地址已经变了

/question/20 已经变成了 /question_20.html 查看全部
1、编辑网站根目录 .htaccess 文件 添加以下代码
RewriteBase / 需不需要加看情况 如果不生效 则加上
我的网站托管到000webhost上 需要添加这一行


RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]



2、网站后台管理 站点功能配置处
选择开启伪静态
在自定义路由处填写

/article/(:any)===/article_(:any).html
/question/(:any)===/question_(:any).html



3、观察效果
随便打开一个问题或文章 地址已经变了

/question/20 已经变成了 /question_20.html


python log简单处理

回复

问答wenda 发起了问题 • 1 人关注 • 0 个回复 • 102 次浏览 • 2017-10-20 17:38 • 来自相关话题

python 时间转换

回复

问答wenda 回复了问题 • 1 人关注 • 1 个回复 • 48 次浏览 • 2017-10-20 11:27 • 来自相关话题

VirtualBox中的Ubuntu没有权限访问通过VirtualBox设置的共享文件夹

回复

问答wenda 回复了问题 • 1 人关注 • 1 个回复 • 33 次浏览 • 2017-10-20 11:20 • 来自相关话题

ssh ControlPersist 避免多次输入密码 多次验证

回复

问答wenda 发起了问题 • 1 人关注 • 0 个回复 • 36 次浏览 • 2017-10-20 11:13 • 来自相关话题

北京外语广播 英语PK台 最简语法索引

回复

问答wenda 回复了问题 • 1 人关注 • 3 个回复 • 144 次浏览 • 2017-10-20 12:13 • 来自相关话题

hive 使用总结

回复

问答wenda 回复了问题 • 1 人关注 • 4 个回复 • 96 次浏览 • 2017-10-20 12:23 • 来自相关话题

wecenter 使用highlight.js 高亮代码

博客blog 发表了文章 • 0 个评论 • 69 次浏览 • 2017-10-13 00:54 • 来自相关话题

1、编辑网站
views/default/global/header_meta.tpl

在<head></head>中加入
<pre><code class="html">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</code></pre>

2、使用
<pre><code class="html">
<pre><code class="html">
放置代码
</code></pre>
</code></pre>

3、highlight.js详细教程
<a href="https://highlightjs.org/" rel="nofollow" target="_blank">https://highlightjs.org/</a>



===================
使用bbcode 代替 pre code
1、编辑网站

修改system/Services/BBCode.php

org标注的是原始代码 把这两行替换成org下面的一行
<pre><code class="php">
private function _code_callback($match)
{
//return "<pre>" . str_replace('[', '<span>[</span>', $match[1]) . "</pre>"; // org
return "<pre><code $match[1]>$match[2]</code></pre>";
}



public function __construct()
{
// Replace [code]...[//code] with <pre><code>...</code></pre>
// $this->bbcode_table["/\[code\](.*?)\[\/code\]/is"] = '_code_callback'; // org
$this->bbcode_table["/\[code(.*?)\](.*?)\[\/code\]/is"] = '_code_callback';
}

<code></pre>

2、使用

[code class="html"]
放置代码
注意//code 要写成/code
我这里避免真的当代码转了 所以放置了两个//
[//code]


TODO:
20191025 网站重新部署好 bbcode没生效 还没时间调查 查看全部
1、编辑网站
views/default/global/header_meta.tpl

在<head></head>中加入
<pre><code class="html">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</code></pre>

2、使用
<pre><code class="html">
<pre><code class="html">
放置代码
</code></pre>
</code></pre>

3、highlight.js详细教程
<a href="https://highlightjs.org/" rel="nofollow" target="_blank">https://highlightjs.org/</a>



===================
使用bbcode 代替 pre code
1、编辑网站

修改system/Services/BBCode.php

org标注的是原始代码 把这两行替换成org下面的一行
<pre><code class="php">
private function _code_callback($match)
{
//return "<pre>" . str_replace('[', '<span>[</span>', $match[1]) . "</pre>"; // org
return "<pre><code $match[1]>$match[2]</code></pre>";
}



public function __construct()
{
// Replace [code]...[//code] with <pre><code>...</code></pre>
// $this->bbcode_table["/\[code\](.*?)\[\/code\]/is"] = '_code_callback'; // org
$this->bbcode_table["/\[code(.*?)\](.*?)\[\/code\]/is"] = '_code_callback';
}

<code></pre>

2、使用

[code class="html"]
放置代码
注意//code 要写成/code
我这里避免真的当代码转了 所以放置了两个//
[//code]


TODO:
20191025 网站重新部署好 bbcode没生效 还没时间调查

一个简单的app server搭建 - 未完

博客blog 发表了文章 • 0 个评论 • 104 次浏览 • 2017-10-11 22:17 • 来自相关话题

一个简单的app server搭建


前期
初始阶段,我们会把服务搭成下面这个样子。用户通过域名走http协议,访问我们的服务,前端使用nginx处理http请求,数据转发到后端的app server处理。







选择http协议作为客户端和服务端交互的协议,当然也可以使用其他协议(比如邮件客户端和服务器之间采用smtp/pop3协议),或者自定义网络协议(比如QQ客户端和服务器之间是腾讯自己定义的协议),http协议简单、无状态,请求-响应-结束,下一次请求和响应直接不存在关系。

选择nginx作为http server。为什么要使用nginx,而不是直接让app server接受请求?比如这样:







1、如果app server直接接收请求,那么app server需要负责解析http协议,然后拿到数据,再做自己的业务处理。nginx可以帮我们处理http层的东西,把一些信息(比如客户端IP地址)和应用数据转给app server,这样app server只需要负责处理业务数据就好了。
2、nginx可以实现简单的负载均衡、热备的功能,app server不需要关心和开发这些功能,专注处理业务逻辑。

接下来,定一下nginx和app server的数据传输格式和方式:
有几个选择:
1、cgi (cgi只能通过标准输入输出与本地的nginx通信)
2、fastcgi
3、google protobuf (通过tcp协议传输protobuf格式数据)
4、自定义协议
5、...

我选择fastcgi协议,简单、通用,nginx直接支持。fastcgi与nginx通过tcp通信,两者可以处于不同的物理机上。怎么配置我这里就不介绍了。


server开发
以下server框架推荐大家了解:
1、epoll
2、muduo
3、spserver
4、boost asio

这里使用简单spawn-fcgi + libfcgi 写一个简单的app server。
libfcgi
源码地址:https://github.com/LuaDist/fcg ... bfcgi
这里不多说,这个lib库可以帮你解析nginx传过来的数据。

spawn-fcgi
源码地址: https://github.com/lighttpd/spawn-fcgi
spawn-fcgi很简单。他负责建立server端的tcp socket,然后启动子进程,将socket dup到标准输入上。这样子进程accept 标准输入,接受新连接,接收数据,响应。
下面是代码事例,子进程调用FCGI_Accept,在标准输入上接收一个新链接,然后向链接写入数据作为响应。

#include
#include
#include
int main()
{
int count = 0;
while(FCGI_Accept() >= 0) {
// 这个可以通过FCGI提供的接口获取请求带来的数据
FCGI_printf("Content-type: text/html\r\n"
"\r\n"
""
"FastCGI Hello!"
"Request number %d running on host%s "
"Process ID: %d\n", ++count, getenv("SERVER_NAME"), getpid());
}

return 0;
}


编译

g++ childfcgi.c -o child -lfcgi


配置nginx的upstream

upstream backend {
server 127.0.0.1:8002;
keepalive 600;
}
location / {
fastcgi_pass backend;
fastcgi_keep_conn on;
fastcgi_index index.cgi;
include fastcgi_params;
}


运行

/usr/local/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 8002 -C 25 -f /usr/local/nginx/cgibin/child


这样spawn-fcgi和编译的小程序组成了一个app server与nginx配合就可以处理请求和响应了。
再来回顾下这个框架图:








进阶
随着业务发展,请求数变多,你会发现服务压力越来越大。是时候优化下server了。




http://blog.csdn.net/wzhwho/ar ... 69620 查看全部
一个简单的app server搭建


前期


初始阶段,我们会把服务搭成下面这个样子。用户通过域名走http协议,访问我们的服务,前端使用nginx处理http请求,数据转发到后端的app server处理。

3.png



选择http协议作为客户端和服务端交互的协议,当然也可以使用其他协议(比如邮件客户端和服务器之间采用smtp/pop3协议),或者自定义网络协议(比如QQ客户端和服务器之间是腾讯自己定义的协议),http协议简单、无状态,请求-响应-结束,下一次请求和响应直接不存在关系。

选择nginx作为http server。为什么要使用nginx,而不是直接让app server接受请求?比如这样:

2.png



1、如果app server直接接收请求,那么app server需要负责解析http协议,然后拿到数据,再做自己的业务处理。nginx可以帮我们处理http层的东西,把一些信息(比如客户端IP地址)和应用数据转给app server,这样app server只需要负责处理业务数据就好了。
2、nginx可以实现简单的负载均衡、热备的功能,app server不需要关心和开发这些功能,专注处理业务逻辑。

接下来,定一下nginx和app server的数据传输格式和方式:
有几个选择:
1、cgi (cgi只能通过标准输入输出与本地的nginx通信)
2、fastcgi
3、google protobuf (通过tcp协议传输protobuf格式数据)
4、自定义协议
5、...

我选择fastcgi协议,简单、通用,nginx直接支持。fastcgi与nginx通过tcp通信,两者可以处于不同的物理机上。怎么配置我这里就不介绍了。


server开发


以下server框架推荐大家了解:
1、epoll
2、muduo
3、spserver
4、boost asio

这里使用简单spawn-fcgi + libfcgi 写一个简单的app server。
libfcgi
源码地址:https://github.com/LuaDist/fcg ... bfcgi
这里不多说,这个lib库可以帮你解析nginx传过来的数据。

spawn-fcgi
源码地址: https://github.com/lighttpd/spawn-fcgi
spawn-fcgi很简单。他负责建立server端的tcp socket,然后启动子进程,将socket dup到标准输入上。这样子进程accept 标准输入,接受新连接,接收数据,响应。
下面是代码事例,子进程调用FCGI_Accept,在标准输入上接收一个新链接,然后向链接写入数据作为响应。

#include
#include
#include
int main()
{
int count = 0;
while(FCGI_Accept() >= 0) {
// 这个可以通过FCGI提供的接口获取请求带来的数据
FCGI_printf("Content-type: text/html\r\n"
"\r\n"
""
"FastCGI Hello!"
"Request number %d running on host%s "
"Process ID: %d\n", ++count, getenv("SERVER_NAME"), getpid());
}

return 0;
}


编译

g++ childfcgi.c -o child -lfcgi


配置nginx的upstream

upstream backend {
server 127.0.0.1:8002;
keepalive 600;
}
location / {
fastcgi_pass backend;
fastcgi_keep_conn on;
fastcgi_index index.cgi;
include fastcgi_params;
}


运行

/usr/local/nginx/sbin/spawn-fcgi -a 127.0.0.1 -p 8002 -C 25 -f /usr/local/nginx/cgibin/child


这样spawn-fcgi和编译的小程序组成了一个app server与nginx配合就可以处理请求和响应了。
再来回顾下这个框架图:

2.png




进阶


随着业务发展,请求数变多,你会发现服务压力越来越大。是时候优化下server了。




http://blog.csdn.net/wzhwho/ar ... 69620





4.png




内网服务器 通过ssh 端口转发 对外提供服务

博客blog 发表了文章 • 0 个评论 • 47 次浏览 • 2017-10-11 22:14 • 来自相关话题

内网服务器通过ssh实现端口转发,对外提供服务。
需要一个外网服务器做转发,其实如果有了外网服务器,还把服务配置在内网干啥。




===============================================================
VPS
vps的ssh配置文件,/etc/ssh/sshd_config 文件 需要设置:
GatewayPorts yes
X11Forwarding yes
重启sshd
===============================================================
内网服务器:
autossh -M 5678 -CNfR 9999:127.0.0.1:80 root@199.83.88.179
将127.0.0.1的80端口 反向映射到 199.83.88.179的9999端口上
这样通过外网访问199.83.88.179:9999时 就是访问的127.0.0.1:80
===============================================================
运行autossh时 每次需要输入密码 可以生成秘钥 利用秘钥登陆
#### 客户端
生成秘钥公钥 ssh-keygen -t rsa
将公钥拷到Server scp /root/.ssh/id_rsa.pub root@199.83.88.179:/root/.ssh
#### VPS上
创建authorized_keys2文件
touch /root/.ssh/authorized_keys2 (如果已经存在这个文件, 跳过这条)
追加公钥到authorized_keys2中
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys2
(将id_rsa.pub的内容追加到 authorized_keys2 中)
#### 客户端上再次运行
autossh -M 5678 -CNfR 9999:192.168.1.11:80 root@199.83.88.179
不需要使用用户名密码了
===============================================================
可以把 9999:192.168.1.11:80 换成自己的IP和端口 尝试下
ssh -CNfR 9999:127.0.0.1:22 root@199.83.88.179
199.83.88.179
@***
ssh -p 9999 root@localhost
ssh -f -N -R 10000:localhost:22 username@主控端ip


参考:
本地转发
远程转发
http://blog.chinaunix.net/uid- ... .html
正向连接
反向连接
代理
http://blog.csdn.net/linsanhua ... 60369 查看全部
内网服务器通过ssh实现端口转发,对外提供服务。
需要一个外网服务器做转发,其实如果有了外网服务器,还把服务配置在内网干啥。




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


VPS

vps的ssh配置文件,/etc/ssh/sshd_config 文件 需要设置:

GatewayPorts yes

X11Forwarding yes


重启sshd

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

内网服务器:


autossh -M 5678 -CNfR 9999:127.0.0.1:80 root@199.83.88.179

将127.0.0.1的80端口 反向映射到 199.83.88.179的9999端口上


这样通过外网访问199.83.88.179:9999时 就是访问的127.0.0.1:80


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


运行autossh时 每次需要输入密码 可以生成秘钥 利用秘钥登陆


#### 客户端


生成秘钥公钥 ssh-keygen -t rsa


将公钥拷到Server scp /root/.ssh/id_rsa.pub root@199.83.88.179:/root/.ssh


#### VPS上

创建authorized_keys2文件


touch /root/.ssh/authorized_keys2 (如果已经存在这个文件, 跳过这条)


追加公钥到authorized_keys2中


cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys2

(将id_rsa.pub的内容追加到 authorized_keys2 中)


#### 客户端上再次运行

autossh -M 5678 -CNfR 9999:192.168.1.11:80 root@199.83.88.179

不需要使用用户名密码了


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


可以把 9999:192.168.1.11:80 换成自己的IP和端口 尝试下


ssh -CNfR 9999:127.0.0.1:22 root@199.83.88.179


199.83.88.179

@***


ssh -p 9999 root@localhost


ssh -f -N -R 10000:localhost:22 username@主控端ip




参考:

本地转发

远程转发

http://blog.chinaunix.net/uid- ... .html


正向连接

反向连接

代理

http://blog.csdn.net/linsanhua ... 60369


给libpcap增加一个新的捕包方法

博客blog 发表了文章 • 0 个评论 • 46 次浏览 • 2017-10-11 22:13 • 来自相关话题

libpcap是一个网络数据包捕获函数库,功能非常强大,提供了系统独立的用户级别网络数据包捕获接口,Libpcap可以在绝大多数类unix平台下工作。大多数网络监控软件都以它为基础,著名的tcpdump就是以它为基础的。tcpdump是linux下一个非常重要的网络工具,可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。很多时候为了提升捕包性能,我们通常使用修改过的驱动或者专用网卡来收包,这样就导致libpcap无法工作了,但我们又需要tcpdump来进行调试等工作。这样就需要我们修改libpcap,以支持我们的收包方式。比如pfring就是这样处理的。

为libpcap添加一个捕包方法非常简单,下面代码先实现捕获内存中一个固定包的功能,保证能够工作后,再去支持专有驱动或者专用网卡的收包。以下所涉及的libpcap代码和tcpdump代码,版本分别为libpcap-1.7.2,tcpdump-4.1.1。

首先添加两个文件,编写收包的代码,可以参考的代码还是挺多的,比如pcap-snoop.c、pcap-can-linux.c等。

pcap-ring.h


pcap_t *ring_create(const char *device, char *ebuf, int *is_ours);
int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf);


pcap-ring.c


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include /* optionally get BSD define */
#include

#ifdef HAVE_OS_PROTO_H
# include "os-proto.h"
#endif

#include "pcap-int.h"
#include "errno.h"

struct pcap_ring {
int pad;
};

/*
* 192.168.19.105 -> 202.106.4.151
* DNS
* Name: offlintab.firefoxchina.cn
* Type: A
* Class: IN
*/
char peer0_0[] = {
0x8c,0x21,0x0a,0x6d,0x72,0x58,0x00,0x26,0xc7,0x35,0x2f,0x58,0x08,0x00,0x45,0x00
,0x00,0x47,0x72,0x51,0x00,0x00,0x40,0x11,0x3b,0x42,0xc0,0xa8,0x13,0x69,0xca,0x6a
,0x2e,0x97,0xe5,0x30,0x00,0x35,0x00,0x33,0x5a,0x2e,0x67,0xcb,0x01,0x00,0x00,0x01
,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x6f,0x66,0x66,0x6c,0x69,0x6e,0x74,0x61,0x62
,0x0c,0x66,0x69,0x72,0x65,0x66,0x6f,0x78,0x63,0x68,0x69,0x6e,0x61,0x02,0x63,0x6e
,0x00,0x00,0x01,0x00,0x01
};

static int pcap_read_ring(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int wirelen = sizeof(peer0_0);
int caplen = wirelen;

if(p->break_loop) {
p->break_loop = 0;
/* can release resource here */

return -2; /* must be -2 */
}

if (caplen > p->snapshot) {
caplen = p->snapshot;
}

memcpy(p->buffer, peer0_0, caplen);

if (bpf_filter(p->fcode.bf_insns, p->buffer, wirelen, caplen)) {
struct pcap_pkthdr h;

gettimeofday(&h.ts, NULL);
h.len = wirelen;
h.caplen = caplen;

(*callback)(user, &h, p->buffer);

return 1;
}

return 0;
}

static int pcap_stats_ring(pcap_t *p, struct pcap_stat *ps)
{
/* not yet implemented */
ps->ps_recv = 0; /* number of packets received */
ps->ps_drop = 0; /* number of packets dropped */
ps->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */

return (0);
}

static int pcap_getnonblock_ring(pcap_t *p, char *errbuf)
{
return (0);
}

static int pcap_setnonblock_ring(pcap_t *p, int nonblock, char *errbuf)
{
return (0);
}

static int pcap_inject_ring(pcap_t *p, const void *buf _U_, size_t size _U_)
{
strlcpy(p->errbuf, "Sending packets isn't supported", PCAP_ERRBUF_SIZE);
return (-1);
}

int pcap_activate_ring(pcap_t *handle)
{
handle->bufsize = 2048;
handle->linktype = DLT_EN10MB;
handle->selectable_fd = -1;

handle->read_op = pcap_read_ring;
handle->stats_op = pcap_stats_ring;
handle->inject_op = pcap_inject_ring;
handle->setfilter_op = install_bpf_program;
handle->setdirection_op = NULL;
handle->set_datalink_op = NULL;
handle->getnonblock_op = pcap_getnonblock_fd; //pcap_getnonblock_ring;
handle->setnonblock_op = pcap_setnonblock_fd;//pcap_setnonblock_ring;

handle->buffer = (u_char *)malloc(handle->bufsize);
if (handle->buffer == NULL) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't allocate dump buffer: %s", pcap_strerror(errno));
pcap_cleanup_live_common(handle);

return (PCAP_ERROR);
}

return 0;
}

pcap_t *ring_create(const char *device, char *ebuf, int *is_ours)
{
pcap_t *p;

if(strncmp(device, "ring", 4) != 0) {
*is_ours = 0;
return NULL;
}

*is_ours = 1;

p = pcap_create_common(device, ebuf, sizeof(struct pcap_ring));
if (p == NULL) {
return (NULL);
}

p->activate_op = pcap_activate_ring;

return (p);
}

int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
return (0);
}




修改pcap.c,支持新的收包方式。

pcap.c


#include "pcap-ring.h"
struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
#ifdef PCAP_SUPPORT_DBUS
... ...
{ dbus_findalldevs, dbus_create },
#endif
{ ring_findalldevs, ring_create }, /* new !!! */
{ NULL, NULL }
};



修改 Makefile.in ,将新添加的文件编译进去。

PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ \
@CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@ pcap-ring.c


接下来可以编译了:

./configure

make

可以看到libpcap.a了。

接下编译tcpdump-4.1.1

./configure

make

运行:

[root@localhost tcpdump-4.1.1]# ./tcpdump -i ring1 -c 2
listening on ring1, link-type EN10MB (Ethernet), capture size 65535 bytes
02:17:45.465535 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
02:17:45.485310 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
2 packets captured
0 packets received by filter
0 packets dropped by kernel


可以看到,tcpdump能拿到包并解析了。 查看全部
libpcap是一个网络数据包捕获函数库,功能非常强大,提供了系统独立的用户级别网络数据包捕获接口,Libpcap可以在绝大多数类unix平台下工作。大多数网络监控软件都以它为基础,著名的tcpdump就是以它为基础的。tcpdump是linux下一个非常重要的网络工具,可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。很多时候为了提升捕包性能,我们通常使用修改过的驱动或者专用网卡来收包,这样就导致libpcap无法工作了,但我们又需要tcpdump来进行调试等工作。这样就需要我们修改libpcap,以支持我们的收包方式。比如pfring就是这样处理的。

为libpcap添加一个捕包方法非常简单,下面代码先实现捕获内存中一个固定包的功能,保证能够工作后,再去支持专有驱动或者专用网卡的收包。以下所涉及的libpcap代码和tcpdump代码,版本分别为libpcap-1.7.2,tcpdump-4.1.1。

首先添加两个文件,编写收包的代码,可以参考的代码还是挺多的,比如pcap-snoop.c、pcap-can-linux.c等。

pcap-ring.h


pcap_t *ring_create(const char *device, char *ebuf, int *is_ours);
int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf);


pcap-ring.c


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include /* optionally get BSD define */
#include

#ifdef HAVE_OS_PROTO_H
# include "os-proto.h"
#endif

#include "pcap-int.h"
#include "errno.h"

struct pcap_ring {
int pad;
};

/*
* 192.168.19.105 -> 202.106.4.151
* DNS
* Name: offlintab.firefoxchina.cn
* Type: A
* Class: IN
*/
char peer0_0[] = {
0x8c,0x21,0x0a,0x6d,0x72,0x58,0x00,0x26,0xc7,0x35,0x2f,0x58,0x08,0x00,0x45,0x00
,0x00,0x47,0x72,0x51,0x00,0x00,0x40,0x11,0x3b,0x42,0xc0,0xa8,0x13,0x69,0xca,0x6a
,0x2e,0x97,0xe5,0x30,0x00,0x35,0x00,0x33,0x5a,0x2e,0x67,0xcb,0x01,0x00,0x00,0x01
,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x6f,0x66,0x66,0x6c,0x69,0x6e,0x74,0x61,0x62
,0x0c,0x66,0x69,0x72,0x65,0x66,0x6f,0x78,0x63,0x68,0x69,0x6e,0x61,0x02,0x63,0x6e
,0x00,0x00,0x01,0x00,0x01
};

static int pcap_read_ring(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int wirelen = sizeof(peer0_0);
int caplen = wirelen;

if(p->break_loop) {
p->break_loop = 0;
/* can release resource here */

return -2; /* must be -2 */
}

if (caplen > p->snapshot) {
caplen = p->snapshot;
}

memcpy(p->buffer, peer0_0, caplen);

if (bpf_filter(p->fcode.bf_insns, p->buffer, wirelen, caplen)) {
struct pcap_pkthdr h;

gettimeofday(&h.ts, NULL);
h.len = wirelen;
h.caplen = caplen;

(*callback)(user, &h, p->buffer);

return 1;
}

return 0;
}

static int pcap_stats_ring(pcap_t *p, struct pcap_stat *ps)
{
/* not yet implemented */
ps->ps_recv = 0; /* number of packets received */
ps->ps_drop = 0; /* number of packets dropped */
ps->ps_ifdrop = 0; /* drops by interface -- only supported on some platforms */

return (0);
}

static int pcap_getnonblock_ring(pcap_t *p, char *errbuf)
{
return (0);
}

static int pcap_setnonblock_ring(pcap_t *p, int nonblock, char *errbuf)
{
return (0);
}

static int pcap_inject_ring(pcap_t *p, const void *buf _U_, size_t size _U_)
{
strlcpy(p->errbuf, "Sending packets isn't supported", PCAP_ERRBUF_SIZE);
return (-1);
}

int pcap_activate_ring(pcap_t *handle)
{
handle->bufsize = 2048;
handle->linktype = DLT_EN10MB;
handle->selectable_fd = -1;

handle->read_op = pcap_read_ring;
handle->stats_op = pcap_stats_ring;
handle->inject_op = pcap_inject_ring;
handle->setfilter_op = install_bpf_program;
handle->setdirection_op = NULL;
handle->set_datalink_op = NULL;
handle->getnonblock_op = pcap_getnonblock_fd; //pcap_getnonblock_ring;
handle->setnonblock_op = pcap_setnonblock_fd;//pcap_setnonblock_ring;

handle->buffer = (u_char *)malloc(handle->bufsize);
if (handle->buffer == NULL) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Can't allocate dump buffer: %s", pcap_strerror(errno));
pcap_cleanup_live_common(handle);

return (PCAP_ERROR);
}

return 0;
}

pcap_t *ring_create(const char *device, char *ebuf, int *is_ours)
{
pcap_t *p;

if(strncmp(device, "ring", 4) != 0) {
*is_ours = 0;
return NULL;
}

*is_ours = 1;

p = pcap_create_common(device, ebuf, sizeof(struct pcap_ring));
if (p == NULL) {
return (NULL);
}

p->activate_op = pcap_activate_ring;

return (p);
}

int ring_findalldevs(pcap_if_t **alldevsp, char *errbuf)
{
return (0);
}




修改pcap.c,支持新的收包方式。

pcap.c


#include "pcap-ring.h"
struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
#ifdef PCAP_SUPPORT_DBUS
... ...
{ dbus_findalldevs, dbus_create },
#endif
{ ring_findalldevs, ring_create }, /* new !!! */
{ NULL, NULL }
};



修改 Makefile.in ,将新添加的文件编译进去。
 
PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ \
@CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@ pcap-ring.c


接下来可以编译了:

./configure

make

可以看到libpcap.a了。

接下编译tcpdump-4.1.1

./configure

make

运行:

[root@localhost tcpdump-4.1.1]# ./tcpdump -i ring1 -c 2
listening on ring1, link-type EN10MB (Ethernet), capture size 65535 bytes
02:17:45.465535 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
02:17:45.485310 IP localhost.58672 > dialdns.bta.net.cn.domain: 26571+ A? offlintab.firefoxchina.cn. (43)
2 packets captured
0 packets received by filter
0 packets dropped by kernel


可以看到,tcpdump能拿到包并解析了。

Docker基本安装与使用

博客blog 发表了文章 • 0 个评论 • 32 次浏览 • 2017-10-11 22:12 • 来自相关话题

本文记录Dokcer的基本安装与使用,好记性不如烂博客,记录就是为了不忘记。



以下操作基于ubuntu 14.04 desktop版本,Docker 版本为1.0.1。其他版本的可能存在一些差异,读者请酌情参考。记录的同时也把出现的错误一同记录下来了。注意以下操作都使用了sudo进行了权限提升,记录中没有体现出来。


安装




$ apt-get install docker.io

E: Failed to fetch http://cn.archive.ubuntu.com/u ... 4.deb Size mismatch

E: Failed to fetch http://cn.archive.ubuntu.com/u ... l.deb Size mismatch

E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?



出错了,错误提示里面提示了怎么处理,按照提示做。






apt-get update

apt-get install docker.io --fix-missing



OK,安装成功了 。



基本操作



查看基本信息



service docker.io status
docker.io start/running, process 9220

docker -v
Docker version 1.0.1, build 990021a

docker images
没东西




获取image


想找符合自己要求的镜像可以在hub.docker.com找,比如找一个安装好http server的,找一个具备开发环境的。一般会找到符合自己需求的,这样就不需要自己搭建环境了。下面笔者下载安装了ubuntu 14.04.3的image。



docker search ubuntu
docker pull ubuntu:14.04.3



使用下面的命令可以看到系统里们已经存在的镜像



docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 91e54dfb1179 5 weeks ago 188.4 MB


运行容器

docker run -i -t ubuntu:14.04.3 /bin/bash


退出容器

exit


提交镜像
注意:退出容器后,之前所有操作都不会保存,要保存需要在退出之前,使用commit命令再生成一个image。下面命令先查看了当前运行着的容器,然后将当前容器的状态保存为一个新镜像。保存后就可以退出了,下次启动容器使用新的镜像,上次的操作就会保留着,这样每次你做了修改,如果需要保存,就要提交一个新的镜像。


docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc6c51bbfff6 ubuntu:14.04 /bin/bash 3 minutes ago Up 3 minutes nostalgic_nobel

docker commit cc6c51bbfff6 ubuntu:14.04+
573049725ed15eaffe3fd42be6ec995200da9ea3e201fe7cd3e21628fd588fef



容器内安装ssh服务
启动进入容器后,安装openssh-server,然后修改/etc/ssh/sshd_config文件,修改内容见下面。然后提交当前镜像,保存操作。

apt-get install openssh-server

PermitRootLogin yes
UsePAM no

docker commit cc6c51bbfff6 ubuntu:14.04+openssh-server


接下来退出原来的容器,使用新的镜像启动容器,并做好端口映射。


docker run -i -t -p 50001:22 ubuntu:14.04+openssh-server /bin/bash

/usr/sbin/sshd


此时你另开一个终端,就可以使用ssh客户端登录容器进行操作了


ssh 127.0.0.1 -p 50001



镜像的导出与导入

docker save ubuntu:14.04+openssh-server >/home/andrew/ubuntu.tar

docker load <ubuntu.tar



挂载宿主目录


docker run -i -t -v /home/andrew:/opt 91e54dfb1179 /bin/bash



通过-v参数,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径。默认挂载的路径权限为读写。如果指定为只读可以用:ro


docker run -i -t -v /home/andrew:/opt:ro 91e54dfb1179 /bin/bash 查看全部


本文记录Dokcer的基本安装与使用,好记性不如烂博客,记录就是为了不忘记。




以下操作基于ubuntu 14.04 desktop版本,Docker 版本为1.0.1。其他版本的可能存在一些差异,读者请酌情参考。记录的同时也把出现的错误一同记录下来了。注意以下操作都使用了sudo进行了权限提升,记录中没有体现出来。



安装





$ apt-get install docker.io

E: Failed to fetch http://cn.archive.ubuntu.com/u ... 4.deb Size mismatch

E: Failed to fetch http://cn.archive.ubuntu.com/u ... l.deb Size mismatch

E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?



出错了,错误提示里面提示了怎么处理,按照提示做。







apt-get update

apt-get install docker.io --fix-missing



OK,安装成功了 。




基本操作





查看基本信息




service docker.io status
docker.io start/running, process 9220

docker -v
Docker version 1.0.1, build 990021a

docker images
没东西




获取image



想找符合自己要求的镜像可以在hub.docker.com找,比如找一个安装好http server的,找一个具备开发环境的。一般会找到符合自己需求的,这样就不需要自己搭建环境了。下面笔者下载安装了ubuntu 14.04.3的image。




docker search ubuntu
docker pull ubuntu:14.04.3



使用下面的命令可以看到系统里们已经存在的镜像




docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 91e54dfb1179 5 weeks ago 188.4 MB


运行容器



docker run -i -t ubuntu:14.04.3 /bin/bash


退出容器



exit


提交镜像


注意:退出容器后,之前所有操作都不会保存,要保存需要在退出之前,使用commit命令再生成一个image。下面命令先查看了当前运行着的容器,然后将当前容器的状态保存为一个新镜像。保存后就可以退出了,下次启动容器使用新的镜像,上次的操作就会保留着,这样每次你做了修改,如果需要保存,就要提交一个新的镜像。




docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc6c51bbfff6 ubuntu:14.04 /bin/bash 3 minutes ago Up 3 minutes nostalgic_nobel

docker commit cc6c51bbfff6 ubuntu:14.04+
573049725ed15eaffe3fd42be6ec995200da9ea3e201fe7cd3e21628fd588fef



容器内安装ssh服务


启动进入容器后,安装openssh-server,然后修改/etc/ssh/sshd_config文件,修改内容见下面。然后提交当前镜像,保存操作。



apt-get install openssh-server

PermitRootLogin yes
UsePAM no

docker commit cc6c51bbfff6 ubuntu:14.04+openssh-server


接下来退出原来的容器,使用新的镜像启动容器,并做好端口映射。




docker run -i -t -p 50001:22 ubuntu:14.04+openssh-server /bin/bash

/usr/sbin/sshd


此时你另开一个终端,就可以使用ssh客户端登录容器进行操作了




ssh 127.0.0.1 -p 50001



镜像的导出与导入



docker save ubuntu:14.04+openssh-server >/home/andrew/ubuntu.tar

docker load <ubuntu.tar



挂载宿主目录




docker run -i -t -v /home/andrew:/opt 91e54dfb1179 /bin/bash



通过-v参数,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径。默认挂载的路径权限为读写。如果指定为只读可以用:ro




docker run -i -t -v /home/andrew:/opt:ro 91e54dfb1179 /bin/bash



推荐一个爬虫框架 Scrapy

回复

问答wenda 发起了问题 • 1 人关注 • 0 个回复 • 59 次浏览 • 2017-10-11 22:10 • 来自相关话题

AP、路由、中继、桥接、客户端模式之间的区别

博客blog 发表了文章 • 0 个评论 • 92 次浏览 • 2017-10-11 22:07 • 来自相关话题

在TP-Link迷你无线路由器上有多种模式:AP(接入点)、Router(无线路由)、Repeater(中继)、Bridge(桥接)、 Client(客户端)。但很多用户都不清楚这几种模式的之间的区别,下面将对这几种模式进行详细的介绍。



注意:有的型号的TP-Link 迷你无线路由器上只有AP(接入点)、Router(无线路由)、Repeater(中继)这3种模式。
一、AP(接入点)模式
AP(接入点)模式下,只需要把一根可以上网的网线插在路由器上,无需任何配置就可以上网了;但需要注意这时候路由器上的无线网络未加密,建议设置一个无线密码。

在此模式下,该设备相当于一台无线HUB,可实现无线之间、无线到有线、无线到广域网络的访问。最常见的能够提供无线客户端的接入,例如:无线网卡接入等。






具体设置步骤:该产品出厂默认是AP模式,用网线将设备与宽带接口连接,搜索该设备的无线信号进行连接,把无线IP地址改为自动获取即可(一般情况下,宽带路由器提供分配IP地址功能,DHCP)。

多数单纯性无线AP本身不具备路由功能,包括DNS、DHCP、Firewall在内的服务器功能都必须有独立的路由或是计算机来完成。目前大多数的无线AP都支持多用户(30-100台电脑)接入,数据加密,多速率发送等功能,在家庭、办公室内,一个无线AP便可实现所有电脑的无线接入。

AP即可以和无线网卡建立无线连接,也可以和有线网卡通过网线建立有线连接。

在这种模式下,无线1到13。选择中应该注意的是,如果周围环境中还有其他的无线网络,尽量不要与它使用相同的频率段。

适用场所:例如宾馆、酒店或者其它提供了一根网线上网的场所,通过无线AP可以满足笔记本、手机等设备无线访问互联网。
二、Router(无线路由)模式
在Router(无线路由)模式下,路由器就相当于一台普通的无线宽带路由器;需要连接ADSL Modem(猫)或者光猫等设备来进行配置。

光猫相当于一个桥,桥接光纤口和接路由器WAN的网口,并进行协议转换,路由器负责拨号,并进行路由和NAT。(这种情况也可以让光猫拨号,接路由器LAN口,路由器工作在AP模式进行上网。)





适用场所:用户自己办理了宽带业务情况下使用。
三、Repeater(中继)模式
Repeater(中继)模式下,路由器会通过无线的方式与一台可以上网的无线路由器建立连接,用来放大可以上网的无线路由器上的无线信号;无线中继器是解决信号受损、衰减等问题的一个有效解决方案。

注意:放大后的无线信号的名称和原来的无线路由器的无线信号名称一致。






适用场所:有一台可以上网的无线路由器,但是该无线路由器的无线信号覆盖有线,希望无线信号可以覆盖更广泛的范围时使用。
四、Bridge(桥接)模式
Bridge(桥接)模式,路由器会通过无线的方式与一台可以上网的无线路由器建立连接,用来放大可以上网的无线路由器上的无线信号;

注意:放大后的无线信号的名称和原来的无线路由器的无线信号名称不一样。





适用场所:有一台可以上网的无线路由器,但是该无线路由器的无线信号覆盖有线,希望无线信号可以覆盖更广泛的范围时使用。

Repeater(中继)模式和Bridge(桥接)模式都是通过无线的方式连接到一台可以上网的无线路由器上,无线桥接目的在于连接两个不同的局 域网,中继用于扩大同一个无线网络的覆盖范围。无线桥接会出现两个单独的SSID,即使设置成一样的SSID,还是会显示出多个,中继不管连多少 AP,SSID只有一个。简单的说:无线中继的作用是扩大一个局域网的覆盖范围,而无线桥接的作用是把多个局域网连起来,从而也达到了拓展无线网络覆盖范 围的目的。本质不同,目的相同。
五、Client(客户端)模式
Client(客户端)模式下,路由器相当于一块无线网卡,用来接收其它无线路由器上的无线信号;电脑只能够通过网线连接到路由器上使用。






适用场所:附近有无线信号,并且用户知道该无线信号密码,用户的台式电脑想连接该无线信号上网时使用。 查看全部
在TP-Link迷你无线路由器上有多种模式:AP(接入点)、Router(无线路由)、Repeater(中继)、Bridge(桥接)、 Client(客户端)。但很多用户都不清楚这几种模式的之间的区别,下面将对这几种模式进行详细的介绍。



注意:有的型号的TP-Link 迷你无线路由器上只有AP(接入点)、Router(无线路由)、Repeater(中继)这3种模式。

一、AP(接入点)模式


AP(接入点)模式下,只需要把一根可以上网的网线插在路由器上,无需任何配置就可以上网了;但需要注意这时候路由器上的无线网络未加密,建议设置一个无线密码。

在此模式下,该设备相当于一台无线HUB,可实现无线之间、无线到有线、无线到广域网络的访问。最常见的能够提供无线客户端的接入,例如:无线网卡接入等。

001EG6RRgy6JOGtFQOb3f690.jpg


具体设置步骤:该产品出厂默认是AP模式,用网线将设备与宽带接口连接,搜索该设备的无线信号进行连接,把无线IP地址改为自动获取即可(一般情况下,宽带路由器提供分配IP地址功能,DHCP)。

多数单纯性无线AP本身不具备路由功能,包括DNS、DHCP、Firewall在内的服务器功能都必须有独立的路由或是计算机来完成。目前大多数的无线AP都支持多用户(30-100台电脑)接入,数据加密,多速率发送等功能,在家庭、办公室内,一个无线AP便可实现所有电脑的无线接入。

AP即可以和无线网卡建立无线连接,也可以和有线网卡通过网线建立有线连接。

在这种模式下,无线1到13。选择中应该注意的是,如果周围环境中还有其他的无线网络,尽量不要与它使用相同的频率段。

适用场所:例如宾馆、酒店或者其它提供了一根网线上网的场所,通过无线AP可以满足笔记本、手机等设备无线访问互联网。

二、Router(无线路由)模式


在Router(无线路由)模式下,路由器就相当于一台普通的无线宽带路由器;需要连接ADSL Modem(猫)或者光猫等设备来进行配置。

光猫相当于一个桥,桥接光纤口和接路由器WAN的网口,并进行协议转换,路由器负责拨号,并进行路由和NAT。(这种情况也可以让光猫拨号,接路由器LAN口,路由器工作在AP模式进行上网。)
001EG6RRgy6JOFsOKNnbd690.jpg


适用场所:用户自己办理了宽带业务情况下使用。

三、Repeater(中继)模式


Repeater(中继)模式下,路由器会通过无线的方式与一台可以上网的无线路由器建立连接,用来放大可以上网的无线路由器上的无线信号;无线中继器是解决信号受损、衰减等问题的一个有效解决方案。

注意:放大后的无线信号的名称和原来的无线路由器的无线信号名称一致。
001EG6RRgy6JOFEWMl86e690.png



适用场所:有一台可以上网的无线路由器,但是该无线路由器的无线信号覆盖有线,希望无线信号可以覆盖更广泛的范围时使用。

四、Bridge(桥接)模式


Bridge(桥接)模式,路由器会通过无线的方式与一台可以上网的无线路由器建立连接,用来放大可以上网的无线路由器上的无线信号;

注意:放大后的无线信号的名称和原来的无线路由器的无线信号名称不一样。
001EG6RRgy6JOFLcyV2c8690.jpg


适用场所:有一台可以上网的无线路由器,但是该无线路由器的无线信号覆盖有线,希望无线信号可以覆盖更广泛的范围时使用。

Repeater(中继)模式和Bridge(桥接)模式都是通过无线的方式连接到一台可以上网的无线路由器上,无线桥接目的在于连接两个不同的局 域网,中继用于扩大同一个无线网络的覆盖范围。无线桥接会出现两个单独的SSID,即使设置成一样的SSID,还是会显示出多个,中继不管连多少 AP,SSID只有一个。简单的说:无线中继的作用是扩大一个局域网的覆盖范围,而无线桥接的作用是把多个局域网连起来,从而也达到了拓展无线网络覆盖范 围的目的。本质不同,目的相同。

五、Client(客户端)模式


Client(客户端)模式下,路由器相当于一块无线网卡,用来接收其它无线路由器上的无线信号;电脑只能够通过网线连接到路由器上使用。
001EG6RRgy6JOFN3UQf5f690.jpg



适用场所:附近有无线信号,并且用户知道该无线信号密码,用户的台式电脑想连接该无线信号上网时使用。






MinGW & VC -- DLL

博客blog 发表了文章 • 0 个评论 • 47 次浏览 • 2017-10-11 22:01 • 来自相关话题

mingw & VC -- DLL

Mingw 生成dll


gcc test.c -shared -o libtest.dll -Wl,--output-def,libtest.def,--out-implib,libtest.a



同时生成了 a.def liba.a

VC (VC6.0)生成dll
File->New->Win32 Dynamic-Link Library …
添加代码使用__declspec(dllexport) 或者使用def文件配置好导出函数或变量
编译…

会生成 dll 和 lib两个文件

Mingw使用Mingw生成的dll
静态调用


gcc test_main.c –o test_main.exe –L. –llibtest


动态调用
编译


gcc test_main.c –o test_main.exe –lkernel32


代码


#include



HMODULE hdll = LoadLibrary("libtest.dll");

If(hdll != NULL) {

函数指针= GetProcAddress(hdll, "函数名");

函数指针();

}



动态调用使用GetProcAddress取得函数指针时必须使用生成的def文件中指明的函数名
使用g++编译出的dll 由于C++函数重载的原因会改变函数名

VC使用VC生成的dll
静态调用
Project->Setting->Link->Project Options 填入libtest.lib

编译…

libtest.dll 拷贝至运行目录

运行程序
动态调用
不需要libtest.lib 代码与mingw动态调用同

注意函数名也需要使用 def文件中指明的函数名
Mingw使用VC生成的dll
有两种比较常用函数调用约定 __cdecl __stdcall

1、如果dll中函数调用约定为__cdecl

使用时mingw可直接通过-l链接该dll



gcc sample.c –o sample.exe –L.-llib_a.dll



代码中包含dll的头文件然后就可以调用dll中的函数了

2、如果dll中的函数调用约定为__stdcall

则mingw就不能直接链接了

Windows底层api全部为__stdcall调用约定

因此api不能直接调用 但mingw已经帮我们生成了一批可以直接调用的库文件

在mingw安装目录的lib文件夹下

如果我们想链接kernel32.dll则可以直接使用-lkernel32

gcc会链接lib下的libkernel32.a 通过.a调用真正的kernel32.dll

如果我们有一个__stdcall调用约定的dll文件 则需要通过以下步骤自己生成.a文件



pexports xxx.dll > xxx.def

dlltool --dllname xxx.dll --def xxx.def --output-lib libxxx.dll.a



(pexports 需要到网上自行下载 dlltool为mingw自带的工具)

生成.a文件后就可以使用-l链接 在运行程序时需要将dll 放在运行目录下

一般情况下使用VC生成的dll文件都是__cdecl调用约定 因此一般情况下 VC生成的dll mingw可以直接通过-l选项链接

除非定义函数时显示指定__stdcall调用约定


VC使用Mingw生成的dll
VC无法使用Mingw的a文件也不能像mingw那样直接调用MinGW生成dll文件

如果调用mingw生成的dll则需要通过以下步骤得到相应的lib文件通过lib文件调用



pexports xxx.dll > xxx.def

lib /machine:ix86 /def:xxx.def



(lib为VC自带的工具)

生成了lib文件后剩下的就和VC调用VC产生的dll 类似了

(目前测试 Mingw产生dll时 .h文件中的函数需使用 extern "c" 声明导出函数可以使用导出变量还不可以不知道哪里还需要下点功夫) 查看全部
mingw & VC -- DLL

Mingw 生成dll




gcc test.c -shared -o libtest.dll -Wl,--output-def,libtest.def,--out-implib,libtest.a



同时生成了 a.def liba.a


VC (VC6.0)生成dll


File->New->Win32 Dynamic-Link Library …
添加代码使用__declspec(dllexport) 或者使用def文件配置好导出函数或变量
编译…

会生成 dll 和 lib两个文件


Mingw使用Mingw生成的dll


静态调用




gcc test_main.c –o test_main.exe –L. –llibtest


动态调用


编译


gcc test_main.c –o test_main.exe –lkernel32


代码


#include



HMODULE hdll = LoadLibrary("libtest.dll");

If(hdll != NULL) {

函数指针= GetProcAddress(hdll, "函数名");

函数指针();

}



动态调用使用GetProcAddress取得函数指针时必须使用生成的def文件中指明的函数名
使用g++编译出的dll 由于C++函数重载的原因会改变函数名


VC使用VC生成的dll


静态调用


Project->Setting->Link->Project Options 填入libtest.lib

编译…

libtest.dll 拷贝至运行目录

运行程序

动态调用


不需要libtest.lib 代码与mingw动态调用同

注意函数名也需要使用 def文件中指明的函数名

Mingw使用VC生成的dll


有两种比较常用函数调用约定 __cdecl __stdcall

1、如果dll中函数调用约定为__cdecl

使用时mingw可直接通过-l链接该dll



gcc sample.c –o sample.exe –L.-llib_a.dll



代码中包含dll的头文件然后就可以调用dll中的函数了

2、如果dll中的函数调用约定为__stdcall

则mingw就不能直接链接了

Windows底层api全部为__stdcall调用约定

因此api不能直接调用 但mingw已经帮我们生成了一批可以直接调用的库文件

在mingw安装目录的lib文件夹下

如果我们想链接kernel32.dll则可以直接使用-lkernel32

gcc会链接lib下的libkernel32.a 通过.a调用真正的kernel32.dll

如果我们有一个__stdcall调用约定的dll文件 则需要通过以下步骤自己生成.a文件



pexports xxx.dll > xxx.def

dlltool --dllname xxx.dll --def xxx.def --output-lib libxxx.dll.a



(pexports 需要到网上自行下载 dlltool为mingw自带的工具)

生成.a文件后就可以使用-l链接 在运行程序时需要将dll 放在运行目录下

一般情况下使用VC生成的dll文件都是__cdecl调用约定 因此一般情况下 VC生成的dll mingw可以直接通过-l选项链接

除非定义函数时显示指定__stdcall调用约定



VC使用Mingw生成的dll


VC无法使用Mingw的a文件也不能像mingw那样直接调用MinGW生成dll文件

如果调用mingw生成的dll则需要通过以下步骤得到相应的lib文件通过lib文件调用



pexports xxx.dll > xxx.def

lib /machine:ix86 /def:xxx.def



(lib为VC自带的工具)

生成了lib文件后剩下的就和VC调用VC产生的dll 类似了

(目前测试 Mingw产生dll时 .h文件中的函数需使用 extern "c" 声明导出函数可以使用导出变量还不可以不知道哪里还需要下点功夫)

static and dynamic lib

博客blog 发表了文章 • 0 个评论 • 44 次浏览 • 2017-10-11 22:00 • 来自相关话题

static and dynamic lib in windows and linux.




Windows下的dll和lib
简介
DLL就是动态链接库 LIB是静态链接库

DLL是程序在运行阶段才需要的文件

LIB是程序编译时需要链接的文件
使用静态库
静态库实际上是obj文件打包而成

使用静态库时 在程序中加入

#pragma comment(lib, "WSock32.lib")

或者通过编译器项目设置中 手动添加Lib静态库

这样在链接程序 就会将静态库链接到程序里面 生成一个可执行文件或其他目标文件
使用动态库
动态库是一个标准的PE文件 经过编译器编译链接的

动态库一般会有两个文件 ws32.dll ws32.lib

这里的lib并不是上面介绍的静态库 他只包含了一些跳转指令

真正的执行命令在dll中

动态库的使用有两种方式

一是有系统负责加载dll

这种方式调用dll时 需要在程序编译时将lib链接到程序中

就像添加静态库一样

程序运行时 系统加载dll 执行dll中命令

二是显示加载dll

这种方式调用不需要lib文件

程序运行时 使用loadlibrary等api 显示加载dll

取得里面的函数指针 调用
动态库函数的导出
这里只介绍两种方式

一是使用模块定义文件(.def文件) 二是使用__declspec(dllexport)关键字

使用.def文件导出

优点:

1、能控制导出函数名字 在导出C++函数时 可以控制函数名不出现乱码 如func@123axx

2、你能控制导出函数的序号

特别适用于第三方DLL的制作

def文件格式:

LIBRARY dll名称

EXPORTS

func1 @1

func2 @2

把def文件和代码放在同一级目录下 编译dll时 会自动载入def生成dll

使用__declspec(dllexport)

优点是简单 方便 但无法完成上面.def的工作 一般用于应用程序自己使用的DLL

当DLL更新后 要使用新的DLL 也需要应用重新编译链接
Dll中设置共享可读写变量
Dll中全局变量是可以供多个进程共享的 但如果有一个进程修改了

Dll会使用页面拷贝机制 为该进程维护一个单独的页面 将原有原有数据拷贝过来

然后修改为该进程的值

这样其他进程依然使用原来的页面 所有这个进程对变量的修改 不会影响其他进程

如果我想设置一个变量 让一个进程修改他的值 其他进程也能看到

则必须建立一个共享的节 将共享变量放到节中 告诉dll 这里的东西是共享的

如果我改变他 不要使用页面拷贝机制

创建节的方法(放在原代码文件中):

#pragma data_seg("MySec") //MySec是新创建的节的名字(不能超过8个字节)

HWND g_hWnd=NULL; //新变量必须初始化,否则没有新建节的信息

#pragma data_seg() //以上为新建节

新创建的节 共享后才有效 共享的两种方法

1、#pragma comment(linker,"/section:MySec,RWS") //设置节的属性,读,写,共享

2、也可以把#pragma comment(linker,"/section:MySec,RWS")省略。

在.def文件中添加如下代码:

SEGMENTS

MySec read write shared

也能对节的属性进行设置
Linux 下的.so .a
.a静态库 使用ar命令将一个或多个.o文件打包成.a文件

编译时使用 –llib链接

.a静态库的生成

ar cru libxxx.a x.o xx.o xxx.o

ranlib libxxx.a #更新静态库函数表

动态库使用gcc编译生成

gcc –shared –fPIC xx.c –o libxx.so 查看全部
static and dynamic lib in windows and linux.




Windows下的dll和lib


简介


DLL就是动态链接库 LIB是静态链接库

DLL是程序在运行阶段才需要的文件

LIB是程序编译时需要链接的文件

使用静态库


静态库实际上是obj文件打包而成

使用静态库时 在程序中加入

#pragma comment(lib, "WSock32.lib")

或者通过编译器项目设置中 手动添加Lib静态库

这样在链接程序 就会将静态库链接到程序里面 生成一个可执行文件或其他目标文件

使用动态库


动态库是一个标准的PE文件 经过编译器编译链接的

动态库一般会有两个文件 ws32.dll ws32.lib

这里的lib并不是上面介绍的静态库 他只包含了一些跳转指令

真正的执行命令在dll中

动态库的使用有两种方式

一是有系统负责加载dll

这种方式调用dll时 需要在程序编译时将lib链接到程序中

就像添加静态库一样

程序运行时 系统加载dll 执行dll中命令

二是显示加载dll

这种方式调用不需要lib文件

程序运行时 使用loadlibrary等api 显示加载dll

取得里面的函数指针 调用

动态库函数的导出


这里只介绍两种方式

一是使用模块定义文件(.def文件) 二是使用__declspec(dllexport)关键字

使用.def文件导出

优点:

1、能控制导出函数名字 在导出C++函数时 可以控制函数名不出现乱码 如func@123axx

2、你能控制导出函数的序号

特别适用于第三方DLL的制作

def文件格式:

LIBRARY dll名称

EXPORTS

func1 @1

func2 @2

把def文件和代码放在同一级目录下 编译dll时 会自动载入def生成dll

使用__declspec(dllexport)

优点是简单 方便 但无法完成上面.def的工作 一般用于应用程序自己使用的DLL

当DLL更新后 要使用新的DLL 也需要应用重新编译链接

Dll中设置共享可读写变量


Dll中全局变量是可以供多个进程共享的 但如果有一个进程修改了

Dll会使用页面拷贝机制 为该进程维护一个单独的页面 将原有原有数据拷贝过来

然后修改为该进程的值

这样其他进程依然使用原来的页面 所有这个进程对变量的修改 不会影响其他进程

如果我想设置一个变量 让一个进程修改他的值 其他进程也能看到

则必须建立一个共享的节 将共享变量放到节中 告诉dll 这里的东西是共享的

如果我改变他 不要使用页面拷贝机制

创建节的方法(放在原代码文件中):

#pragma data_seg("MySec") //MySec是新创建的节的名字(不能超过8个字节)

HWND g_hWnd=NULL; //新变量必须初始化,否则没有新建节的信息

#pragma data_seg() //以上为新建节

新创建的节 共享后才有效 共享的两种方法

1、#pragma comment(linker,"/section:MySec,RWS") //设置节的属性,读,写,共享

2、也可以把#pragma comment(linker,"/section:MySec,RWS")省略。

在.def文件中添加如下代码:

SEGMENTS

MySec read write shared

也能对节的属性进行设置

Linux 下的.so .a


.a静态库 使用ar命令将一个或多个.o文件打包成.a文件

编译时使用 –llib链接

.a静态库的生成

ar cru libxxx.a x.o xx.o xxx.o

ranlib libxxx.a #更新静态库函数表

动态库使用gcc编译生成

gcc –shared –fPIC xx.c –o libxx.so
www.000webhost.com