Linux/Unix系统编程手册--SOCKET章节读书笔记

SOCKET章节读书笔记

强烈推荐Linux/Unix系统编程手册,号称超越APUE的神书。

backlog含义

#include <sys/socket.h>
int listen(int socketfd, int backlog)

backlog参数限制未决连接(未accept)的数量,在这个数量之内,connect会立刻成功

Linux上上限为128,定义在

udp已连接socket

udp socket也是可以调用connect()的,这种叫已连接socket,内核会记录这个socket的对等socket的地址。

当一个udp socket已连接之后:

1.数据包发送可使用write或send,会自动发送到对等socket上,与sendto一样,每个write会发送一个独立的数据包

2.在这个socket上只能读取对等socket发送的数据**

零时端口

未调用bind(),tcp/udp会分配一个零时端口(tcp服务器也可以不调用bind)

可通过/proc/sys/net/ipv4/ip_local_port_range来修改范围,一般做高并发测试时,测试机可能需要修改以支持多并发。

UDP避免IP分段

一般来说,UDP会采用保守的方法来避免IP分段,即确保传输的IP数据包的大小小于IPv4组缓冲区576字节。8自己udp头部,至少需要20字节存放IP头,剩下548字节存放UDP数据包。实践中,一般会选择512来存放数据包。

shutdown与close区别

SHUT_WR被称为半关闭套接字,通过文件结尾来通知对端本地的写端已经关闭了。

shoutdown与close一个重要区别:无论该套接字上是否还关联其它的文件描述符,shotdown都会关闭套接字通道。

如sockfd指向一个已连接的流式套接字,执行以下调用,连接依然保持打开,仍然可以通过文件描述符fd2在该连接上做i/o操作。

fd2=dup(sockfd);
close(sockfd);

但如果执行以下调用,那么连接的双向通道都会关闭,通过fd2无法执行i/o操作.

fd2=dup(sockfd);
shutdown(sockfd,SHUT_RDWR);

如果套接字文件描述符fork()被复制,如果fork()后,一个进程在描述符副本上执行SHUT_RDWR操作,那么其它进程都无法在这个文件描述符上执行i/o操作了。

需要注意的是,shutdown并不会关闭文件描述符,要关闭文件描述符,还需调用clsoe。

TCP_CORK套接字选项

HTTP中使用sendfile()发送文件,为提供带宽利用率,可使用TCP_CORK将HTTP首部给缓冲,与数据报文合并为一个报文。

int optval =1
setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval);
write(sockfd, ...); //write http headers
sendfile(sockfd,...); // send data
optval =0
setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &optval, sizeof(optval));

TIME_WAIT状态

TIME_WAIT状态值出现在执行主动关闭的一端,迁移到CLOSED状态需要2MSL(报文最大生存时间)。MSL是IP报文在吃过TTL限制前可在网络中生存的最大估计时间。

Linux中TIME_WAIT将持续60s。

目的:

1.实现可靠的连接终止

如果最后发送的ACK丢失了,等待2MSL可以重新发送最后ACK;而如果主动关闭的一方不存在了,TCP协议将发送RST报文(RST会被解释为错误)

2.让老的重复的报文段在网络中过期失效,这样建立新的连接时将不再接受它们

当有TCP节点处于TIME_WAIT状态时是无法通过同样的IP和端口号重新建立新的连接的。SO_REUSEADDR选项可用来避免会遇到EADDRINUSE错误,同时仍然允许TIME_WAIT状态提供可靠性保证。

带外数据

send()和recv()需要制定MSG_OOB标志,当套接字接受到带外数据通知时,内核为套接字属主(通常为使用该套接字的进程)生成SIGURG信号。

带外数据是TCP套接字的一种特性,允许发送端将传送的数据标记为高优先级。TCP通过URG标志位来标示有紧急(带外)数据,并将紧急指针指向紧急数据,但TCP没有执行紧急数据长度,因此认为紧急数据只由一个字节组成。telnet,ftp等,都利用该特性来终止之前传送的命令。

s.send("hello",socket.MSG_OOB)

c.recv(100,socket.MSG_OOB) // "o"
c.recv(100) // "hell"

分散聚合IO

readv和writev可以一次系统调用读写多个非连续缓冲区

#include <sys/uio.h>
ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt)
struct iovec{
void *iov_base; //buffer
size_t iov_len; //size of buffer
}

I/O多路复用,信号驱动,epoll

水平触发通知:

如果文件描述法上可以非阻塞的执行I/O系统调用,此时认为它已经就绪。所以每次不需要读取很多数据,多个描述符读取平衡。

边缘触发通知:

如果文件描述符自上次状态检查以来有了新的I/O活动,此时触发通知。由于只有新状态才通知,所以一次需要读取所有数据,不然会导致数据丢失,会导致其他描述符处于饥饿状态。

I/O模式 水平触发 边缘触发
select,poll yes
信号驱动I/O yes
epoll yes yes

select

#include <sys/time.h>
#incldue <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timevel *timeout)
 返回就绪(3个集合)的描述符数量,0 超时,-1 错误

exceptfds一般只会在下面两种情况发生:

1.连接到信包模式下的伪终端主设备上的从设备状态发生改变

2.tcp套接字接收到了带外数据

nfds是集合中最大文件描述符+1,目的是让select变得更有效率,内核不用检查大于这个值的描述符是否属于这个集合。

eopll

max_user_watches:每个用户可以注册到epoll实例上的文件描述符总数(/proc/sys/fs/epoll/max_user_watches,默认的上学值是根据系统可用内存计算)

