理解私有地址和NAT
私有地址:10.0.0.0~10.255.255.255.255 172.16.0.0~172.31.255.255.255 192.168.0.0~192.168.255.255
私有地址与因特网通信一般是NAT(网络地址翻译)
支持NAT的设备包括路由器、防火墙和独立NAT设备。大部分NAT设备支持一下三种模式:静态、地址池、PAT-端口地址转换
PAT涉及到:修改源地址、端口、ip首部校验和以及tcp段校验和(可能给哪些将于端口号有关的信息放在报文主体中传输的非标准协议带来一些问题)
TCP与UDP性能
即使程序运行在同一台机器上,udp也无法保障数据安全到达---缓冲区空间耗尽导致数据丢失
udp的性能不一定优于tcp,如多次发送数据时,tcp可能组合成一个包发送一次,而upd就会发送多次而导致性能不如tcp
认识TCP的可靠性
收到ACK并不代表对方应用程序接收到了,只是网络协议栈接收到了。
tcp的
这种简单的
校验和也不是那么可靠----忘了在哪看到的文章说 是硬件还是什么的原因导致,tcp发送的数据内容有误
理解TCP写操作
写操作很少向tcp返回错误,由于写操作会在数据被实际发送出去之前返回,通常错误都是由下一条操作返回。因为下一条操作通常都是读操作,所以通常说写操作的错误由读操作返回。
考虑用inetd来装载应用程序
考虑用tcpmux为服务器“分配"知名端口
不要暗杀TIME-WAIT连接
1.处于TIME-WAIT状态下的连接收到RST时,连接立即关闭。如主动关闭放处于TIME-WAIT状态,被动关闭端还有重复分段到达,这是主动关闭端会以ACK响应(被动FIN之后的序列)。但是被动端已经关闭了没有改连接,所以会以RST回复主动端的ACK,这时处于TIME-WAIT状态的主动端收到RST被立即关闭。虽然有些实现避免了这种误杀,但是并不是所有的
2.套接字选项SO_LINGER
如果可能使用大规模的写,而不是很多个小规模的写操作
Nagle算法与延迟ACK之间交互会造成性能下降,禁用Nagle算法,性能问题就会消失,但是网络拥塞就会加剧。所以不应该禁用Nagle算法,相反,应用程序应该将所有逻辑关联的数据一次性写入
理解如何使用connect调用超时
将监听套接字设置为非阻塞,然后用select、epoll等待它完成。
在unix下,连接建立起来时,套接字是可写的。如果出错,套接字会即可写也可读。但是当连接建立后本身有数据可读,那套接字可能是即可读也可写,就像出错了一样。我们应当调用getsockopt来从套接字解析出错状态
1.select/epoll :
小于0 select 出错,
等于0 时间到 ,
大于0 则调用 getsockopt :
2.getsockopt:
小于0 套接字出错(自动设置errno);
大于0 时要判断getsockopt 设置的返回参数err的值是否等于0 ,等于0 成功,不等于0 ,则err就是错误码
ps:elect与阻塞和非阻塞
这2天一直和同事在讨论socket的非阻塞用在什么场合,并且认为在select时,使用的socket要设置成阻塞的,今天在网上搜了一下,才发现,原来,我们搞错了,一个套接字阻塞或者不阻塞,select就在那里,它可以针对这2种套接字使用,对任何一种套接字的轮询检测,超时时间都是有效的,区别就在于:
当select完毕,认为该套接字可读时,
1 .阻塞的套接字,会让read阻塞,直到读到所需要的所有字节;
2 .非阻塞的套接字,会让read读完fd中的数据后就返回,但如果原本你要求读10个数据,这时只读了8个数据,如果你不再次使用select来判断它是否可读,而是直接read,很可能返回EAGAIN或=EWOULDBLOCK(BSD风格) ,
此错误由在非阻塞套接字上不能立即完成的操作返回,例如,当套接字上没有排队数据可读时调用了recv()函数。此错误不是严重错误,相应操作应该稍后重试。对于在非阻塞 SOCK_STREAM套接字上调用connect()函数来说,报告EWOULDBLOCK是正常的,因为建立一个连接必须花费一些时间。
EWOULDBLOCK的意思是如果你不把socket设成非阻塞(即阻塞)模式时,这个读操作将阻塞,也就是说数据还未准备好(但系统知道数据来了,所以select告诉你那个socket可读)。使用非阻塞模式做I/O操作的细心的人会检查errno是不是EAGAIN、EWOULDBLOCK、EINTR,如果是就应该重读,一般是用循环。如果你不是一定要用非阻塞就不要设成这样,这就是为什么系统的默认模式是阻塞。
避免数据复制
避免数据复制,如在linux下多进程间有大量数据传递,则可以考虑共享内存+信号量
将共享内存格式化成链表或者数组,两进程间只需传递链表或者数组元素的序号
使用前将结构sockadddr_in清零
理解已连接的UDP套接字
sendto实际是一种connect调用的特例,用sendto发送数据师,内核子暂时让套接字与目的地址连接,发送数据,然后解除套接字的连接---这种连接应该是本地行为,不会产生任何网络流量,就像对udp调用connect。但是这种临时的连接、解除连接所耗费的时间大概是传输udp数据报的三分之一。所以先调用 connect 可能可以将效率提高
一般接收端不应该调用connect连接到对等实体上,如果这么做,那就只能从这个对等实体接收数据了。其他对等想与接收端连接时会收到ECONNREFUSED错误
理解缓冲区长度带来的影响
非交互式应用程序至少应该将其发送缓冲区设置为3MSS
traceroute
查询到某个目的主机的路径(ip数据包都有TTL,每经过一个路由器,TTL减一,当TTL为0时,该路由器返回一个ICMP传输超时,traceroute通过发送udp报文,每次发送的报文的TTL加1(从1开始),到达目的主机时,由于taceroute发送的目的端口一般不被监测,所有会收到目的主机返回的ICMP端口不可达
)
学习使用lsof
netstat只能看出有哪些端口被占用,但是并不知道是哪个进程。lsof-列出打开的文件:可查是哪个进程使用了哪个文件-套接字
学习使用netstat
1.查看活动的套接字,-f 协议 ,如 netstat -f inet 只看tcp和udp
2.查看网卡-网络接口,netstat -i 可以列出所有网卡ip、mac、ipkts-接收到的分组、opkts-发出的分组、错误、冲突
还可以与 -b 、/ 、-d 一起使用,列出输入输出的字节数,以及丢失的分组
3.查看路由
netstat -rn
4.协议统计 -s 选项。如果只对某个协议统计 ,-sp
如 netstat -sp udp
-ssp 不统计结果是0的信息
学习使用系统中的调试追踪工具strace