天行健
君子以自强不息

详解CentOS 6.4 添加永久静态路由所有方法汇总

Logan阅读(654)评论(0)

CentOS添加永久静态路由,具体如下:

 在使用双网卡,同时使用2个网关的时候就需要加一条静态路由了。当然还有很多时候会需要加路由。

操作系统版本centos-6.4 64bit

一:使用route 命令添加 

1、使用route 命令添加的路由,机器重启或者网卡重启后路由就失效了,方法:

//添加到主机的路由

 # route add –host 192.168.1.11 dev eth0

# route add –host 192.168.1.12 gw 192.168.1.1

//添加到网络的路由

# route add –net 192.168.1.11 netmask 255.255.255.0 dev eth0

# route add –net 192.168.1.11 netmask 255.255.255.0 gw 192.168.1.1

# route add –net 192.168.1.0/24 dev eth1

//添加默认网关

# route add default gw 192.168.2.1

//删除路由

# route del –host 192.168.1.11 dev eth0

2、还可以使用ip命令来添加、删除路由

ip route add default via 172.16.10.2 dev eth0

ip route add 172.16.1.0/24 via 172.16.10.2 dev eth0

格式如下:

ip route

default via gateway dev interface

ip/netmask via gateway dev interface

二:在Linux下设置永久路由的方法:

 1.在/etc/rc.local里添加

 方法:

 route add -net 192.168.3.0/24 dev eth0

route add -net 192.168.2.0/24 gw 192.168.2.254

2.在/etc/sysconfig/network里添加到末尾

 方法:

GATEWAY=gw-ip

或者

 GATEWAY=gw-dev 

3./etc/sysconfig/static-routes :

 any net 192.168.3.0/24 gw 192.168.3.254

 any net 10.250.228.128 netmask 255.255.255.192 gw 10.250.228.129

 如果在rc.local中添加路由会造成NFS无法自动挂载问题,所以使用static-routes的方法是最好的。无论重启系统和service network restart 都会生效。

解决NFS问题的描述:

 按照linux启动的顺序,rc.local里面的内容是在linux所有服务都启动完毕,最后才被执行的,也就是说,这里面的内容是在netfs之后才被执行的,那也就是说在netfs启动的时候,服务器上的静态路由是没有被添加的,所以netfs挂载不能成功。

4、在/etc/sysconfig/network-script/route-interface下添加路由(每个接口一个文件,如果没有就创建一个,只能添加针对该接口的路由)

格式如下:

network/prefix via gateway dev intf

例如给eth0添加一个默认网关:

vim /etc/sysconfig/network-scripts/route-eth0

#添加如下内容(可以省略dev eth0)

0.0.0.0/0 via 172.16.10.2 dev eth0 

ps:注意这里的掩码是0而不是32,因为这里是网段而不是路由。

 保存退出后,service network restart。

使用route -n或netstat -r查看路由表。

[root@localhost ~]# route -n
Kernel IP routing table
Destination   Gateway     Genmask     Flags Metric Ref  Use Iface
172.16.10.0   0.0.0.0     255.255.255.0  U   0   0    0 eth0
192.168.122.0  0.0.0.0     255.255.255.0  U   0   0    0 virbr0
169.254.0.0   0.0.0.0     255.255.0.0   U   1002  0    0 eth0
0.0.0.0     172.16.10.2   0.0.0.0     UG  0   0    0 eth0

默认路由已经被添加到路由表里面了。 

注意如果有两块网卡,需要设置默认路由才能访问internet。

所有添加静态路由的方法在centos6.4上面均经过验证,正确无误。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

centos 6.5 oracle开机自启动的环境配置详解

Logan阅读(20516)评论(0)

centos 6.5 oracle开机自启动的环境配置详解

环境:centos 6.5 + Oracle 11g

自启动之前问题

虚拟机里的oracle环境,每次重启完系统,用plsql developer连接,先是报错:

无TNS监听程序

解决方法是切换到系统的oracle用户,执行lsnrctl start,但是执行之前,因为ORACLE_HOME环境变量没有生效,还要是环境变量文件生效,步骤如下:

[oracle@localhost ~]$ source .bash_profile 

[oracle@localhost ~]$ echo $ORACLE_HOME
/home/oracle/app/oracle/product/11.2.0/dbhome_1

[oracle@localhost ~]$ lsnrctl start

启动完成后,再次连接,又报错:

oracle没有启动。启动步骤如下:

[oracle@localhost ~]$ sqlplus /nolog

SQL*Plus: Release 11.2.0.1.0 Production on Wed Oct 19 14:29:10 2016

Copyright (c) 1982, 2009, Oracle. All rights reserved.

SQL> conn / as sysdba
Connected to an idle instance.
SQL> startup
ORACLE instance started.

Total System Global Area 776646656 bytes
Fixed Size         2217384 bytes
Variable Size       490736216 bytes
Database Buffers     281018368 bytes
Redo Buffers        2674688 bytes
Database mounted.
Database opened.

配置自启动

下面把上述过程都配置成开机启动。

环境变量生效

可能是因为我的oracle用户不是桌面登录的,是从终端su切换过来的,.bash_profile文件没有运行。我把文件里的内容写入.bashrc文件后,重启就可以了。

TNS监听以及oracle服务自启动

编辑: /etc/oratab文件,把最后一行的N改成Y

# This file is used by ORACLE utilities. It is created by root.sh
# and updated by the Database Configuration Assistant when creating
# a database.

# A colon, ':', is used as the field terminator. A new line terminates
# the entry. Lines beginning with a pound sign, '#', are comments.
#
# Entries are of the form:
#  $ORACLE_SID:$ORACLE_HOME::
#
# The first and second fields are the system identifier and home
# directory of the database respectively. The third filed indicates
# to the dbstart utility that the database should , "Y", or should not,
# "N", be brought up at system boot time.
#
# Multiple entries with the same $ORACLE_SID are not allowed.
#
#
orcl:/home/oracle/app/product/11.2.0/dbhome_1:Y

