昆明网站建设猫咪,企业排名优化公司,甘肃建设厅官方网站,网站半年了 没有流量## TCP Socket 收发缓冲区: 每个socket在linux内核中都有一个发送缓冲区和一个接收缓冲区。 只要对端将数据发送过来#xff0c;linux内核TCP/IP协议栈就会负责将数据缓存到socket对应的接收缓冲区中#xff0c;无论是否调用recv。 recv()所做的工作#xff0c;只是把内核缓…
## TCP Socket 收发缓冲区: 每个socket在linux内核中都有一个发送缓冲区和一个接收缓冲区。 只要对端将数据发送过来linux内核TCP/IP协议栈就会负责将数据缓存到socket对应的接收缓冲区中无论是否调用recv。 recv()所做的工作只是把内核缓冲区中的数据拷贝到应用层用户的buffer里面。 调用send()发送的数据的时候只是将应用层buffer中数据拷贝进入socket的内核发送缓冲区之中然后send便会在上层返回注意数据是否发送过去不一定。 linux内核TCP/IP协议栈负责将数据发送到对端。
异常场景 应用进程一直没有读取数据导致接受缓冲区满了。此时接收端通知发送端接收窗口关闭保证接收缓冲区不会溢出。TCP流控机制 滑动窗口法 socket内核发送缓冲区的默认大小 16KB cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 4161536
## Errorssocket层标准错误 These are some standard errors generated by the socket layer.
EAGAIN or EWOULDBLOCK socket被标记为非阻塞当recv操作阻塞或者接收超时。 The socket is marked nonblocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.
EBADF 无效socket The argument sockfd is an invalid descriptor.
ECONNREFUSED 远程主机拒绝网络连接 A remote host refused to allow the network connection (typically because it is not running the requested service).
EFAULT 内存越界 The receive buffer pointer(s) point outside the processs address space.
EINTR 被信号打断 The receive was interrupted by delivery of a signal before any data were available; see signal(7).
EINVAL 参数无效 Invalid argument passed.
ENOTCONN: 没有建连的socket The socket is associated with a connection-oriented protocol and has not been connected.
## 1: socket #include sys/socket.h int socket(int domain, int type, int protocol); domain : AF_UNIX--本地socket AF_INET--ipv4 AF_INET--ipv6 type: SOCKT_STREAM--TCP SOCKT_DGRAM—UDP
## 2: socket reuse (ip复用 或者port复用) 一个socket的五元组 {protocol, src addr, src port, dest addr, dest port} (1) non-reuse 如果指定src addr为0.0.0.0将不再表示某一个具体的地址而是表示本地的所有的可用地址。 指定src addr为0.0.0.0将不再表示某一个具体的地址而是表示本地的所有的可用地址。
reuse有三个级别: non-reuse: src addrsrc port不能冲突。eg: ip1:port1和ip2:port1不冲突。0.0.0.0:port1和ip1:port1冲突。 0.0.0.0和其他IP冲突。 reuse-addr: src addrsrc port不能冲突。 eg: ip1:port1和ip2:port1不冲突。0.0.0.0:port1和ip1:port1不冲突。 0.0.0.0和其他IP不冲突。 reuse-port: src addrsrc port可以冲突。eg: 0.0.0.0:port1和0.0.0.0:port1不冲突。
## 使用setsockopt()设置复用。 设置reuse-addr setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (int){1}, sizeof(int)); 设置reuse-port setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (int){1}, sizeof(int));
## 3: recv 定义 The recv() function is normally used only on a connected socket
原理 recv只是将socket对应的接收缓冲区的数据copy到buffer中真正的是Linux内核的TCP/IP网络协议栈负责接收数据。
接口 #include sys/socket.h ssize_t recv(int socket, void *buffer, size_t length, int flags);
参数socket: buffer: 缓冲区。 length: buffer的长度 flags: 一般设置为0.
返回值0: 返回接收的字节数 -1:发生错误 0:对端关闭了连接 无论阻塞还是非阻塞返回值的都是这3钟 These calls return the number of bytes received, or -1 if an error occurred。 For TCP sockets, the return value 0 means the peer has closed its half side of the connection.
阻塞与非阻塞 阻塞 默认为阻塞。没有数据时recv函数将一直等待获取到数据或者发生报错。 非阻塞 没有数据时不会阻塞着读数据而是返回-1(需要判断errno)需要循环读取数据。
在返回值处理上 阻塞 缓冲区有数据成功执行返回接收到的字节数0。 另一端关闭(0)。 缓冲区无数据阻塞一直等。 连接失败(-1) errno ENOCONN。 非阻塞缓冲区有数据成功执行返回接收到的字节数 0。 另一端关闭(0). 缓冲区无数据立即返回 返回值为-1 同时errno EAGAIN || EWOULDBLOCK。 连接失败(-1) errno ENOCONN。
## 4: 设置阻塞方式 (1) sock socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 或者 (2) int flag fcntl(sock F_F_GETFL)fcntl(sock, F_SETFL, flag | O_NONBLOCK);
## 5: connect #include sys/socket.h int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
connect: 默认为阻塞式的。
非阻塞connect实现机制: a: 创建socket,利用fcntl将其设置为非阻塞。 b: 调用connect函数如果返回0则连接建立如果返回-1检查errno 如果值为 EINPROGRESS则连接正在建立。如果值不是EINPROGRESS建连错误。 c: 调用阻塞式接口select/pool检测是否连接建立。这里对于select/pool可以采用设置超时时间来等待。 d: 在select/pool的超时时间内成功建立返回成功建连。否则调用getsockopt获取错误信息。
示例 https://blog.csdn.net/qq_43684922/article/details/106444292?utm_mediumdistribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-106444292-blog-119000780.235^v27^pc_relevant_t0_downloadspm1001.2101.3001.4242.1utm_relevant_index3
## send
#include sys/socket.h ssize_t send(int sockfd, const void *buf, size_t len, int flags);
返回值 0 发送的的数据字节数。 -1发送发生错误 查看errno。0 N/A Return Value On success, these calls return the number of characters sent. On error, -1 is returned, and errno is set appropriately.
阻塞与非阻塞 在阻塞模式下send函数的过程是将应用程序请求发送的数据拷贝到内核发送缓存中待发送数据完全被拷贝到内核发送缓存区中才返回当然如果内核发送缓存区一直没有空间能容纳待发送的数据,则一直阻塞。 When the message does not fit into the send buffer of the socket, send() normally blocks。 1如果内核发送缓冲区可用大小为0send直接堵塞 2如果内核发送缓冲区可用空间小于待发送的数据长度len则send函数会先把部分数据拷贝到内核发送缓冲区中然后会阻塞等待有空间再将剩余数据发送到内核缓冲区。 3如果待发送数据的长度大于s的内核发送缓冲区的长度时会先将s发送端的内核发送缓冲区填满然后发送端会将内核发送缓冲区的数据发送到接收端socket的内核接收缓冲区所以s发送端的内核发送缓冲区又会慢慢腾出空间send又会将待发送数据往s发送端的内核发送缓冲区中copy。
在非阻塞模式下send函数的过程也是将应用程序请求发送的数据拷贝内核发送缓存中。 send函数不需要等到待发送数据完全被拷贝到内核发送区中才返回。 如果内核缓存区可用空间不够容纳所有待发送数据则尽能力的拷贝返回成功拷贝的大小 如果缓存区可用空间为0,则返回-1,同时设置errno为EAGAIN. In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case. The select(2) call may be used to determine when it is possible to send more data.
errno: EBADF 参数s 非合法的socket处理代码。 EFAULT 参数中有一指针指向无法存取的内存空间 ENOTSOCK 参数s为一文件描述词非socket。 EINTR 被信号所中断。 EAGAIN 此操作会令进程阻断但参数s的socket为不可阻断。 ENOBUFS 系统的缓冲内存不足 ENOMEM 核心内存不足 EINVAL 传给系统调用的参数不正确