基本socket
socket函数
|
|
family: 协议地址族
AF_xxx:表示地址族PF_xxx:表示协议族
基本上都是采用的AF_xxx
connect函数
|
|
如果是TCP套接字,调用connect将发起三次握手,建立成功或出错返回,出错的情况如下:
若TCP客户端没有收到SYN分节的响应,则返回
TIMEDOUT错误。举例来说,调用connect函数时,发送一个SYN包后若无响应则等待6s后再发一个,若无响应则再等待24s。若总共75s时仍未收到则出现本错误。若对客户端的`SYN`的响应是
RST,则表明该服务器主机在我们指定的端口没有进程在等待与之连接。这是一种硬错误,客户端一旦收到RST,则马上返回ECONNREFUSED错误。产生
RST的三个条件:一是目的地为某端口的SYN到达服务器,可是服务器端口并未开放;二是TCP想取消一个已有连接;三是TCP接收到一个根本不存在的连接上的分节。- 若客户端发出的
RST在中间的某个路由器引发了一个“destination unreachable”的ICMP错误,则认为这是一种软错误。客户机内核保存该消息,然后就像情况一一样继续发送,到规定时间(有的是75s)仍未响应,则把保存的消息作为EHOSTUNREACH或ENETUNREACH返回给进程。
端口扫描原理分析
NMAP端口扫描
TCP扫描的原理主要是三次握手。这种扫描也称为SYN扫描。Scanner向主机发起SYN请求。如果服务器回复SYN、ACK,这说明此端口开放。如果回复TCP、RST,表示端口未开放。如果没有回复,那么就可能没有这个服务器,或者数据包被防火墙丢弃。
UDP的扫描原理:由于UDP没有三次握手,所以UDP的扫描原理不一样。同样在Scanner发起一次UDP请求。如果服务器回复ICMP的端口不可达。则说明该服务器的此端口关闭。如果没有回应,这说明:一、服务器开放该端口。二、服务器主机不存在。三、被防火墙等设备丢弃。
ZMAP端口扫描
bind函数
|
|
第二个参数是一个指向特定于协议的地址结构的指针,第三个为该地址结构的长度。
返回的常见错误EADDRINUSE,地址已经被使用。
listen函数
|
|
为了理解bloglog参数,我们必须认识到内核为任何一个给定的监听的套结字维护两个队列:
1) 未完成连接队列,每个这样的
SYN分节对应其中一项:已由某个客户端发出并到达服务器,而服务器正在等待完成相应的三次握手过程。这些套接字处于SYN_RCVD状态。2)已完成连接队列,每个已完成
TCP三路握手过程的客户端对应其中一项。这些套结字处于ESTABLISHED状态。
两队列之和不操过blacklog。
accept函数
|
|
参数cliaddr和addrlen用来返回已连接的对端进程的协议地址,调用前,我们将由*addrlen所引用的整数值置为有cliaddr所指的套接字地址结构的长度,返回时,该整数值即为内核存放该套接字地址结构内的确切长度。所以address_len是一个值结果参数。
如果accept成功,那么其返回值是有内核自动生成的一个全新的描述符。
如果我们队客户协议地址不感兴趣,可以把后面两个参数均设置成空指针。
fork和exec函数
并发服务器
一个最简单的并发服务器
对一个套接字调用colse方法,会导致内核发送一个FIN包,但是父进程调用了close(connfd),并没有发送FIN.
因为每个文件或套接字都由一个引用计数,引用计数放在文件表项中维护。