http://blog.csdn.net/kzm2008/article/details/5372834
http://blog.csdn.net/kzm2008/article/details/5377117
http://bbs.chinaunix.net/thread-876233-1-1.html
1.原始套接字(raw socket)
1.1 原始套接字工作原理与规则
原始套接字是一个特殊的套接字类型,它的创建方式跟TCP/UDP创建方法几乎是
一摸一样,例如,通过
sockfd = socktet(AF_INET, SOCK_RAW, IPPROTO_ICMP);
这两句程序你就可以创建一个原始套接字.然而这种类型套接字的功能却与TCP或者UDP类型套接字的功能有很大的不同:TCP/UDP类型的套接字
只能够访问传输层以及传输层以上的数据,因为当IP层把数据传递给传输层时,下层的数据包头已经被丢掉了.而原始套接字却可以访问传输层以下的数据,,所
以使用 raw套接字你可以实现上至应用层的数据操作,也可以实现下至链路层的数据操作.
比如:通过
方式创建的raw socket就能直接读取链路层的数据.
什么是TCP/IP、UDP?
TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
这里有一张图,表明了这些协议的关系。
图1
TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。
Socket在哪里呢?
在图1中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。
图2
原来Socket在这里。
Socket是什么呢?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
====================================================
有关raw socket的一些知识 众所周知,通过socket编程,我们能够实现机器之间的通信.在TCP/IP协议 簇(PF_INET)中,可以建立面向连接的SOCK_STREAM类型的socket,非连接的 SOCK_DGRAM类型的socket.事实上,在所有的网络程序中,也是这两种socket用 的最为广泛.除此之外,还有一些不常用的socket类型,它们却是在某些网络通 信中担当重要的角色.这里要讲的就是这么一种socket,称之为raw socket. raw socket的作用主要在三个方面: 1.通过raw socket来接受发向本机的ICMP,IGMP协议包,或者用来发送这些 协议包. 2.接受发向本机的但TCP/IP栈不能够处理的IP包. 3.用来发送一些自己制定源地址特殊作用的IP包(自己写IP头,TCP头等等) 我们知道,平时我们想看一看网络是否通达,就用ping命令测试一些.ping 命令用的是ICMP协议.因此,我们不能够通过建立一个SOCK_STREAM或SOCK_DGRAM 来发送这个包,只能够自己亲自来构建ICMP包来发送.这是一种情况.另一种情况 是:现在许多操作系统在实现网络部分的时候,通常只实现了常用的几种协议, 如tcp,udp,icmp等,但象其它的如ospf,ggp等协议,操作系统往往没有实现,如果 自己有必要编写位于其上的应用,就必须借助raw socket来实现,这是因为操作 系统遇到自己不能够处理的数据包(ip头中的protocol所指定的上层协议不能处 理).就将这个包交给raw socket.而最后一种使用raw socket的目的主要是用来 构建一些特殊的协议头,比如我们想对某台机器进行denial of service类型的 攻击,但是有不想留下痕迹,让别人知道IP包的来源,这时候就可以使用raw socket来发送这些伪造源地址信息的包,这其实也是这种攻击所采用的主要技术 手段.当然了,我说的是HACKER行为,之所以想要处理这些特殊的IP包,通常也是 为了诊断网络的目的.
==================================================================================
关于getsockopt()/setsockopt()函数的参数格式,相关的介绍很多,我只写设置缓冲区的形式:
SO_RCVBUF和SO_SNDBUF每个套接口都有一个发送缓冲区和一个接收缓冲区,使用这两个套接口选项可以改变缺省缓冲区大小。
// 接收缓冲区
int nRecvBuf=32*1024; //设置为32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
//发送缓冲区
int nSendBuf=32*1024;//设置为32K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));
注意:
当设置TCP套接口接收缓冲区的大小时,函数调用顺序是很重要的,因为TCP的窗口规模选项是在建立连接时用SYN与对方互换得到的。对于客户,SO_RCVBUF选项必须在connect之前设置;对于服务器,SO_RCVBUF选项必须在listen前设置。
===============================================
FTP是基于TCP协议的应用层协议,所以我们要能从传输层区分出TCP包和UDP包,但是,前面的规则已经讲到了,对于UDP或者TCP产生的IP层数 据包,内核将不会把它传递给任何原始套接字,而是交给对应的TCP/UDP处理函数,要能够让原始套接字接收UDP和TCP产生的IP数据包,或者说接收 传输层的UDP和TCP类型的数据,所创建的原始套接字必须为ETH_P_IP类型的,在程序里面体现出来就是将第三个参数指定为这个值.