或者通过回环地址127.0.0.1
linux 通过ip adder 查看 ip地址为172.26.96.233
新建进程1(服务端)
nc -l 本地ip 端口号 启动本地服务端 172.26.96.233的9090端口开启监听
此时出现阻塞等待连接
新建进程2(查看当前连接状态)
netstat -natp 显示连接
可以看到第三行程序nc
172.26.96.233:9090为LISTEN监听状态, 0.0.0.0:*
表示接收到
目的地址为172.26.96.233端口为9090
源地址为任何ip地址和端口
的数据包,就把数据包交给nc程序
外界来的数据包通过四元组匹配Socket,从而将数据包交给正确的服务
Recv-Q接收队列 Send-Q发送队列
现在该服务端处于监听状态,还未进行三次握手
一旦有客户端建立连接,才会开始三次三次握手
新建进程3(用于抓包) 过滤端口号为9090
tcpdump -nn -i eth0 port 9090
这里命令写错了,应该改为tcpdump -nn -i lo port 9090 (走本地环回地址而没有走网卡)
新建进程4.(作为用户进程),连接该ip地址和端口号
或者用telnet
此时进程3抓到包
- SYN
- SYN+ACK
- ACK
[S.] SYN
[.] ACK
并且此时新增ESTABLISH状态的连接
新增
lo:9090(服务端) ->lo 48388(客户端)
lo 48388(客户端) ->lo 9090 (服务端)
只要是连接,都会有自己独立的队列,不能进行共享不然区别不出队列中某条数据是谁发的
客户端给服务端发送消息的过程:
进程4(用户进程)给服务端发送消息
进程1(服务进程)收到消息
此时进程3抓到的包
客户端发送数据包 length=6 hello 5个字符+换行符=6个字节
由于TCP是可靠传输的,服务端回传一个ACK表示收到
在这个过程中,客户端send-Q把数据发出去,发到对方的receive-Q,对方从接收队列中读取
服务端给客户端发送消息的过程
进程1(服务端)给进程4(客户端)发送消息
进程4(客户端)收到进程1(服务端发来的消息)
这个过程中进程3抓到的包
服务端发送数据包 length=6 hello client12个字符+换行符=13个字节
由于TCP是可靠传输的,客户端回传一个ACK表示收到
在这个过程中,服务端send-Q把数据发出去,发到对方的recv-Q,对方从接收队列中读取
- socket本身用4元组(源IP,源端口,目的IP,目的端口)唯一区分,真正的数据传输靠socket自己独立的发送和接收队列完成
- 三次握手实际是双方开辟资源,产生为对方提供服务的队列以及规则,未来的数据包在上面进行发送和接受
- 在刚三次握手时队列就可以使用,但三次握手完成后队列才真正能够使用(Socket处于ESTABLISHED)
一个主机端口号有65535个
理论上服务器一个端口号最多可以建立65536个连接
无状态协议
客户端服务端通信,必须通过TCP协议建立socket连接
如果只建立一个连接,但是有很多线程 如果应用层使用HTTP传输 如果多个线程使用同一连接,返回消息时无法区分返回给哪个线程,所以 HTTP协议是无状态的,一个线程只能同时使用一个连接 如果要满足多个线程和服务器同时通信,必须建立多个连接
短连接与长连接:
短连接:
单步请求(发送完回来,后面发不发不重要,完全可以断开)
长连接:
设置为KEEPALIVE开启,一个连接串行请求资源
有状态通信:
RPC协议给消息设置id,通过map进行映射,消息返回时可以匹配线程
约束:必须完成id的返回
请求方 对不同服务,控制连接池数量
服务提供方 限制链接数量,限流
TCP连接建立后,因为各种原因断开了,假设是client侧网络断了,那么服务端端侧连接没有关闭,若client再次发起请求,又建立TCP,之前连接的服务端为什么不能立即释放socket队列等待资源?
连接是两个端点间的队列,中间断了,两边都不知道谁断了,客户端发了几次后发现没有回应,客户端连接断开。
服务端是无法感知到的,在加上服务端没有开启 TCP keepalive,又没有数据交互的情况下,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程
解决方法:内核中有心跳机制,服务端需要利用心跳机制进行断开



