【发布时间】:2021-02-16 19:17:58
【问题描述】:
客户端连接服务器后,服务器端的输入会被阻塞,直到客户端断开连接。这是终端缓冲区中的阻塞数据吗? 如果输入数据大于终端的缓冲区会怎样?
tcp 栈中有一个类似的缓冲区。当应用程序不处理缓冲区中的数据时,tcp 会调整窗口大小,使发送方不再发送数据。终端有这样的机制吗?
是否每个 Linux fd 都有这样的缓冲区?缓冲区的大小是由实现决定的吗?
void echo(const clientinfo &ci){
size_t n;
char buff[MAXLEN];
rio_t rio;
Rio_readinitb(&rio,ci.fd);
while((n = Rio_readlineb(&rio,buff,MAXLEN)) != 0){
std::cout << "server received " << n << " bytes from "<< ci.client_hostname << " port " <<ci.client_port <<std::endl;
std::cout << buff;
Rio_writen(ci.fd,buff,n);
}
}
void command(){
char buf[MAXLEN];
if(!fgets(buf,MAXLEN,stdin))
return;
std::cout << buf;
}
int main(int argc,char **argv){
int listenfd,connfd;
socklen_t clientlen;
sockaddr_storage clientaddr;
fd_set read_set,ready_set;
clientinfo ci;
if(argc != 2){
std::cerr << "usage: " << argv[0] << " <port>" << std::endl;
exit(0);
}
listenfd = open_listenfd(argv[1]);
FD_ZERO(&read_set);
FD_SET(STDIN_FILENO,&read_set);
FD_SET(listenfd,&read_set);
while(1){
ready_set = read_set;
if(select(listenfd+1,&ready_set,NULL,NULL,NULL) < 0)
unix_error("select error");
if(FD_ISSET(STDIN_FILENO,&ready_set))
command();
if(FD_ISSET(listenfd,&ready_set)){
clientlen = sizeof(sockaddr_storage);
ci.fd = accept(listenfd,(sockaddr*)&clientaddr,&clientlen);
getnameinfo((sockaddr*)&clientaddr,clientlen,ci.client_hostname,MAXLEN,ci.client_port,MAXLEN,0);
std::cout << "connect from " << ci.client_hostname << " port " << ci.client_port <<std::endl;
echo(ci);
close(ci.fd);
}
}
}
【问题讨论】:
-
文件描述符没有缓冲区。像 C 库这样的库提供缓冲区。
-
是的,但是每个 fd 都有一个与之关联的缓冲区
-
如果你知道,为什么还要问?
-
不知道我的理解是否正确
-
取决于驱动程序。串行端口通常在硬件中缓冲 8 或 16 个字符。一些实时音频代码不会缓冲以避免延迟。网络设备可能有相当大的数据包缓冲区。所以不能保证所有的 fd 都有缓冲区。
标签: linux io linux-kernel