可以研究研究https://github.com/cloudwu/socket-server,以及tornado源码,这两个都是水平触发的,边缘触发的可以研究nginx或golang,当然nginx更适合。

典型异步I/O读写:

int sz = write(fd, buffer, sz);
if (sz < 0) {
    switch(errno) {
    case EINTR:
        continue;
    case EAGAIN:
        return -1;
}

int n = read(fd, buffer, sz);
if (n<0) {
    switch(errno) {
    case EINTR:
        break;
    case EAGAIN:
        fprintf(stderr, "socket-server: EAGAIN capture.\n");
        break;
    default:
        // close when error
        return SOCKET_ERROR;
    }
    return -1;
}

配置参数

  1. 系统限制 /etc/sysctl.conf

    来自gopush群的分享

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.msgmnb = 1048576
kernel.msgmax = 1048576
kernel.shmmax = 68719476736
kernek.shmall = 4294967296
fs.file-max = 1048576
kernel.pid_max = 1048576
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_timestsmps = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_wmem = 4096 4096 1677216
net.ipv4.tcp_rmen = 4096 4096 1677216
net.ipv4.tcp_mem = 94500000 91500000 92700000
net.ipv4.tcp_max_orphans = 3276800
net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
vm.overcommit_memory = 1
  1. 登陆用户限制 /etc/security/limits.conf

    soft是警告设置,hard是阀值(鸟哥私房菜)

* soft nofile 150000
* hard nofile 150000

如果不管可直接用ulimit -n 10000设置

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 07-19

Linux/Unix系统编程手册--SOCKET章节读书笔记的相关文章

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software

《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候都会发生缓冲.通过缓冲可以在一定程度上将用户空间与实际的物理设备分离,还可以减少内核访问磁盘的次数. 先来看看关于内核缓冲区高速缓冲:read和write调用在对磁盘文件进行操作的时候不会直接访问磁盘,如下图所示. 例如:write(fd, "abc", 3) write调用会将"

《Linux/Unix系统编程手册》读书笔记9(文件属性)

<Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有更深入的研究一定会写出来. 下图为磁盘分区与文件系统的关系 文件系统中的文件(目录)在i-node表上都有唯一的记录(i-node).i-node通过数据块指针指向数据块,这些数据块就是该i-node对应的文件的数据. i-node与数据块的关系如下: 因为Linux支持很多类型的文件系统,但是每种文件系统的

Linux/UNIX系统编程手册 PDF下载

网盘下载地址:Linux/UNIX系统编程手册 PDF下载 – 易分享电子书PDF资源网 作者: Michael Kerrisk 出版社: 人民邮电出版社 原作名: The Linux Programming Interface: A Linux and UNIX System Programming Handbook 译者: 孙剑 许从年 董健 / 孙余强 郭光伟 陈舸 出版年: 2014-1 页数: 1176 定价: 158 装帧: 平装 内容简介 · · · · · · <linux/un

Linux/UNIX系统编程手册 练习3.8

闲来无聊看了看  3-1. 使用Linux专有的reboot系统调用重启系统时,必须将第二个参数magic2定义为一组magic号(例如:LINNUX_REBOOT_MAGIC2).这些号有何意义?(将magic号转换为十六进制数,对解题会有所帮助.) 刚看的时候 有点晕就去查了查 转换成16进制了 . 结果发现 是彩蛋.... 原文地址:https://www.cnblogs.com/jingchu/p/10262241.html

linux/unix系统编程手册源码编译

我的操作,我在官网下载 书本源代码 ,在windows 解压后 ftp工具 传到 linux虚拟机 然后 make 发现 报错 如: No rule to make target `../libtlpi.a', needed by 郁闷好久! 方案: 把源代码压缩包 ftp到虚拟机 在解压缩,make 就成功了! 注意,习惯: 永远在linux解压缩

TLPI(liunx/unix系统编程手册)初读笔记

当然我只是记录一下我初读这本书的想法和我自己不懂该记下的地方,其他的地方就不一一论述,全部记下来就没有意思了. 若有什么错误,望大家指出,谢谢~希望有评论~ ------------------------------------------------------------------ 前言就是明确的介绍书的目的编程标准等等..source code在http://man7.org/大家可以去参阅 一章介绍POSIX标准和一些历史发展. 二章开始介绍基本概念: 讲到了内核的功能:1.提供了文

TLPI(liunx/unix系统编程手册)笔记(四) 深入探究文件I/O

本章的重点我想就是原子操作,避免在几个进程在打开同一文件的时候造成的错误,了解一下时间片的概念会对本章有所帮助. (1)独占方式打开文件.(open     <-O_CREAT) 知道,open,可以创建文件并返回fd.当我们的进程运行到open这个函数时间片到了,另一个进程也对这个路径的文件open,那么时间片结束后两个进程都会认为自己是这个文件的拥有者.并未是独占创建打开的.在open 函数的第二个参数中有 O_EXCL 这种打开方式,可以解决独占的问题.另外可以在多进程对一个文件写的时候,

TLPI(liunx/unix系统编程手册)笔记(三) 文件IO:通用的IO模型

读下来总的就是介绍了四个IO的API--open,read,write,close. 大家都是知道的,everything is file,在linux系统里面一切都是看作文件来操作的,学习linux就得先学好文件IO,也可以看见TLPI这本书的介绍完一些概念之后就开始介绍文件IO了. IO,大概的分为磁盘文件IO,buffering(缓冲)IO.貌似缓冲的水很深,之后会写博客. ------------------------------------ (1)文件描述符. 在进行IO操作之前,总