Ⅰ c语言 阻塞,非阻塞和多线程有什么关系
阻塞是在传统的网络编程中我们依赖于ServerSocket,Socket进行通信,大致的框架就是ServerSocket调用accept方法,等待客户端的连接,如果连接进来的时候则创建一个服务器端socket,客户端和服务器端socket建立好InputStream 和outputStream通道进行通信,在这个网络IO的过程中inputStream的read 和outputStream的write方法都可能发送阻塞。为了减少这种阻塞对其他连接的影响,一般都会在服务器端为每个连接开辟一个新的线程,或者使用线程池技术来避免线程的创建销毁同时又一定程度支持并发量。然而这种情况下,如果发生大量的read 或者write阻塞线程池的效率会大大降低,而且操作系统也额外需要频繁的处理cpu的切换。
非阻塞式通信实际是对上述模式的扩展,它的核心思想是为传统的socket加入事件监听的功能,操作系统可以在socket和serversocket上进行事件监听,一旦监听的对象发生了连接和可读可写的事件,监听器就会对注册了事件的对象返回相应的通知。在javaNIO中实现这一套的机制就是把socket 和ServerSocket重写成为SocketChanel,ServerSocketChanel,他们的底层仍然使用socket实现,所以原则上javaNIO包可以完全实现阻塞和非阻塞两种编程模式。事件监听的功能由Selection类完成,他使用select方法一直阻塞式监听注册了的事件是否发生,对于每一个发生的事件,他都会返回一个selectionKey,通过这个key我们就可以确定这个事件的发生源(socket)和相关信息。对于ServerSocketChanel,Socketchanel分别对应了不同的事件,serverChanel只有OP_ACCEPT代表是否可以接受连接,而socketChanel则有OP_CONNECT、read、write事件。笔者认为与阻塞IO相比他的优势在于可以避免read 和write的阻塞,因为这个比较具有实际意义的。比如是一个网络文件传输系统,read方法可能会因为网络原因发生多次阻塞,使用非阻塞IO read的话线程可以立即返回去处理其他任务。
多线程是在进程中进一步去划分的独立单元。
Ⅱ c语言的recv()非阻塞方法怎么弄哦
需要将recv设置超时,Linux下设置超时如下:
//设置发送超时
struct timeval timeout={3,0};//3s
setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(struct timeval));
//设置接收超时
setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval));
windows下设置超时如下:
int timeout = 3000; //3s
int ret=setsockopt(sock_fd,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
int ret=setsockopt(sock_fd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
Ⅲ C语言阻塞、非阻塞和多线程有什么关系
这个问题我知道!说到阻塞和非阻塞的概念,就要了解同步和异步的概念吧同步:多个线程可以同时访问同一个资源。比如对一个变量而言,线程们可以同时对他进行读写。使用场景:多个线程同时访问一块数据,也叫共享区。对于多个线程同时访问一块数据的时候,必须使用同步,否则可能会出现不安全的情况。比如数据库中的脏读。但是,多个线程同时访问一块数据,有一种情况不需要同步技术,那就是原子操作,也就是说操作系统在底层保证了操作要么全部做完,要么不做。异步:使用场景:只有一个线程访问当前的数据。比如,观察者模式,没有共享区,主题发生变化,通知观察者更新,主题继续做自己的事情,不需要等待观察者更新完成后再工作。同步分为阻塞IO和异步IO异步可以分为阻塞IO和非阻塞的IO异步阻塞IO通过select和epoll实现
Ⅳ C语言Socket通信 非阻塞问题 谁能帮我解释解释这段代码呀
非堵塞通信,可以使用MFC的CAsyncSocket类。
Ⅳ windows下C语言非阻塞方式读取键盘缓冲区
有所不同。服务器是网络的节点,存储、处理网络上80%的数据、信息,在网络中起到举足轻重的作用。它们是为客户端计算机提供各种服务的高性能的计算机,其高性能主要表高速度的运算能力、长时间的可靠运行、强大的外部数据吞吐能力等方面。服务器的构成与普通电脑类似,
Ⅵ c语言中select函数的作用
在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在这里,无法执行下面的代码。这是就需要用到非阻塞的编程方式,使用selcet函数就可以实现非阻塞编程。
selcet函数是一个轮循函数,即当循环询问文件节点,可设置超时时间,超时时间到了就跳过代码继续往下执行。
Select的函数格式:
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*timeout);
select函数有5个参数
第一个是所有文件节点的最大值加1,如果我有三个文件节点1、4、6,那第一个参数就为7(6+1)
第二个是可读文件节点集,类型为fd_set。通过FD_ZERO(&readfd);初始化节点集;然后通过FD_SET(fd, &readfd);把需要监听是否可读的节点加入节点集
第三个是可写文件节点集中,类型为fd_set。操作方法和第二个参数一样。
第四个参数是检查节点错误集。
第五个参数是超时参数,类型为struct timeval,然后可以设置超时时间,分别可设置秒timeout.tv_sec和微秒timeout.tv_usec。
然后调用select函数,用FD_ISSET()函数判断节点是否可读写。返回值不为0表示可读写,为0表示不可读写。select函数的返回值为是一个整数,表示有几个节点可读写。
先说明两个结构体:
第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来操作,比如清空集合FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set*),将一个给定的文件描述符从集合中删除FD_CLR(int,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。
第二,struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。
具体解释select的参数:
int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。
fd_set * readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。
fd_set * writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。
fd_set * errorfds同上面两个参数的意图,用来监视文件错误异常。
struct timeval * timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
返回值:返回状态发生变化的描述符总数。
负值:select错误
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
Ⅶ c语言中非阻塞单线程输入循环怎么做
继承Thread类,须重写父类的run()方法,另一种:实现Runnable接口,也是实现run()方法。run() 方法很重要,是当你新建一个线程,运行时的核心,注意,你不要自己去调用run()方法,如果你自己调用,就只是你写那行调用代码,运行那行代码的线程在执行该方法,而不是你新建线程执行的。这一点,也是我之前多线程编程常混乱的。
说到这,如何新建一个线程呢?很简单: Thread newThread = new Thread( 参数) ; 构造方法中的参数,为前面两种之前的实现类的一个实例。那么当你调用了: newThread.start()方法后,就新启动了一个线程,那么当该线程执行了run(),即参数中实例的run()方法,就是该线程执行的主体。
注意: 一个线程执行的主体run()方法,是不需要你显示调用的。
Ⅷ C语言如何在子线程中等待输入的同时(scanf或者getchar等等之类的输入),不阻塞其他线程去进行输出
要用_kbhit()函数, 非阻塞
//direct代表方向:0-向右,1-向下,2-向左,3-向上
while(1)
{
if(_kbhit())//如果按下的是方向键或功能键,_getch()要调用两次,第一次返回0XE0或0
{
c=_getch();//上:72下:80左:75右:77
if(c==0XE0||c==0) c=_getch();
if(c==72&&(direct!=1||direct!=3))
{
direct=3;
}
elseif(c==80&&(direct!=1||direct!=3))
{
direct=1;
}
elseif(c==75&&(direct!=0||direct!=2))
{
direct=2;
}
elseif(c==77&&(direct!=0||direct!=2))
{
direct=0;
}
}
}
Ⅸ udp非阻塞怎么写 linuxc语言
int flag=fcntl(fd,F_GETFL,0); flag |= O_NONBLOCK; if(fcntl(fd,F_SETFL,flag) < 0){ perror("fcntl"); exit(1); }
Ⅹ C语言如何让程序一直不断运行直到按了某个键以后停止,代码怎么写
可以参考下面的代码:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
main( )
{
int p;
while( ! _kbhit() ) {
// run progs
_cputs( "Please hit me ! " );
Sleep(500);
}
return 0;
}
(10)c语言非阻塞编程扩展阅读:
kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件。
函数名:kbhit()
功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。
用 法:int kbhit(void);
C++语言包含头文件: include <conio.h>。
C语言不需包含额外头文件。
在VC++6.0下为_kbhit()
功能及返回值同上。