在《unp》书上,stevent一开始的一个服务器小例子这样介绍到:一个TCP的服务器和客户
端,客户端puts进行阻塞式的输入消息。暴露的问题是,当用户进行阻塞到puts输入时,对方
的服务器关闭,那么用户可能发了一大断消息按下发送时,发现程序崩溃了。。阻塞的出现的
另一种意义就是各司职。 最近在负责的一个项目中,需要频繁的进行TCP吞吐,我一时认为不
需要什么阻塞,都是即时的消息,而且又很频繁。结果暴露的问题出来了:(9060为服务端)
1、如
tcp 0 16385 218.66.25.238:32821 218.66.25.238:9060 FIN_WAIT1
tcp 60416 0 218.66.25.238:9060 218.66.25.238:32821 ESTABLISHED
tcp 0 36 218.66.25.238:22 218.66.25.222:1874 ESTABLISHED
tcp 0 0 218.66.25.238:32821 218.66.25.238:9060 TIME_WAIT
哦是的,我卡住了。我在发送数据的时候阻塞了。而且当我我把客户端关闭时,发送第一个
TCP FIN后,客户端状态为FIN_WAIT1,这时我期待着对方的返回。(TCP SYS 和 socket fin)
可是,看到60416了吗,服务器的缓冲区满了。我不得不等到服务套接字将他们都取完后才结
束。但是这个阻塞影响了我一些线程方面的判断。或许你会说, 谁叫你把recv和send设置得
不一样。这个我承认,但是你也得考虑到,万一网速不那么顺畅,可能会造成一方发送较快,
导致在缓冲区里累计一些包,长久以后,程序必然崩溃;当然还包括当你机器繁忙时,recv和
send执行得也许不那么顺利呢?这些都是隐患。
所以考虑下,决定用select执行。代码如下:
int CCreateTCP_UDP::Writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = (const char*)vptr;
nleft = n;
while (nleft > 0)
{
if ( (nwritten = write(fd, ptr, nleft)) <= 0)
{
if (errno == EINTR)
nwritten = 0; /* and call write() again
*/
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
int CCreateTCP_UDP::WritenUBlock(int fd, const void *vptr, size_t n)
{
fd_set set_write;
timeval time_out;
FD_ZERO(&set_write);
FD_SET(fd, &set_write);
time_out.tv_sec=time_out.tv_usec=3; //可能会被改变
if( select(fd+1, NULL, &set_write, NULL, &time_out)==-1 )
{
return -1;
}
/*select可能返回>0的数,为了防止0套接字,进行个判断
所以这里要注意保持收和发的平衡性
尽量减少缓冲区的饱和
*/
if( FD_ISSET(fd, &set_write) )
{
/*为了防止数据上的一些连包,返回错误重新处理*/
if( Writen( fd, vptr, n )!=n)
{
return -1;
}
}
/*成功的话,理所当然返回发送的字节数,不过既然能通过!=n,
就简单的以统一的0表示成功*/
return 0;
}
一些代码是照抄《unp》上的。
这里做点解释:在WritenUBlock这个函数里,首先将套接字放入FD_SET的类型,接着用select
查询。用select我们当然希望它当套接字可以用时告诉我们。
可以有如下几个情况(总结的不是很完全)
1 当缓冲区中的数据满足读的条件(比如你的套接字至少要10个字节,而这时候缓冲区中的数
据长度满足)
2 当socket发生错误时。这里大家可能不明白,为什么要socket发生错误时。很好理解,当我
们用一个套接字时,最希望的是当它可以用的时候告诉我们,起码使用它时不会崩溃。既然这
样的话,发生错误是不是也在我们范围之内呢?
错误有两种,
一是1;这表示发生了一个调用错误,要和普通的数据接收错误分开,这是一个函数的调用错误
二是0;很不幸,这表示它读到了一个EOF字符。表示对方要跟你断开了,这里细节如下:当对
方进程结束或者调用close,对方的TCP首先发送一个FIN,我方回复这个FIN,接着我方的TCP向
这个套接字的缓冲区送一个EOF,等带着套接字调用,当我方套接字收到这个0,就发送一个
socket的FIN,对方接着回复这个FIN。一环扣着一环,具体见我上一篇BLOG,《time_wait状
态的解释和验证》。
这就是今天我对阻塞和非阻塞的一点认识,当然对select的工作系统还不熟悉,只是初步的使
用
分享到:
相关推荐
socket_recv 函数使用心得 在学习 socket_recv 函数时,需要了解其返回值的含义和使用场景。在阻塞模式下,当网络异常时,recv 函数返回值为-1,表示连接异常,需要关闭连接。在非阻塞模式下,如果没有数据,recv ...
6. **易于使用和扩展**:Netty 的 API 设计简洁,方便开发者理解和使用,同时提供了丰富的扩展点,允许自定义各种组件以满足特定需求。 在 Netty 实战中,我们通常会遇到以下场景: 1. **创建服务器**:通过 ...
其中,绑定变量和非阻塞读是两个非常重要的概念,对于提高Oracle应用程序的性能和稳定性具有重要意义。通过对这些知识点的学习和实践,开发者可以更好地利用Oracle的强大功能,构建高效稳定的数据库应用。
然而,always块中的敏感列表和非阻塞赋值()用于描述顺序行为,这是理解和调试Verilog设计的关键。 5. **状态机设计**:状态机是Verilog中常见的一种设计模式,用于控制系统的流程。学会如何用Verilog描述Mealy型...
在Linux系统中,设备驱动程序是内核的一部分,它们使得操作系统能够高效地管理和使用各种硬件资源。 "Linux设备驱动程序学习心得"主要围绕着"LDD3",即《Linux Device Drivers》第三版这本书展开。LDD3是一本经典的...
* I/O 模型:使用非阻塞 I/O 模型,基于 I/O 复用模型,使用 Selector 对象对多路复用器进行管理 * 线程处理模型:使用 NioEventLoop 线程池,聚合了多路复用器 Selector,可以同时并发处理成百上千个客户端连接 ...
4. **IO与NIO**:了解输入/输出流的使用,以及Java NIO(非阻塞I/O)的优势和应用场景。 5. **多线程**:学习如何创建和管理线程,理解线程同步与通信,如synchronized关键字、wait()和notify()方法等。 6. **反射...
Java的IO流模型处理输入输出操作,NIO则提供了非阻塞I/O操作,适用于高并发场景。此外,多线程编程也是Java的一大特色,线程同步和互斥的机制,如synchronized关键字和Lock接口,能够帮助开发者构建高效的并发程序。...
- **优先考虑非阻塞算法**:在可能的情况下,使用非阻塞算法可以提高程序的效率。 - **正确处理异常**:在多线程环境中,正确处理异常尤为重要,因为异常可能会导致线程挂起或资源泄漏等问题。 - **避免过度使用线程...
8. **数据流与管道**:在处理大量数据时,可以利用MATLAB的流数据处理功能,例如使用`readasync`和`writeasync`函数实现数据的非阻塞读写,以连续、高效的方式传递和处理大数据。 9. **内存管理与性能优化**:理解...
在本文档中,我们探讨了15个对软件工程师尤其是jQuery开发者至关重要的技巧和心得,旨在帮助他们提高代码效率和性能。以下是对这些技巧的详细解释: 1. **使用最新版本的jQuery库**:更新到最新版本的jQuery是提高...
深入学习GC的工作原理,包括分代收集、可达性分析、各种GC算法(如Serial、Parallel、CMS、G1、ZGC等),可以帮助优化内存使用和避免内存泄漏。 3. **并发与多线程**:Java提供了丰富的并发API,如synchronized、...
NIO(New IO)提供非阻塞I/O操作,提高了效率。 10. **线程**:Java内置对多线程的支持,通过Thread类或实现Runnable接口创建线程。线程同步机制(如synchronized关键字、wait(), notify(), notifyAll()方法)防止...
1. 基于事件机制: Node.js 是一个基于事件机制的框架, Node.js 部分的模块都继承自 Event 模块,实现了简单的事件模式的实现,将常见且成熟的技术引入到后端,实现和异步非阻塞 I/O 的配合。 2. 异步非阻塞 I/O:...
4. **操作系统**:理解进程与线程的概念,掌握同步与互斥机制(如信号量、锁、条件变量),了解内存管理(虚拟内存、内存分配与释放)和I/O模型(同步异步、阻塞非阻塞)。 5. **计算机网络**:理解TCP/IP五层模型...
此外,它还体现了在嵌入式系统中优化资源使用的重要性,如通过中断服务程序实现非阻塞式的数据处理,以及在低功耗设备上进行有效的电源管理。对于其他类似应用,开发者可以借鉴这种方法,根据实际需求调整阈值和处理...
Oracle数据库是全球广泛使用的大型企业级数据库管理系统,其性能优化和设计原则对于任何IT专业人员来说都是至关重要的。本文将围绕“ORACLE学习心得”展开,深入探讨Oracle数据库的优化策略、并发控制、数据库设计...