linux socket缓冲区 linux如何弄全局代理
大家好,今天给各位分享linux socket缓冲区的一些知识,其中也会对linux如何弄全局代理进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!
修改linux系统socket缓冲区大小
进行socket编程有时候可能需要修改下socket的接收缓冲区大小,这里可以使用 setsockopt函数,但是如果需要修改的缓冲区很大(比如500MB),则还需要修改系统内核的TCP/IP参数,不然接收缓冲区大小会收到内核参数的限制,所以需要改两个地方。下面以把socket接收缓冲区修改为500MB说明一下要作的修改。《Linux就该这么学》
修改内核TCP/IP参数
在终端用sysctl命令修改socket最大缓冲区限制:
sudo sysctl-w net.core.rmem_max=5242880001
在代码中用setsockopt函数修改SO_RCVBUF选项
int recvbuff= 500*1024*1024;
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,(const char*)&recvbuff, sizeof(int))==-1)
printf("setsocket error\n");
else
printf("setsocket success\n");12345
以上两点,只改第1点,一个socket只会预留63个报文的接收缓冲;只改第2点,缓冲区大小会受到rmem_max的限制,如果需要的缓冲区很大的话,必须两点都改。
socket套接字及缓冲区详解(一篇搞定~)
一、域(domain)
域指明套接字通信所使用的网络介质。常见的是AF_INET(IPv4)或AF_INET6(IPv6),代表Internet网络。这类网络多用于Linux局域网和因特网。
二、类型(type)
流套接字(SOCK_STREAM):
流套接字提供面向连接且可靠的传输服务。它确保无差错、无重复、按序数据传输,通过使用TCP协议实现。
数据报套接字(SOCK_DGRAM):
数据报套接字提供无连接服务,不保证数据传输的可靠性,数据可能丢失或重复,且接收顺序不确定。它使用UDP协议传输数据。
原始套接字(SOCK_RAW):
原始套接字与标准套接字不同,它能读取内核未处理的IP数据包。标准套接字仅能读取TCP或UDP协议的数据。因此,访问其他协议需使用原始套接字。
三、协议(protocol)
协议用于指定通信协议,如使用默认协议(0)、TCP(IPPROTO_TCP)或UDP(IPPROTO_UDP)。
四、socket缓冲区以及阻塞模式
1、缓冲区简介
每个socket创建后,分配输入与输出缓冲区。write()/send()先将数据写入缓冲区,TCP协议负责发送至目标机器。read()/recv()从缓冲区读取数据。
2、使用write()/send()发送数据
【阻塞模式下】:
检查缓冲区,空间不足时阻塞,直至数据发送完毕或缓冲区空间足够。如果TCP发送数据,输出缓冲区锁定,直至解锁才允许写入。
【非阻塞模式下】:
数据拷贝至缓冲区,缓冲区空间不足时返回成功拷贝大小。若为0,返回-1并设置errno为EAGAIN。
3、使用read()/recv()读取数据
【阻塞模式下】:
检查缓冲区,有数据则读取,无数据阻塞直至数据到达。
【非阻塞模式下】:
接收数据时可能遇到“Resource temporarilyunavailable”错误,返回EAGAIN。此错误不影响同步,循环recv继续。
五、面试题:TCP服务端一直sleep,客户端发送数据问题
1、TCP发送数据过程:
TCP确保按序、无差错接收数据。服务端sleep不接收数据,客户端持续write,输入缓冲区和输出缓冲区最终会满,write无法继续。
2、阻塞方式:
服务端sleep,客户端write导致数据积压,直至缓冲区满或数据发送完毕。
3、非阻塞方式:
服务端sleep,客户端write返回-1并设置errno为EWOULDBLOCK,表示缓冲区空间不足。
总结,套接字是不同主机间进程通信的约定,通过特定的域、类型和协议定义。缓冲区管理数据传输,阻塞或非阻塞模式控制I/O操作。理解这些概念有助于解决网络编程中的问题。
Linux如何清空Socket缓冲区
还有就是用recv读取,但是由于不知道缓存里有多少数据,如果是阻塞模式,到最后必然等到超时才知道数据已经读取完毕,这是个问题。另一个是用fgetc,通过返回判断是否是feof:
whlie(1){ a=fgetc(f);if(feof(f)) break;//
b=fgetc(f);if(feof(f)) break;//}当然,我不知道读取完毕后最后一次调用fgetc会不会堵塞,需要测试。在非阻塞模式下,我们用recv就可以轻松搞定了,但是阻塞模式下,由于我们不知道缓冲区有多少数据,不能直接调用recv尝试清除。使用一个小小的技巧,利用select函数,我们可以轻松搞定这个问题:
select函数用于监视一个文件描述符集合,如果集合中的描述符没有变化,则一直阻塞在这里,直到超时时间到达;在超时时间内,一旦某个描述符触发了你所关心的事件,select立即返回,通过检索文件描述符集合处理相应事件;select函数出错则返回小于零的值,如果有事件触发,则返回触发事件的描述符个数;如果超时,返回0,即没有数据可读。重点在于:我们可以用select的超时特性,将超时时间设置为0,通过检测select的返回值,就可以判断缓冲是否被清空。通过这个技巧,使一个阻塞的socket成了‘非阻塞’socket.现在就可以得出解决方案了:使用select函数来监视要清空的socket描述符,并把超时时间设置为0,每次读取一个字节然后丢弃(或者按照业务需要进行处理,随你便了),一旦select返回0,说明缓冲区没数据了(超时了)。
struct timeval tmOut;tmOut.tv_sec= 0;tmOut.tv_usec= 0;fd_set fds;FD_ZEROS(&fds);FD_SET(skt,&fds);
int nRet;
char tmp[2];
memset(tmp, 0, sizeof(tmp));
while(1){ nRet= select(FD_SETSIZE,&fds, NULL, NULL,&tmOut);if(nRet== 0) break;recv(skt, tmp, 1,0);}这种方式的好处是,不再需要用recv、recvfrom等阻塞函数直接去读取,而是使用select,利用其超时特性检测缓冲区是否为空来判断是否有数据,有数据时才调用recv进行清除。有人说同样可以用recv和socket的超时设置去清空啊,这个没错,但是你需要直接对socket描述符设置超时时间,而为了清空数据而直接修改socket描述符的属性,可能会影响到其他地方的使用,造成系统奇奇怪怪的问题,所以,不推荐使用。