路径可能不同

编辑 /etc/rc.local 文件,增加 最后两行:

#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local
service smb restart
su - oracle -c 'lsnrctl start'
su - oracle -c 'dbstart'
su - oracle -c 'emctl start dbconsole'

dbstart是数据库自带的启动脚本,我们只要加到rc.local中让它开机调用就可以了。但是还需要编辑一下它。修改dbstart的ORACLE_HOME_LISTNER,使其指向$ORACLE_HOME:

# First argument is used to bring up OracleNet Listener
ORACLE_HOME_LISTNER=$ORACLE_HOME

重启虚拟机,发现plsql developer可以直接连接上了。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Linux多线程锁属性设置方法

Logan阅读(606)评论(0)

互斥锁是Linux下多线程资源保护的常用手段,但是在时序复杂的情况下,很容易会出现死锁的情况。

可以通过设置锁的属性,避免同一条线程重复上锁导致死锁的问题。

通过int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)接口设置

一般是以下四种属性:

PTHREAD_MUTEX_NORMAL
This type of mutex does not detect deadlock. A thread attempting to relock this mutex without first unlocking it will deadlock. Attempting to unlock a mutex locked by a different thread results in undefined behaviour. Attempting to unlock an unlocked mutex results in undefined behaviour.

PTHREAD_MUTEX_ERRORCHECK
This type of mutex provides error checking. A thread attempting to relock this mutex without first unlocking it will return with an error. A thread attempting to unlock a mutex which another thread has locked will return with an error. A thread attempting to unlock an unlocked mutex will return with an error.

PTHREAD_MUTEX_RECURSIVE
A thread attempting to relock this mutex without first unlocking it will succeed in locking the mutex. The relocking deadlock which can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this mutex require the same number of unlocks to release the mutex before another thread can acquire the mutex. A thread attempting to unlock a mutex which another thread has locked will return with an error. A thread attempting to unlock an unlocked mutex will return with an error.

PTHREAD_MUTEX_DEFAULT
Attempting to recursively lock a mutex of this type results in undefined behaviour. Attempting to unlock a mutex of this type which was not locked by the calling thread results in undefined behaviour. Attempting to unlock a mutex of this type which is not locked results in undefined behaviour. An implementation is allowed to map this mutex to one of the other mutex types.

这里主要指同一条线程重复上锁,不同线程上锁,无论设置什么属性,当锁已经被锁定后都会互斥阻塞。

使用PTHREAD_MUTEX_RECURSIVE属性,当同一条线程在没有解锁的情况下尝试再次锁定会返回成功。

以上就是小编为大家带来的Linux多线程锁属性设置方法全部内容了,希望大家多多支持脚本之家~

分别在Linux和Windows下设置JVM内存的简单方法

Logan阅读(667)评论(0)

Linux服务器:

在/usr/local/apache-tomcat-5.5.23/bin 目录下的catalina.sh

添加:JAVA_OPTS=’-Xms512m -Xmx1024m’

或者 JAVA_OPTS=”-server -Xms800m -Xmx800m  

-XX:MaxNewSize=256m” 或者 CATALINA_OPTS=”-server -Xms256m -Xmx300m”

Windows服务器:

在/apache-tomcat-5.5.23/bin 目录下的

catalina.bat 添加:

set JAVA_OPTS=-Xms128m -Xmx350m 或者 

set CATALINA_OPTS=-Xmx300M -Xms256M  (区别是一个直接设置jvm内存,另一个设置tomcat内存,CATALINA_OPTS似乎可以与JAVA_OPTS不加区别的使用)

以上就是小编为大家带来的分别在Linux和Windows下设置JVM内存的简单方法全部内容了,希望大家多多支持脚本之家~

CentOS7—HAProxy安装与配置详解

Logan阅读(850)评论(0)

概述

Haproxy下载地址:http://pkgs.fedoraproject.org/repo/pkgs/haproxy/

关闭SElinux、配置防火墙

1、vi /etc/selinux/config

#SELINUX=enforcing #注释掉

#SELINUXTYPE=targeted #注释掉

SELINUX=disabled #增加

:wq! #保存退出

setenforce 0 #使配置立即生效

2、vi /etc/sysconfig/iptables  #编辑

-A RH-Firewall-1-INPUT -d 224.0.0.18 -j ACCEPT #允许组播地址通信

-A RH-Firewall-1-INPUT -p vrrp -j ACCEPT #允许VRRP(虚拟路由器冗余协)通信

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT #允许80端口通过防火墙

:wq! #保存退出

/etc/init.d/iptables restart #重启防火墙使配置生效

安装HAProxy

1、创建HAProxy运行账户和组

groupadd haproxy #添加haproxy组

useradd -g haproxy haproxy -s /bin/false #创建nginx运行账户haproxy并加入到haproxy组,不允许haproxy用户直接登录系统

2、安装:

[root@A local]# yum install -y gcc
[root@A local]# tar zxvf haproxy-1.6.9.tar.gz
[root@A local]# cd haproxy-1.6.9
[root@A local]# make TARGET=linux3100 CPU=x86_64 PREFIX=/usr/local/haprpxy #编译 uname -r #查看系统内核版本号
[root@A local]# make install PREFIX=/usr/local/haproxy #安装

#数说明:
#TARGET=linux3100
#使用uname -r查看内核,如:2.6.18-371.el5,此时该参数就为linux26
#kernel 大于2.6.28的用:TARGET=linux2628
#CPU=x86_64 #使用uname -r查看系统信息,如x86_64 x86_64 x86_64 GNU/Linux,此时该参数就为x86_64
#PREFIX=/usr/local/haprpxy #/usr/local/haprpxy为haprpxy安装路径

3、设置HAProxy

mkdir -p /usr/local/haproxy/conf #创建配置文件目录

mkdir -p /etc/haproxy #创建配置文件目录

