PNP : TCP relay & Socks4a

来源:互联网 发布:数组foreach c# 编辑:程序博客网 时间:2024/06/05 20:37

TCP relay

TCP中继。
这里写图片描述

带宽不匹配问题怎么应对?

TCP half-closed

这里写图片描述

muduo的做法是:
TcpConnection::shutdown() –> shutdown(sockfd, SHUT_WR)
Keep read(sockdf) uitil it return 0, then close(sockfd)

有可能数据没有读完,此时如果使用close关闭连接,那么TCP会发送一个RST到对端,导致对端数据接收不完整。

向一个收到RST报文的连接发送数据,进程会收到SIGPIPE信号。
那么何时会收到RST报文呢?
1. 请求的目标端口未开放,会收到rst段。
2. socket Recv-Q中的数据未完全被应用程序读取,而关闭该socket,会发送rst段。
3. 向已关闭的socket发送数据,对方会发回rst段。
4. SO_LINGER可以控制close的行为,发送rst。

muduo对与发送方向的half-close做了处理,但是对于接收方向,没做处理,因为这个需求并不常见。在read返回0时,无法判断对方时调用的close、还是shutdown

https://www.zhihu.com/question/48871684

这里写图片描述

如果看到Fin_WAIT_2 CLOSE_WAIT 状态,说明有程序在使用tcp half-close, 只关闭了写端,但是还可以继续接收数据。

non-block TCP relay

通过高水位回掉避免两端接收速度不匹配的情况(阻塞IO不会有这个问题,速度不匹配被自动完成).

tcprelay
$ ./tcprelay 127.0.0.1 3000 2000

客户端
$ pv /dev/zero | nc localhost 2000

服务端 可以限速来模拟一方接受较慢的情况
$ nc -l 3000 | pv -L 1M >/dev/null

61课的调试手段值得学习,gdb 手动调用一个函数,使用命令p

SOCKS4 and SOCKS4a

这里写图片描述

Non-blocking IO is not the only choice

异步DNS解析有些负责,其实nonblock IO不是唯一的选择。

这里写图片描述

TLS握手过程:
这里写图片描述
openssl中这个过程使用的是阻塞IO,使用非阻塞IO将会很复杂。对于天生支持并发的go语言来说,实现这个过程很简单。见go语言的src/crypto/tls/handshake_server.go 中的实现。

Threads vs Events debating for 20 years

关于线程模型和事件驱动模型的争论。
这里写图片描述

第7层以外的实现

这里写图片描述

splice可以避免read,write之间的拷贝。

这里写图片描述
这是从第4层做的relay,相比第7层要简单。

Maglev:Google’s network load balancer.

Bugs

https://github.com/chenshuo/muduo/commit/0502020488bc6d381f76fb6a1616cc58c8ffb903

注意理解这个bug.

TCP的可靠性到底指的是什么(最重要的知识点)

这里写图片描述

调用完send,马上close为什么不可以?
当你close时,如果内核接收缓冲区还有数据未被应用程序处理,那么tcp协议栈会给对方发送一个rst分节(而不是正常关闭连接的Fin分节),那么此时发送缓冲区的数据就不可能发送到对方了。
正确的做法是,对于发送方,如果你不需要发送数据给对方了,那么就是关闭tcp连接的写端: shutdown(WR), 然后等待recv返回0时,就可以使用close关闭整个连接了。接收方的处理比较简单,发送方使用shutdown(WR),那么接收方recv返回0,那么接收方调用close,发送FIN到接收方。接收方收到FIn,recv返回0,然后close。
总结一句话:read返回0时,可以close。但是遇到恶意的客户端,它一直不close,通常需要超时事件,在调用shutdown(WR),在若干秒之后就强制close。
起始可以通过协议设计解决,协议头设置消息长度,服务器接收到了完整数据后就可以close了。
这里写图片描述

这里写图片描述

分布式系统中的partial failure

这里写图片描述

C++11

这里写图片描述

这里写图片描述

注意第一条,list的成员函数size载gcc5之前时o(n), gcc5之后才变成o(1)