之后,操作系统断开套接字连接,本地的套接字也会被删除。 TCP 连接 在“委托协议栈发送消息”部分简单地提了下客户端和服务端利用套接字进行连接,那这个连接具体是什么样的呢? 首先什么是套接字?...套接字其实就是个放在内存的备忘录,协议栈在发送数据时先看一眼备忘录,了解这个数据是发到哪个端口,当数据发送出去后,这个备忘录还得记录什么时间收到响应、什么时候断开等控制信息,协议栈需要根据这些信息来决定下一步做什么...套接字则会写入相应的信息,然后将状态改为“正在连接”; 服务端的 TCP 模块收到连接请求后就要回应,与客户端一样, 需要在 TCP 头部设置发送方和接收方的端口号,以及将 SYN 设为 1,同时,返回响应时还要将...接着,将信息打包好,发送给客户端; 客户端收到消息后,发现 SYN 为 1,则表示连接成功,所以在套接字中写入服务器的端口号,同时将状态改为连接完毕。...; 服务器收到 FIN 为 1 的 TCP 头部时,协议栈将套接字记录为进入断开操作状态,同时向客户端发送一个 ACK 号,告诉客户端已经收到消息; 服务器收到断开连接信息时,可能还有数据没有传完,所以等待数据全部传输结束后
() 被动接受TCP客户的连接,(阻塞式)等待连接的到来客户端套接字函数s.connect() 主动初始化TCP服务器连接s.connect_ex() connect()函数的扩展版本,出错时返回出错码...,而不是抛出异常公共用途的套接字函数s.recv() 接收TCP数据s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失...9 ss.close() #关闭服务器套接字(可选) tcp客户端 1 cs = socket() # 创建客户套接字 2 cs.connect() # 尝试连接服务器 3...允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收...feng'.encode('utf-8')) 拆包的发生情况 当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去。
很像生活中的写信或发邮件,不需要征得对方的同意,不需要与对方建立连接,就可以将数据发送出去,但是不能保证发送出去的数据能够确保无误地到达目的地。 ...InputStream is=null; OutputStream os=null; try{ Socket s=new Socket("127.0.0.1",5566); //创建一个套接字并将其连接到...执行时,先启动服务端,服务端创建服务器套接字ServerSocket并绑定到指定的端口,当执行到Socket s=ss.accept()时,会产生“阻塞”(即让程序暂时停留在此处),但客户端启动,创建套接字...例子中,Socket的getInputStream()方法可以获得网络连接输入,返回此套接字的字节输入流对象;getOutputStream()方法返回此套接字的字节输出流对象,用于向连接对象写入数据。...文章前面说了TCP三次握手,客户端发送请求、服务端接受请求并返回确认信息,客户端收到确认信息后再发送确认收到确认信息,简单的三个步骤,过程却非常复杂(而且TCP断开连接时还需要四次挥手)。
fileno 如果指定了fileno,则其他参数将被忽略,导致带有指定文件描述符的套接字返回。 与socket.fromfd()不同,fileno将返回相同的套接字,而不是重复的。...有粘包现象,UDP永远不会粘包 黏包成因 TCP协议中的数据传递 tcp协议的拆包机制 当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去。...socket数据传输过程中的用户态与内核态说明 例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看了,根本不知道该文件的字节流从何处开始,在何处结束 此外...() 开始TCP监听 s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数 s.connect() 主动初始化TCP服务器连接 s.connect_ex...) 连接到当前套接字的远端的地址 s.getsockname() 当前套接字的地址 s.getsockopt() 返回指定套接字的参数 s.setsockopt()
前面提到服务端套接字的绑定与监听 ? 服务端接受连接并生成对等的连接套接字 ?...>>>res = server.accept() # 接受连接请求 >>>type(res) # 返回一个元组 >>>conn, addr = res # conn 元组第一项是一个对等的连接套接字...>>>addr # 元组第二项是对等套接字地址元组 >>>conn is server # 对等的连接套接字与服务端套接字是不同的套接字...使用套接字传输 >客户端发送请求数据到服务端 ? >>>client.send(b'hello world!')...>>>conn.recv(1024) # 指明一次性能接收的最大的字节数量 客户端 一发 一收 服务端 一收 一发 断开套接字连接 >客户端主动断开连接 ?
[管道中仍有未完成请求和应答] 因此我们需要一种方式来关闭TCP连接的一半,给服务器发送一个FIN,告诉它已经完成数据发送,但是仍开放套接口描述字用于读数据。这就需要shutdown函数来完成。...进程不能再对套接口执行任何读操作。调用后,由TCP套接口接收到的数据仅做确认,而不实际接收。 SHUT_WD 关闭连接的写一半,又称半关闭。发送缓冲区的数据都发送出去,然后TCP连接终止。...终止网络连接的正常方法是调用close,但close有两个限制可由函数shutdown来避免。 close将描述字的访问计数减1,仅在计数为0时才关闭套接口。...[调用shutdown关闭TCP连接的写一半] 再修订版str_cli函数 在上一节加入select模型的str_cli函数的基础上再次进行修改,标准输入遇到文件结束符时,调用shutdown函数,关闭...TCP连接的读一半,修改标志位为1,当从套接口读到文件终止符,而此标志位为1时,说明这是正常的终止。
客户端与服务端进行通信时,双方需要使用套接字。当使用Tcp套接字时,传输层会创建两个缓冲区:发送缓冲区和接收缓冲区。...以上就是tcp支持全双工通信的本质原因!!! 接下来Tcp就需要解决发送缓冲区的一些问题: 什么时候将数据发送? 一次发送多少数据? 发送出错了怎么办? 这些都是由Tcp协议来决定的!...所以对序列化和反序列化中还需要进行特别处理 3 程序重构 在我们将序列化与发序列化加入我们的程序中之前我们先来将我们的代码进行一个重构。...之前我们编写的Tcp代码的服务器类并没有做到绝对的解耦: 服务器类中进行了Socket套接字的创建,bind绑定服务器端口号,进入监听模式。...而服务器类只负责建立连接和执行回调函数(回调函数由上层传递),不用在处理套接相关的操作!!!
应用程序中有一个 socket 组件,在应用程序启动时,会调用 socket 申请创建套接字,协议栈会根据应用程序的申请创建套接字:首先分配一个套接字所需的内存空间,这一步相当于是为控制信息准备一个容器...至此套接字的创建就已经完成了。套接字创建完成后,会返回一个套接字描述符给应用程序,这个描述符相当于是区分不同套接字的号码牌。根据这个描述符,应用程序在委托协议栈收发数据时就需要提供这个描述符。...,之后通过网络介质传递给服务器,服务器上会对帧头、IP 模块、TCP 模块的报文头进行解析,从而找到对应的套接字,套接字收到请求后,会写入相应的信息,并且把状态改为正在连接。...TCP 模块在拆分数据时,会计算出网络包偏移量,这个偏移量就是相对于数据从头开始计算的第几个字节,并将算好的字节数写在 TCP 头部,TCP 模块还会生成一个网络包的序号(SYN),这个序号是唯一的,这个序号就是用来让服务器进行确认的...首先,客户端在连接时需要计算出序号初始值,并将这个值发送给服务器。接下来,服务器通过这个初始值计算出 确认号并返回给客户端。
HTTP 要传送一条报文时,会以流的形式将报文数据的内容通过一条打开的 TCP 连接按 序传输。...TCP 套接字 操作系统提供了一些操纵其 TCP 连接的工具。...标识一个本地套接字,使其可以合法接受连接 s2 = accept(s) 等待某人建立一条到本地端口的连接 套接字 API 允许用户创建 TCP 的端点数据结构,将这些端点与远程服务器的 TCP 端点进...上图中说明了可以怎样通过套接字 API 来凸显客户端和服务器在实现 HTTP 事务时所应执行的步骤。 2、TCP 连接的握手 TCP 连接握手需要经过以下几个步骤。如图所示: ?...如果某个 HTTP 事务有大量数据要发 送,是不能一次将所有分组都发送出去的。必须发送一个分组,等待确认;然后可以发送 两个分组,每个分组都必须被确认,这样就可以发送四个分组了,以此类推。
如果client再次调用write发数据给server,由于TCP协议层已经处于RST状态了,因此不会将数据发出,而是发一个SIGPIPE信号给应用层,SIGPIPE信号的缺省处理动作是终止程序。...也就是说只有当所有进程(可能fork多个子进程都打开了这个套接字)都关闭了这个套接字,close 才会发送FIN 段。...所以说,如果是调用shutdown how = 1 ,则意味着往一个已经发送出FIN的套接字中写是允许的,接收到FIN段仅代表对方不再发送数据,但对方还是可以读取数据的,可以让对方可以继续读取缓冲区剩余的数据...shutdown 改成了 close,那么当延时后服务器端发送数据给客户端时,客户端的读端和写端都已经关闭,第一次发AAAAA会返回一个RST段,根据本文前面所说,再次发BBBBB直接产生SIGPIPE...信号,默认会终止进程,但因为我们已经设置了忽略SIGPIPE信号,所以服务器端进程不会被终止,但客户端也会出错,因为回到while循环开头,select阻塞等待时发现套接字的读端已经关闭,所以不能再关心可读事件了
阻塞套接字模式下,send函数如果由于对端tcp窗口太小,不足以将全部数据发送出去,将阻塞执行流,直到出错或超时或者全部发送出去为止;同理recv函数如果当前协议栈系统缓冲区中无数据可读,也会阻塞执行流...这个选项的用处是用于解决,当需要关闭套接字时,协议栈发送缓冲区中尚有未发送出去的数据,等待这些数据发完的最长等待时间。...在收到ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接。...允许将TIME-WAIT套接字重新用于新的TCP连接。默认为0,表示关闭。 u net.ipv4.tcp_tw_recycle=1 表示开启TCP连接中TIME-WAIT套接字的快速回收。...u net.ipv4.tcp_max_tw_buckets=5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数 字,TIME_WAIT套接字将立刻被清除并打印警告信息。
当TCP套接字正常关闭时,close会立刻返回,内核会尽力去保证把未发送的缓存发送出去——注意,是尽力保证,并没有说一定会发出去。使用linger选项时,可以设置一个延时时间。...调用close时,不再立刻返回,而是尝试在设置的延时时间内,将数据发送出去。当全部发送成功,或者到达设置的超时时间时,close就会返回。...利用nc监听指定的TCP端口,然后运行测试程序,抓包如下: ? 可以明显的看到,在关闭TCP套接字时,应用层强制发送了RST中止连接。 任务达成!...在tcp_close函数中, ? 如果套接字设置了linger且lingertime值为0,那么就调用disconnect函数,即tcp_disconnect。在这个函数中, ?...其无不关心具体的套接字的实现,之间返回0。所以对于套接字的fd来说,其close永远返回0——至少到目前的linux最新内核是这样的:D
# socket """ 1、Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。...数据,将string中的数据发送到连接的套接字。...3、sendall:完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。...类型 2、send:发送TCP数据,将string中的数据发送到连接的套接字。...3、sendall:完整发送TCP数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
套接字的工作流程(基于TCP和 UDP两个协议) TCP和UDP对比 TCP(Transmission Control Protocol) 可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信...() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数 s.connect() s.connect_ex() s.connect_ex() connect()函数的扩展版本,出错时返回出错码...,而不是抛出异常 公共用途的套接字函数 s.recv() 接收TCP数据 s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不 会发完) s.sendall(...() 发送UDP数据 s.getpeername() 连接到当前套接字的远端的地址 s.getsockname() 当前套接字的地址 s.getsockopt() 返回指定套接字的参数 s.setsockopt...这些I/O缓冲区特性可整理如下: I/O缓冲区在每个TCP套接字中单独存在; I/O缓冲区在创建套接字时自动生成; 即使关闭套接字也会继续传送输出缓冲区中遗留的数据; 关闭套接字将丢失输入缓冲区中的数据
概念 socket又称“套接字”,socket在应用层和传输层之间,我们的应用层只要将数据传递给socket就可以了,socket会传递给传输层、网络层等。 网络通信其实就是Socket之间的通信。...TCP服务应用 SOCK_DGRAM 数据报式Socket 对应于无连接的UDP服务应用 指定协议,与类型对应,如果传入0会根据第二个参数选择合适的值 常用协议有IPPROTO_TCP(TCP传输协议...)、IPPROTO_UDP(UDP传输协议) 返回值: 如果调用成功就返回新创建的套接字的描述符(套接字描述符是一个整数类型的值),如果失败就返回-1 ---- connect连接到服务器 作用:用来将参数...---- 发送数据 #include 作用 用来将数据由指定的 socket 传给对方主机。使用 send 时套接字必须已经连接。...因此,如果send 成功返回,并不必然表示连接另一端的进程接收数据。所保证的仅是当send 成功返回时,数据已经无错误地发送到网络上。
设置该选项后,假设2小时内在此套接口的任一方向都没有数据交换,TCP就自己主动给对方 发一个保持存活探測分节(keepalive probe)。...当传输数据完毕时,最好取消TCP_CORK 选项设置给连接“拔去塞子”以便任一部分的帧都能发送出去。这同“塞住”网络连接同等重要。...当在TCP_NODELAY 模式下提交大量小数据块传输时,大量信息将依照一次write()函数调用发送一块数据的方式发送出去。...如今server创建了一个套接字同 时等待连接。TCP/IP式的连接过程就是所谓“3次握手”。首先,客户程序发送一个设置SYN标志并且不带数据负载的TCP包(一个SYN包)。...对Linux客户程序来说,我们还可 以採用还有一个选项,它也被叫做TCP_DEFER_ACCEPT。我们知道,套接字分成两种类型,侦听套接字和连接套接字,所以它们也各自具有对应的 TCP选项集合。
在创建时,选择TCP协议和ipv4。.../*将buf中的数据通过套接字发送出去*/ ssize_t Send(void* buf,size_t len,int flag = 0) { //ssize_t send(int sockfd...流程简单来说就是:先获取套接字的文件状态标志,然后将非阻塞属性跟套接字的文件状态标志设置在一起,从而让套接字变成非阻塞。...客户端的套接字通常**不需要手动绑定**(bind)地址和端口号,是因为: ①通常当客户端创建一个套接字的时候,系统会自动分配端口号,不需要用户在创建时显示绑定,系统会自动绑定的。...; return false; } return true; } /*将buf中的数据通过套接字发送出去*/ ssize_t
我们带着以下3个问题来细细分析:发送方法成功返回时,能保证TCP另一端的主机接收到吗?能保证数据已经发送到网络上了吗?套接字为阻塞或者非阻塞时,发送方法做的事情有何不同?...0 : sk->sk_sndtimeo; } 也就是说,当这个套接字是阻塞套接字时,timeo就是SO_SNDTIMEO选项指定的发送超时时间。...(6)在图1的例子中,我们假定使用了阻塞套接字,且等待了足够久的时间,收到了对方的ACK,滑动窗口释放出了缓存。 (7)将剩下的用户态数据都组成MSS报文拷贝到内核态的sk_buff中。...从图1的10个步骤中可知,无论是使用阻塞还是非阻塞套接字,发送方法成功返回时(无论全部成功或者部分成功),既不代表TCP连接的另一端主机接收到了消息,也不代表本机把消息发送到了网络上,只是说明,内核将会试图保证把消息送达对方...Nagle算法要求一个TCP连接上最多只能有一个发送出去还没被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。 内核中是通过 tcp_nagle_test方法实现该算法的。
在上一篇中,我们已经建立好的TCP连接,对应着操作系统分配的1个套接字。操作TCP协议发送数据时,面对的是数据流。...我们带着以下3个问题来细细分析:发送方法成功返回时,能保证TCP另一端的主机接收到吗?能保证数据已经发送到网络上了吗?套接字为阻塞或者非阻塞时,发送方法做的事情有何不同?...0 : sk->sk_sndtimeo; } 也就是说,当这个套接字是阻塞套接字时,timeo就是SO_SNDTIMEO选项指定的发送超时时间。...(6)在图1的例子中,我们假定使用了阻塞套接字,且等待了足够久的时间,收到了对方的ACK,滑动窗口释放出了缓存。 (7)将剩下的用户态数据都组成MSS报文拷贝到内核态的sk_buff中。...Nagle算法要求一个TCP连接上最多只能有一个发送出去还没被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。 内核中是通过 tcp_nagle_test方法实现该算法的。
领取专属 10元无门槛券
手把手带您无忧上云