touch /usr/local/haproxy/conf/haproxy.cfg #创建配置文件

ln -s /usr/local/haproxy/conf/haproxy.cfg /etc/haproxy/haproxy.cfg #添加配置文件软连接

cp -r /usr/local/src/haproxy-1.6.9/examples/errorfiles /usr/local/haproxy/errorfiles #拷贝错误页面

ln -s /usr/local/haproxy/errorfiles /etc/haproxy/errorfiles #添加软连接

mkdir -p /usr/local/haproxy/log #创建日志文件目录

touch /usr/local/haproxy/log/haproxy.log #创建日志文件

ln -s /usr/local/haproxy/log/haproxy.log /var/log/haproxy.log #添加软连接

cp /usr/local/src/haproxy-1.6.9/examples/haproxy.init /etc/rc.d/init.d/haproxy #拷贝开机启动文件

chmod +x /etc/rc.d/init.d/haproxy #添加脚本执行权限

chkconfig haproxy on #设置开机启动

ln -s /usr/local/haproxy/sbin/haproxy /usr/sbin #添加软连接

4、配置haproxy.cfg参数

cp /usr/local/haproxy/conf/haproxy.cfg /usr/local/haproxy/conf/haproxy.cfg-bak #备份

vi /usr/local/haproxy/conf/haproxy.cfg #编辑,修改
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
 log 127.0.0.1 local2   ###[err warning info debug] 
 chroot /usr/local/haproxy
 pidfile /var/run/haproxy.pid ###haproxy的pid存放路径,启动进程的用户必须有权限访问此文件 
 maxconn 4000     ###最大连接数,默认4000
 user haproxy
 group haproxy
 daemon       ###创建1个进程进入deamon模式运行。此参数要求将运行模式设置为"daemon"
 
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will 
# use if not designated in their block
#---------------------------------------------------------------------
defaults
 mode http    ###默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
 log global   ###采用全局定义的日志
 option dontlognull  ###不记录健康检查的日志信息
 option httpclose  ###每次请求完毕后主动关闭http通道 
 option httplog   ###日志类别http日志格式 
 option forwardfor  ###如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip 
 option redispatch  ###serverId对应的服务器挂掉后,强制定向到其他健康的服务器
 timeout connect 10000 #default 10 second timeout if a backend is not found
 timeout client 300000 ###客户端连接超时
 timeout server 300000 ###服务器连接超时
 maxconn  60000  ###最大连接数
 retries  3   ###3次连接失败就认为服务不可用,也可以通过后面设置 
####################################################################
listen stats
  bind 0.0.0.0:1080   #监听端口 
  stats refresh 30s   #统计页面自动刷新时间 
  stats uri /stats   #统计页面url 
  stats realm Haproxy Manager #统计页面密码框上提示文本 
  stats auth admin:admin  #统计页面用户名和密码设置 
  #stats hide-version   #隐藏统计页面上HAProxy的版本信息
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
 bind 0.0.0.0:80
 acl url_static path_beg -i /static /images /javascript /stylesheets
 acl url_static path_end -i .jpg .gif .png .css .js
 
 use_backend static if url_static  ###满足策略要求,则响应策略定义的backend页面
 default_backend dynamic   ###不满足则响应backend的默认页面
 
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
 
backend static
 balance  roundrobin     ###负载均衡模式轮询
 server  static 127.0.0.1:80 check ###后端服务器定义
  
backend dynamic
 balance roundrobin
 server   websrv1 10.252.97.106:80 check maxconn 2000
 server   websrv2 10.117.8.20:80 check maxconn 2000
 
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------

#errorloc 503 http://www.osyunwei.com/404.html

errorfile 403 /etc/haproxy/errorfiles/403.http

errorfile 500 /etc/haproxy/errorfiles/500.http

errorfile 502 /etc/haproxy/errorfiles/502.http

errorfile 503 /etc/haproxy/errorfiles/503.http

errorfile 504 /etc/haproxy/errorfiles/504.http

:wq! #保存退出

service haproxy start #启动

service haproxy stop #关闭

service haproxy restart #重启

5、设置HAProxy日志

vi /etc/syslog.conf #编辑,在最下边增加

# haproxy.log

local0.*   /var/log/haproxy.log

local3.*   /var/log/haproxy.log

:wq! #保存退出

vi /etc/sysconfig/syslog #编辑修改

SYSLOGD_OPTIONS="-r -m 0" #接收远程服务器日志

:wq! #保存退出

service syslog restart #重启syslog

6.浏览器打开haproxy的监控页面

如下:http://120.55.95.103:1080/stats  //说明:1080即haproxy配置文件中监听端口,stats 即haproxy配置文件中的监听名称

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

CentOS 7配置LNMP开发环境及配置文件管理详解

Logan阅读(589)评论(0)

安装并配置MySQL 5.6

从CentOS从7.x开始默认使用MariaDB。MariaDB完全兼容MySQL,包括API和命令行。但是很多时候我们还是会想要安装MySQL,所以不能直接通过yum命令安装。

下载源安装文件

 wget http://repo.mysql.com//mysql57-community-release-el7-8.noarch.rpm 

本地安装rpm包(配置MySQL安装源)

 yum -y localinstall mysql57-community-release-el7-8.noarch.rpm 

查看所有MySQL安装源(默认MySQL安装版本5.7)

 yum repolist all | grep mysql 

关闭MySQL 5.7安装源

 sudo yum-config-manager --disable mysql57-community 

开启MySQL 5.6安装源

 sudo yum-config-manager --enable mysql56-community 

没有yum-config-manager命令可以安装yum install yum-utils.noarch工具 或者编辑/etc/yum.repos.d/mysql-community.repo文件enable项为1表示开启,为0表示关闭

安装MySQL

 yum -y install mysql-devel mysql-community-server 

启动MySQL

 systemctl start mysqld.service 

安全配置MySQL

mysql_secure_installation 

