这是在windows下面的定义。在linux下面的定义只是将SOCKET改成int,那么在linux下面的原型是这样:
在Linux网络编程中,常常使用select和poll来做事件触发,监听socket的读写状态,然后进行读写操作。现在新的linux内核中,增加了epoll事件触发机制,具有更高的性能和更好的设计理念,可以用它来完全代替select和poll。相比于select,epoll最大的好处在于它不会随监听fd数目的增长而降低效率。因为在内核总的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多。并且,在linux/posix_types.h头文件中有这样的声明: [cpp] view pl
前一段时间研究了大规模日志流高吞吐并行存储,通过深入研究Kafka的底层存储机制。我们发现Kafka的Zero-Copy零拷贝技术采用的是Java底层FileTransferTo方法,后期我们尝试了对TransferTo性能及其并行性能进行测试。以及后面在Kafka上面实现了并行TransferTo方法,并应有到了Apache Kafka系统中。
本文将从上层介绍Linux上的TCP/IP栈是如何工作的,特别是socket系统调用和内核数据结构的交互、内核和实际网络的交互。写这篇文章的部分原因是解释监听队列溢出(listen queue overflow)是如何工作的,因为它与我工作中一直在研究的一个问题相关。
用户态进程通过write()系统调用切到内核态将用户进程缓冲区中的HTTP报文数据通过Tcp Process处理程序为HTTP报文添加TcpHeader,并进行CPU copy写入套接字发送缓冲区,每个套接字会分别对应一个Send-Q(发送缓冲区队列)、Recv-Q(接收缓冲区队列),可以通过ss -nt语句获取当前的套接字缓冲区的状态;
从套接字上接收一个消息。对于recvfrom,可同时应用于面向连接的和无连接的套接字。recv一般只用在面向连接的套接字,几乎等同于recvfrom,只要将recvfrom的第五个参数设置NULL。
基本操作就是循环的从磁盘读入文件内容到缓冲区,再将缓冲区的内容发送到socket。但是由于Linux的I/O操作默认是缓冲I/O。这里面主要使用的也就是read和write两个系统调用,我们并不知道操作系统在其中做了什么。实际上在以上I/O操作中,发生了多次的数据拷贝。
参数释义: sock:网络文件描述符 level:选项所在协议层。 如果想要在套接字层面上进行配置,则将此项设置为SOL_SOCKET。 optname:需要访问的选项名 (后面会有)(取决于level) optval:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。 optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。
水平触发:socket的接收缓冲区里有数据来了,只要缓冲里有数据,select、poll或者epoll就都会一直收到通知
有时候我们要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要控制套接字的选项了. 以下资料均从网上收集得到 getsockopt 和 setsockopt 获得套接口选项:
lrs_get_socket_handler 获取指定套接字的套接字处理程序
进程间通信(IPC,Inter-Process Communication),指至少两个进程或线程间传送数据或信号的一些技术或方法。
int setsockopt( SOCKET s, int level, int optname, const char* optval, int optlen );
在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:
"狼哥,面试又跪了,碰到了知识盲区" "哪个?" "一面还可以,二面面试官问我零拷贝的原理,懵逼了...这块内容没去研究过" "哦,这个知识点,我之前应该有讲过,你没注意到?" "这东西工作中用不到,可能被我忽略了" "啧啧啧..." "哎,有空和我讲讲?"
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)
最近,有小伙伴在群里提问:Linux系统怎么设置tcp_nodelay参数?也有小伙伴说问我。那今天,我们就来根据这个问题来聊聊在高并发场景下如何优化服务器的性能这个话题。
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
struct sockaddr :很多网络编程函数的出现早于IPV4协议,为了向前兼容,现在sockaddr都退化成(void *)结构了。 传递一个地址给函数,然后由函数内部再强制类型转换为所需的地址类型。
进程通信: 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
IP地址的作用是表示网络中唯一的一台设备的,也就是说通过IP地址能够找到网络中某台设备。
I/O是计算机的输入输出,通俗一点讲是计算机数据的流动,包括CPU、内存、磁盘、网络、外设的数据流程,是针对不同主体而言的数据的输入和输出。
net.core.netdev_max_backlog = 400000 #该参数决定了,网络设备接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。 net.core.optmem_max = 10000000 #该参数指定了每个套接字所允许的最大缓冲区的大小 net.core.rmem_default = 10000000 #指定了接收套接字缓冲区大小的缺省值(以字节为单位)。 net.core.rmem_max = 10000000 #指定了接收套接字缓冲区大小的最大值(以字节为单位)。 net.core.somaxconn = 100000 #Linux kernel参数,表示socket监听的backlog(监听队列)上限 net.core.wmem_default = 11059200 #定义默认的发送窗口大小;对于更大的 BDP 来说,这个大小也应该更大。 net.core.wmem_max = 11059200 #定义发送窗口的最大大小;对于更大的 BDP 来说,这个大小也应该更大。 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 #严谨模式 1 (推荐) #松散模式 0 net.ipv4.tcp_congestion_control = bic #默认推荐设置是 htcp net.ipv4.tcp_window_scaling = 0 #关闭tcp_window_scaling #启用 RFC 1323 定义的 window scaling;要支持超过 64KB 的窗口,必须启用该值。 net.ipv4.tcp_ecn = 0 #把TCP的直接拥塞通告(tcp_ecn)关掉 net.ipv4.tcp_sack = 1 #关闭tcp_sack #启用有选择的应答(Selective Acknowledgment), #这可以通过有选择地应答乱序接收到的报文来提高性能(这样可以让发送者只发送丢失的报文段); #(对于广域网通信来说)这个选项应该启用,但是这会增加对 CPU 的占用。 net.ipv4.tcp_max_tw_buckets = 10000 #表示系统同时保持TIME_WAIT套接字的最大数量 net.ipv4.tcp_max_syn_backlog = 8192 #表示SYN队列长度,默认1024,改成8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_syncookies = 1 #表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; net.ipv4.tcp_timestamps = 1 #开启TCP时间戳 #以一种比重发超时更精确的方法(请参阅 RFC 1323)来启用对 RTT 的计算;为了实现更好的性能应该启用这个选项。 net.ipv4.tcp_tw_reuse = 1 #表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 #表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout = 10 #表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。 net.ipv4.tcp_keepalive_time = 1800 #表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为30分钟。 net.ipv4.tcp_keepalive_probes = 3 #如果对方不予应答,探测包的发送次数 net.ipv4.tcp_keepalive_intvl = 15 #keepalive探测包的发送间隔 net.ipv4.tcp_mem #确定 TCP 栈应该如何反映内存使用;每个值的单位都是内存页(通常是 4KB)。 #第一个值是内存使用的下限。 #第二个值是内存压力模式开始对缓冲区使用应用压力的上限。 #第三个值是内存上限。在这个层次上可以将报文丢弃,从而减少对内存的使用。对于较大的 BDP 可以增大这些值(但是要记住,其单位是内存页,而不是字节)。 net.ipv4.tcp_rmem #与 tcp_wmem 类似,不过它表示的是为自动调优所使用的接收缓冲区的值。 net.ipv4.tcp_wmem = 30000000 30000000 30000000 #为自动调优定义每个 socket 使用的内存。 #第一个值是为 socket 的发送缓冲区分配的最少字节数。 #第二个值是默认值(该
相关参数仅供参考,具体数值还需要根据机器性能,应用场景等实际情况来做更细微调整。
http://blog.csdn.net/zapldy/article/details/5813984
关于对 Socket 的认识,大致分为下面几个主题,Socket 是什么,Socket 是如何创建的,Socket 是如何连接并收发数据的,Socket 套接字的删除等。
在前一章节中,我们了解了DMA技术在文件传输中的重要性,并简要介绍了零拷贝技术。为了提高文件传输的性能,我们需要减少用户态与内核态之间的上下文切换次数以及内存拷贝次数。本章将深入探讨零拷贝技术的优化方法,让我们一起走进零拷贝的优化之路!
DatagramSocket是对UDP的封装,DatagramSocket本身不维护连接的状态,因为UDP协议面向非连接,所以也不会产生IO流,只是用来发送与接收数据报。在java中数据报使用DatagramPacket来表示,所以最有用的方法是send与receive,表示发送与接收报文。可以使用DatagramSocket来收发数据报,也可以使用DatagramChannel来收发数据。
参考自《VC++深入详解》 这是我在看书时记录下来的东西。 注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与驱动程序建立关系。 此后,应用程序给Socket的数据,由Socket交给驱动程序向网络上发送出去。 计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。 14.1 计算机网络基本知识。 1,最简单
公众号中关于Unix网络编程的1、2章节对基础知识做了铺垫,介绍了建立网络通信的API。然而客户和服务器之间建立通信管道(以下简称Channel)之后,如何管理Channel以及Channel中双向流动的数据才是开发者关注的重点,这构成了所有网络应用(如http服务器,ftp服务器等)的基础,也才真正是Unix网络课程这个分支所涉及的内容。
net.ipv4.ip_local_port_range = 9000 65500
本文实例讲述了php基于websocket搭建简易聊天室实践。分享给大家供大家参考。具体如下:
在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,点击查看。
公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室。于是搜集各种资料看文档、找实例自己也写了个简单的聊天室。
socket() 函数是进行网络编程的基础,它用于创建一个新的套接字(socket)。套接字是网络通信的端点,可以用于在不同计算机之间传输数据。下面是对 socket() 函数的详细解释:
一、 操作系统提供的网络接口 为了能更好的排查网络通信问题,我们需要熟悉操作系统提供的以下网络接口函数,列表如下: 接口函数名称接口函数描述接口函数签名socket创建套接字int socket(int domain, int type, int protocol);connect连接一个服务器地址int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);send发送数据ssiz
socket函数创建一个文件描述符fd,一个fd 对应两个缓冲区,一个输入缓冲区,一个输出缓冲区。 而recv和send函数就是对这两个函数进行操作。
说明:我们已经知道write操作返回成功仅仅能说明数据已经发送到套接字的发送缓冲区,不能代表对端已经成功收到数据,close的默认返回成功也仅仅是成功发出了一个FIN分节,也不代表对端已经确认
int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData);
Linux系统提供给用户用于接收网络IO的系统接口。从套接字上接收一个消息,可同时应用于面向连接和无连接的套接字。
同步Socket的send函数的执行流程,当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲的长度(因为待发送数据是要copy到套接字s的发送缓冲区的,注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里):
服务器的分类和功能种类有很多,但是网络相关的部分, 如网卡、协议栈、Socket 库等功能和客户端却并无二致。
Socket的英文原义是“孔”或“插座”。在编程中,Socket被称做套接字,是网络通信中的一种约定。Socket编程的应用无处不在,我们平时用的QQ、微信、浏览器等程序,都与Socket编程有关。我们平时使用浏览器查资料,这个过程的技术原理是怎样的呢?
本文讲解 Linux 的零拷贝技术,云计算是一门很庞大的技术学科,融合了很多技术,Linux 算是比较基础的技术,所以,学好 Linux 对于云计算的学习会有比较大的帮助。
有些进程需要一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪(也就是说输入已准备好被读取,或者描述符已能承受更多的输出),他就通知进程,这个能力称为I/O复用
领取专属 10元无门槛券
手把手带您无忧上云