安装并配置PHP 5.6

CentOS 7.1版本中,默认安装PHP为PHP5.4版本,其中php-mysqlnd是PHP源码提供的MYSQL驱动数据库。

很多时候会对PHP环境要求校新的版本,例如PHP5.6环境,记录一种通过yum工具安装最新PHP版本的方法。首先,需要在系统上安装一个扩展yum源,即epel源。可从http://fedoraproject.org/wiki/EPEL网站下载并安装。(注意:如果文章时间久,就可能需要去重新找新的下载链接。)

下载源安装文件

 wget https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-8.noarch.rpm 

本地安装(和上面MySQL安装源命令类似)

 rpm -ivh epel-release-7-8.noarch.rpm 

接着,还需要一个REMI源,这个yum源提供了最新的PHP版本的下载和安装,它的官网http://rpms.famillecollet.com/。安装REMI源的过程如下。

导入gpg校验文件

 rpm --import http://rpms.remirepo.net/RPM-GPG-KEY-remi 

下载源安装文件

 wget https://mirrors.tuna.tsinghua.edu.cn/remi/enterprise/remi-release-7.rpm 

本地安装

 rpm -Uvh remi-release-7.rpm 

默认情况下,REMI是禁用的,防止多个yum源发生冲突。可以通过命令查看REMI源是否成功安装

 yum repolist disabled | grep remi 

通过REMI源安装需要的PHP版本,安装PHP5.6版本。

 yum --enablerepo=remi-php56 install php 

安装php-fpm

 yum --enablerepo=remi-php56 install php-fpm 

开启php-fpm

 systemctl start php-fpm 

安装并配置Nginx

导入gpg校验文件

 rpm --import http://rpms.remirepo.net/RPM-GPG-KEY-remi 

下载源安装文件(配置Nginx安装源)。可从http://nginx.org/packages/centos/网站下载安装源。(注意:如果文章时间久,就可能需要去重新找新的下载链接。)

 wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.10.0-1.el7.ngx.x86_64.rpm 

本地安装

 rpm -Uvh nginx-1.10.0-1.el7.ngx.x86_64.rpm 

安装Nginx

 yum install nginx 

开启Nginx

 systemctl start nginx 

Nginx主机配置(设置php-fpm)

编辑/etc/nginx/conf.d/default.conf配置文件,并重启。

 server {
  listen    80;
  server_name localhost;

  #charset koi8-r;
  #access_log /var/log/nginx/log/host.access.log main;

  root  /usr/share/nginx/html;
  index index.html index.htm index.php;

  #error_page 404       /404.html;

  # redirect server error pages to the static page /50x.html
  #
  error_page  500 502 503 504 /50x.html;
  location = /50x.html {
    root  /usr/share/nginx/html;
  }

  # proxy the PHP scripts to Apache listening on 127.0.0.1:80
  #
  #location ~ \.php$ {
  #  proxy_pass  http://127.0.0.1;
  #}

  # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  #
  location ~ \.php$ {
    root      html;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
    include    fastcgi_params;
  }

  # deny access to .htaccess files, if Apache's document root
  # concurs with nginx's one
  #
  #location ~ /\.ht {
  #  deny all;
  #}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

利用iptables来配置linux禁止所有端口登陆和开放指定端口的方法

Logan阅读(547)评论(0)

1、关闭所有的 INPUT FORWARD OUTPUT 只对某些端口开放。

下面是命令实现:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

再用命令 iptables -L -n 查看 是否设置好, 好看到全部 DROP 了

这样的设置好了,我们只是临时的, 重启服务器还是会恢复原来没有设置的状态

还要使用 service iptables save 进行保存

看到信息 firewall rules 防火墙的规则 其实就是保存在 /etc/sysconfig/iptables

可以打开文件查看 vi /etc/sysconfig/iptables

2、下面我只打开22端口,看我是如何操作的,就是下面2个语句

iptables -A INPUT -p tcp –dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT

再查看下 iptables -L -n 是否添加上去, 看到添加了

Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:22

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp spt:22

现在Linux服务器只打开了22端口,用putty.exe测试一下是否可以链接上去。

可以链接上去了,说明没有问题。

最后别忘记了保存 对防火墙的设置

通过命令:service iptables save 进行保存

iptables -A INPUT -p tcp –dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT

针对这2条命令进行一些讲解吧

-A 参数就看成是添加一条 INPUT 的规则

-p 指定是什么协议 我们常用的tcp 协议,当然也有udp 例如53端口的DNS

到时我们要配置DNS用到53端口 大家就会发现使用udp协议的

而 –dport 就是目标端口 当数据从外部进入服务器为目标端口

反之 数据从服务器出去 则为数据源端口 使用 –sport

-j 就是指定是 ACCEPT 接收 或者 DROP 不接收

3、禁止某个IP访问

1台Linux服务器,2台windows xp 操作系统进行访问
Linux服务器ip 192.168.1.99
xp1 ip: 192.168.1.2
xp2 ip: 192.168.1.8

下面看看我2台xp 都可以访问的

192.168.1.2  这是 xp1 可以访问的,
192.168.1.8 xp2 也是可以正常访问的。

那么现在我要禁止 192.168.1.2 xp1 访问, xp2 正常访问,

下面看看演示

通过命令 iptables -A INPUT -p tcp -s 192.168.1.2 -j DROP

这里意思就是 -A 就是添加新的规则, 怎样的规则呢? 由于我们访问网站使用tcp的,我们就用 -p tcp , 如果是 udp 就写udp,这里就用tcp了, -s就是 来源的意思,ip来源于 192.168.1.2 ,-j 怎么做 我们拒绝它 这里应该是 DROP

好,看看效果。好添加成功。下面进行验证 一下是否生效

一直出现等待状态 最后 该页无法显示 ,这是 192.168.1.2 xp1 的访问被拒绝了。

再看看另外一台 xp 是否可以访问, 是可以正常访问的 192.168.1.8 是可以正常访问的

4、如何删除规则

首先我们要知道 这条规则的编号,每条规则都有一个编号

通过 iptables -L -n –line-number 可以显示规则和相对应的编号

num  target     prot opt source               destination
1    DROP       tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:3306
2    DROP       tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:21
3    DROP       tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:80

多了 num 这一列, 这样我们就可以 看到刚才的规则对应的是 编号2

那么我们就可以进行删除了

iptables -D INPUT 2

删除INPUT链编号为2的规则。

再 iptables -L -n 查看一下 已经被清除了。

5、过滤无效的数据包

假设有人进入了服务器,或者有病毒木马程序,它可以通过22,80端口像服务器外传送数据。

它的这种方式就和我们正常访问22,80端口区别。它发向外发的数据不是我们通过访问网页请求 而回应的数据包。

下面我们要禁止这些没有通过请求回应的数据包,统统把它们堵住掉。

iptables 提供了一个参数 是检查状态的,下面我们来配置下 22 和 80 端口,防止无效的数据包。

iptables -A OUTPUT -p tcp –sport 22 -m state –state ESTABLISHED -j ACCEPT

可以看到和我们以前使用的:
iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT
多了一个状态判断。

同样80端口也一样, 现在删掉原来的2条规则,
iptables -L -n –line-number   

这个是查看规则而且带上编号。我们看到编号就可以 删除对应的规则了。

iptables -D OUTPUT 1     这里的1表示第一条规则。

当你删除了前面的规则, 编号也会随之改变。看到了吧。

好,我们删除了前面2个规则,22端口还可以正常使用,说明没问题了

下面进行保存,别忘记了,不然的话重启就会还原到原来的样子。

service iptables save    进行保存。

Saving firewall rules to /etc/sysconfig/iptables:          [  OK  ]

其实就是把刚才设置的规则写入到 /etc/sysconfig/iptables 文件中。

6、DNS端口53设置

下面我们来看看如何设置iptables来打开DNS端口,DNS端口对应的是53

大家看到我现在的情况了吧,只开放22和80端口, 我现在看看能不能解析域名。

host www.google.com    输入这个命令后,一直等待,说明DNS不通

出现下面提示 :
;; connection timed out; no servers could be reached

ping 一下域名也是不通

[root@localhost ~ping www.google.com
ping: unknown host www.google.com

我这里的原因就是 iptables 限制了53端口。

有些服务器,特别是Web服务器减慢,DNS其实也有关系的,无法发送包到DNS服务器导致的。

下面演示下如何使用 iptables 来设置DNS 53这个端口,如果你不知道 域名服务端口号,你

可以用命令 : grep domain /etc/services

[root@localhost ~grep domain /etc/services
domain          53/tcp                          # name-domain server
domain          53/udp
domaintime      9909/tcp                        # domaintime
domaintime      9909/udp                        # domaintime

看到了吧, 我们一般使用 udp 协议。

好了, 开始设置。。。

iptables -A OUTPUT -p udp –dport 53 -j ACCEPT

这是我们 ping 一个域名,数据就是从本机出去,所以我们先设置 OUTPUT,

我们按照ping这个流程来设置。

然后 DNS 服务器收到我们发出去的包,就回应一个回来

iptables -A INPUT -p udp –sport 53 -j ACCEPT

同时还要设置

iptables -A INPUT -p udp –dport 53 -j ACCEPT
iptables -A OUTPUT -p udp –sport 53 -j ACCEPT

好了, 下面开始测试下, 可以用 iptables -L -n 查看设置情况,确定没有问题就可以测试了

[root@localhost ~iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp dpt:80
ACCEPT     udp  —  0.0.0.0/0            0.0.0.0/0           udp spt:53
ACCEPT     udp  —  0.0.0.0/0            0.0.0.0/0           udp dpt:53

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp spt:22 state ESTABLISHED
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0           tcp spt:80 state ESTABLISHED
ACCEPT     udp  —  0.0.0.0/0            0.0.0.0/0           udp dpt:53
ACCEPT     udp  —  0.0.0.0/0            0.0.0.0/0           udp spt:53

可以测试一下 是否 DNS 可以通过iptables 了。

[root@localhost ~host www.google.com
www.google.com is an alias for www.l.google.com.
www.l.google.com is an alias for www-china.l.google.com.
www-china.l.google.com has address 64.233.189.104
www-china.l.google.com has address 64.233.189.147
www-china.l.google.com has address 64.233.189.99

正常可以解析 google 域名。

ping 方面可能还要设置些东西。

用 nslookup 看看吧

[root@localhost ~nslookup
> www.google.com
Server:         192.168.1.1
Address:        192.168.1.1#53

Non-authoritative answer:
www.google.com  canonical name = www.l.google.com.
www.l.google.com        canonical name = www-china.l.google.com.
Name:   www-china.l.google.com
Address: 64.233.189.147
Name:   www-china.l.google.com
Address: 64.233.189.99
Name:   www-china.l.google.com
Address: 64.233.189.104

说明本机DNS正常, iptables 允许53这个端口的访问。

7、iptables对ftp的设置

现在我开始对ftp端口的设置,按照我们以前的视频,添加需要开放的端口

ftp连接端口有2个 21 和 20 端口,我现在添加对应的规则。

[root@localhost rootiptables -A INPUT -p tcp –dport 21 -j ACCEPT
[root@localhost rootiptables -A INPUT -p tcp –dport 20 -j ACCEPT
[root@localhost rootiptables -A OUTPUT -p tcp –sport 21 -j ACCEPT
[root@localhost rootiptables -A OUTPUT -p tcp –sport 20 -j ACCEPT

好,这样就添加完了,我们用浏览器访问一下ftp,出现超时。

所以我刚才说 ftp 是比较特殊的端口,它还有一些端口是 数据传输端口,例如目录列表, 上传 ,下载 文件都要用到这些端口。

而这些端口是 任意 端口。。。 这个 任意 真的比较特殊。

如果不指定什么一个端口范围, iptables 很难对任意端口开放的,如果iptables允许任意端口访问, 那和不设置防火墙没什么区别,所以不现实的。

那么我们的解决办法就是 指定这个数据传输端口的一个范围。

下面我们修改一下ftp配置文件。

我这里使用vsftpd来修改演示,其他ftp我不知道哪里修改,大家可以找找资料。

[root@localhost rootvi /etc/vsftpd.conf

在配置文件的最下面 加入

pasv_min_port=30001
pasv_max_port=31000

然后保存退出。

这两句话的意思告诉vsftpd, 要传输数据的端口范围就在30001到31000 这个范围内传送。

这样我们使用 iptables 就好办多了,我们就打开 30001到31000 这些端口。

[root@localhost rootiptables -A INPUT -p tcp –dport 30001:31000 -j ACCEPT
[root@localhost rootiptables -A OUTPUT -p tcp –sport 30001:31000 -j ACCEPT

[root@localhost rootservice iptables save

最后进行保存, 然后我们再用浏览器范围下 ftp。可以正常访问

用个账号登陆上去,也没有问题,上传一些文件上去看看。

看到了吧,上传和下载都正常。。 再查看下 iptables 的设置

[root@localhost rootiptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp dpt:22
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp dpt:21
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp dpt:20
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp dpts:30001:31000

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp spt:22
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp spt:21
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp spt:20
ACCEPT     tcp  —  0.0.0.0/0            0.0.0.0/0          tcp spts:30001:31000

这是我为了演示ftp特殊端口做的简单规则,大家可以添加一些对数据包的验证

例如 -m state –state ESTABLISHED,RELATED  等等要求更加高的验证

以上这篇利用iptables来配置linux禁止所有端口登陆和开放指定端口的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

Linux 修改 etc/hosts文件详细介绍

Logan阅读(743)评论(0)

 Linux 修改 etc/hosts文件

hosts文件

hosts —— the static table lookup for host name(主机名查询静态表)。

hosts文件是Linux系统上一个负责ip地址与域名快速解析的文件,以ascii格式保存在/etc/目录下。hosts文件包含了ip地址与主机名之间的映射,还包括主机的别名。在没有域名解析服务器的情况下,系统上的所有网络程序都通过查询该文件来解析对应于某个主机名的ip地址,否则就需要使用dns服务程序来解决。通过可以将常用的域名和ip地址映射加入到hosts文件中,实现快速方便的访问。

优先级 : dns缓存 > hosts > dns服务

hosts格式配置

hosts文件可以配置主机ip与对应的主机名。在局域网或者是万维网上,每台主机都有一个ip地址,它区分开每台主机,并可以根据ip进行通讯。但是Ip地址不符合人脑的记忆规律,因此出现了域名,例如www.baidu.com.在一个局域网中,每台机器都有一个主机名,用于区分主机,便于相互访问。

hosts文件格式

ip地址   主机名/域名   (主机别名)

主机名和域名的区别在于:

  • 主机名通常在局域网内使用,通过hosts文件,主机名就被解析到对应的ip。
  • 域名通常在internet上使用,但是优先级低于hosts文件中内容,因此如果你不想使用internet上的域名解析,可以更改自己的hosts文件,加入自己的域名解析。

hosts文件作用

一个主要的作用是:线下环境模拟,通信双方在同一个局域网内想通过internet上的域名相互访问,则只需要修改自己的/etc/hosts文件内容即可。

例如,修改www.baidu.com的ip为127.0.0.1:

修改/etc/hosts之后,ping百度的效果如下图所示:

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

linux线程的取消(终止)方法

Logan阅读(642)评论(0)

关键:

pthread_cancel函数发送终止信号
pthread_setcancelstate函数设置终止方式
pthread_testcancel函数取消线程(另一功能是:设置取消点)

1 线程取消的定义

一般情况下,线程在其主体函数退出的时候会自动终止,但同时也可以因为接收到另一个线程发来的终止(取消)请求而强制终止。

2 线程取消的语义

线程取消的方法是向目标线程发Cancel信号(pthread_cancel函数发送Cancel信号),但如何处理Cancel信号则由目标线程自己决定,或者忽略、或者立即终止、或者继续运行至Cancelation-point(取消点),由不同的Cancelation状态(pthread_setcancelstate函数设置状态)决定。

线程接收到CANCEL信号的缺省处理(即pthread_create()创建线程的缺省状态)是继续运行至取消点,也就是说设置一个CANCELED状态,线程继续运行,只有运行至Cancelation-point的时候才会退出。

3 取消点

根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、 pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用 pthread_testcancel(),从而达到POSIX标准所要求的目标,即如下代码段:

pthread_testcancel();
retcode = read(fd, buffer, length);
 pthread_testcancel();

4 程序设计方面的考虑

如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用。

5 与线程取消相关的pthread函数

int pthread_cancel(pthread_t thread)

发送终止信号给thread线程,如果成功则返回0,否则为非0值。发送成功并不意味着thread会终止。

int pthread_setcancelstate(int state, int *oldstate)

设置本线程对Cancel信号的反应,state有两种值:PTHREAD_CANCEL_ENABLE(缺省)和 PTHREAD_CANCEL_DISABLE,分别表示收到信号后设为CANCLED状态和忽略CANCEL信号继续运行;old_state如果不为 NULL则存入原来的Cancel状态以便恢复。

int pthread_setcanceltype(int type, int *oldtype)

设置本线程取消动作的执行时机,type由两种取值:PTHREAD_CANCEL_DEFFERED和 PTHREAD_CANCEL_ASYCHRONOUS,仅当Cancel状态为Enable时有效,分别表示收到信号后继续运行至下一个取消点再退出和立即执行取消动作(退出);oldtype如果不为NULL则存入运来的取消动作类型值。

void pthread_testcancel(void)

功能一:设置取消点;

功能二:检查本线程是否处于Canceld状态,如果是,则进行取消动作,否则直接返回。

代码:

#include 
#include 
#include 
#include 
#include 


#define THREAD_MAX 4


pthread_mutex_t mutex;
pthread_t thread[THREAD_MAX];


static int tries;
static int started;


void print_it(int *arg)
{
pthread_t tid;
tid = pthread_self();
printf("Thread %lx was canceled on its %d try.\n",tid,*arg);
}


void *Search_Num(int arg)
{
pthread_t tid;
int num;
int k=0,h=0,j;
int ntries;
tid = pthread_self();

/*while(pthread_mutex_trylock(&mutex) == EBUSY)
{
printf("**************busy****************\n");
pthread_testcancel();
}*/
srand(arg);
num = rand()&0xFFFFFF;
//pthread_mutex_unlock(&mutex);

printf("thread num %lx\n",tid);

ntries = 0;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

pthread_cleanup_push((void *)print_it,(void *)&ntries);

while(1)
{
num = (num+1)&0xffffff;
ntries++;

if(arg == num)
{
//只允许一个线程操作此处
while(pthread_mutex_trylock(&mutex) == EBUSY) { 
//一个线程操作后其余线程进入次循环挂起,等待pthread_cancel函数发送cancel信号终止线程
k++;
if(k == 10000)
{
printf("----------2busy2-----------\n");
}

pthread_testcancel();
}
tries = ntries;
//pthread_mutex_unlock(&mutex);  //如果加上这句话,将会有好几个线程找到主函数中设定的值pid
printf("Thread %lx found the number!\n",tid);

for(j = 0;j

运行结果:

Search the num of 6531
-----------i = 0--------------
thread num b6fbcb70
thread num b67bbb70
thread num b5fbab70
thread num b77bdb70
----------thread num b67bbb70-------------
Thread b67bbb70 found the number!
----------thread num b6fbcb70-------------
----------thread num b77bdb70-------------
----------2busy2-----------
----------thread num b5fbab70-------------
----------2busy2-----------
Thread b5fbab70 was canceled on its 1174527 try.
Thread b77bdb70 was canceled on its 1023100 try.
-----------i = 1--------------
Thread b6fbcb70 was canceled on its 1174527 try.
-----------i = 2--------------
-----------i = 3--------------
It took 1174527 tries ot find the number!

从这结果里你有没有看出什么呢?呵呵~.~

以上就是小编为大家带来的linux线程的取消(终止)方法全部内容了,希望大家多多支持脚本之家~

对send(),recv()函数的全面理解

Logan阅读(588)评论(0)

int send( SOCKET s, const char FAR *buf, int len, int flags );

不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。

客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。

该函数的第一个参数指定发送端套接字描述符;

第二个参数指明一个存放应用程序要发送数据的缓冲区;

第三个参数指明实际要发送的数据的字节数;

第四个参数一般置0。

这里只描述同步Socket的send函数的执行流程。当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的 长度, 如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR;如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议 是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么 send就比较s的发送缓冲区的剩余空间和len,如果len大于剩余空间大小send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余 空间大小send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR;如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。

要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端如 果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执 行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回 SOCKET_ERROR)

注意:在Unix系统下,如果send在等待协议传送数据时网络断开的话,调用send的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

recv函数

int recv( SOCKET s, char FAR *buf, int len, int flags );

不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。

该函数的第一个参数指定接收端套接字描述符;

第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;

第三个参数指明buf的长度;

第四个参数一般置0。

这里只描述同步Socket的recv函数的执行流程。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数 据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,只到 协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。
cp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据.
在阻塞模式下, send函数的过程是将应用程序请求发送的数据拷贝到发送缓存中发送并得到确认后再返回.但由于发送缓存的存在,表现为:如果发送缓存大小比请求发送的大小要大,那么send函数立即返回,同时向网络中发送数据;否则,send向网络发送缓存中不能容纳的那部分数据,并等待对端确认后再返回(接收端只要将数据收到接收缓存中,就会确认,并不一定要等待应用程序调用recv);
在非阻塞模式下,send函数的过程仅仅是将数据拷贝到协议栈的缓存区而已,如果缓存区可用空间不够,则尽能力的拷贝,返回成功拷贝的大小;如缓存区可用空间为0,则返回-1,同时设置errnoEAGAIN.
linux下可用sysctl -a | grep net.ipv4.tcp_wmem查看系统默认的发送缓存大小:
net.ipv4.tcp_wmem = 4096 16384 81920
这有三个值,第一个值是socket的发送缓存区分配的最少字节数,第二个值是默认值(该值会被net.core.wmem_default覆盖),缓存区在系统负载不重的情况下可以增长到这个值,第三个值是发送缓存区空间的最大字节数(该值会被net.core.wmem_max覆盖).
根据实际测试,如果手工更改了net.ipv4.tcp_wmem的值,则会按更改的值来运行,否则在默认情况下,协议栈通常是按net.core.wmem_default和net.core.wmem_max的值来分配内存的.
应用程序应该根据应用的特性在程序中更改发送缓存大小:
socklen_t sendbuflen = 0; 
socklen_t len = sizeof(sendbuflen); 
getsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, (void*)&sendbuflen, &len); 
printf("default,sendbuf:%d\n", sendbuflen); 
 
sendbuflen = 10240; 
setsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, (void*)&sendbuflen, len); 
getsockopt(clientSocket, SOL_SOCKET, SO_SNDBUF, (void*)&sendbuflen, &len); 
printf("now,sendbuf:%d\n", sendbuflen); 


需要注意的是,虽然将发送缓存设置成了10k,但实际上,协议栈会将其扩大1倍,设为20k.
——————-实例分析———————-
在实际应用中,如果发送端是非阻塞发送,由于网络的阻塞或者接收端处理过慢,通常出现的情况是,发送应用程序看起来发送了10k的数据,但是只发送了2k到对端缓存中,还有8k在本机缓存中(未发送或者未得到接收端的确认).那么此时,接收应用程序能够收到的数据为2k.假如接收应用程序调用recv函数获取了1k的数据在处理,在这个瞬间,发生了以下情况之一,双方表现为:
A. 发送应用程序认为send完了10k数据,关闭了socket:
发送主机作为tcp的主动关闭者,连接将处于FIN_WAIT1的半关闭状态(等待对方的ack),并且,发送缓存中的8k数据并不清除,依然会发送给对端.如果接收应用程序依然在recv,那么它会收到余下的8k数据(这个前题是,接收端会在发送端FIN_WAIT1状态超时前收到余下的8k数据.), 然后得到一个对端socket被关闭的消息(recv返回0).这时,应该进行关闭.
B. 发送应用程序再次调用send发送8k的数据:
假 如发送缓存的空间为20k,那么发送缓存可用空间为20-8=12k,大于请求发送的8k,所以send函数将数据做拷贝后,并立即返回8192;
假如发送缓存的空间为12k,那么此时发送缓存可用空间还有12-8=4k,send()会返回4096,应用程序发现返回的值小于请求发送的大小值后,可以认为缓存区已满,这时必须阻塞(或通过select等待下一次socket可写的信号),如果应用程序不理会,立即再次调用send,那么会得到-1的值, 在linux下表现为errno=EAGAIN.
C. 接收应用程序在处理完1k数据后,关闭了socket:
接收主机作为主动关闭者,连接将处于FIN_WAIT1的半关闭状态(等待对方的ack).然后,发送应用程序会收到socket可读的信号(通常是 select调用返回socket可读),但在读取时会发现recv函数返回0,这时应该调用close函数来关闭socket(发送给对方ack);
如果发送应用程序没有处理这个可读的信号,而是在send,那么这要分两种情况来考虑,假如是在发送端收到RST标志之后调用send,send将返回 -1,同时errno设为ECONNRESET表示对端网络已断开,但是,也有说法是进程会收到SIGPIPE信号,该信号的默认响应动作是退出进程,如果忽略该信号,那么send是返回-1,errno为EPIPE(未证实);如果是在发送端收到RST标志之前,则send像往常一样工作;
以上说的是非阻塞的send情况,假如send是阻塞调用,并且正好处于阻塞时(例如一次性发送一个巨大的buf,超出了发送缓存),对端socket关闭,那么send将返回成功发送的字节数,如果再次调用send,那么会同上一样.
D. 交换机或路由器的网络断开:
接收应用程序在处理完已收到的1k数据后,会继续从缓存区读取余下的1k数据,然后就表现为无数据可读的现象,这种情况需要应用程序来处理超时.一般做法是设定一个select等待的最大时间,如果超出这个时间依然没有数据可读,则认为socket已不可用.
发送应用程序会不断的将余下的数据发送到网络上,但始终得不到确认,所以缓存区的可用空间持续为0,这种情况也需要应用程序来处理.
如果不由应用程序来处理这种情况超时的情况,也可以通过tcp协议本身来处理,具体可以查看sysctl项中的:
net.ipv4.tcp_keepalive_intvl
net.ipv4.tcp_keepalive_probes
net.ipv4.tcp_keepalive_time
send函数特点及相关问题收藏
在send函数的help里面看到
The successful completion of a send call does not indicate that the data was successfully delivered.
send成功完成并不代表数据已经成功送达。
If no buffer space is available within the transport system to hold the data to be transmitted, send will block unless the socket has been placed in nonblocking mode.
如果没有缓冲存储待发送的数据,send会阻塞直到socket被设置为非阻塞模式,
On nonblocking stream-oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both client and server machines.
在非阻塞流模式socket中,写入的字节可以是1到需要的长度,依赖于客户端和服务器的缓冲。
The select or WSAEventSelect function can be used to determine when it is possible to send more data.
select 或 WSAEventSelect 函数可以用于决定什么时候可以继续发送数据
阻塞模式下send并不是说直到你发送数据到对方机器才返回的意思,它是说把你要发送的数据放入发送缓冲后,就直接返回。而不是阻塞时,如发送缓冲区没有了,他就直接返回,而阻塞时会等待发送缓冲区有空间。
先看看在阻塞模式下send的表现吧(注意缓冲区的大小,我这里是16k)
1,发送一个小于16k的数据,send马上就返回了
也就说是,send把待发送的数据放入发送缓冲马上就返回了,前提是发送的数据字节数小于缓冲大小
2,发送一个大于16k的数据,send没有马上返回,阻塞了一下
send一定要把所有数据放入缓冲区才会返回,假设我们发32k的数据,当send返回的时候,有16k数据已经到达另一端,剩下16k还在缓冲里面没有发出去
在阻塞模式下
如果发送成功,返回的nBytes一定等于len
nBytes = send(m_socket,buf,len,0);
也就是在上面代码中那个发送循环其实是没有必要的
再看看在非阻塞模式下的情况吧
1,发送一个小于16k的数据,send马上返回了,而且返回的字节长度是等于发送的字节长度的,情况和阻塞模式是向相同的
2,发送一个大于16k的数据,send也是马上就返回了,返回的nByte小于待发送的字节数
来模拟一下实际情况,假设我们有32k的数据要发送,
第一次send,返回16384字节(16k),也就是填满了缓冲区
第二次send,在这之前sleep了1000毫秒,这段时间可能已经有5000字节从缓冲区发出,到达另外一端了,于是缓冲区空了5000字节出来,相应的,这次返回的是5000,表示新放入了5000字节到缓冲区
第三次send ,和第二次相同,又放了6000字节
最后一次send,放入了剩下的字节数,这个时候缓冲还是有数据的。
再发送大于16k数据的情况下,那个send发送循环就是必须的了

以上就是小编为大家带来的对send(),recv()函数的全面理解全部内容了,希望大家多多支持脚本之家~