linux下怎么实现监听键盘按键

linux下怎么实现监听键盘按键,第1张

在Unix/Linux下,并没有提供int kbhit(void)这个函数。在linux下开发控制台程序时,需要自己编写kbhit()实现的程序了。下面是kbhit在Unix/Linux下的一个实现。用到了一种终端 *** 作库termios。下面是头文件kbhit.h:QUOTE:#ifndef KBHITh#define KBHIThvoid init_keyboard(void)void close_keyboard(void)int kbhit(void)int readch(void)#endif下面式源程序kbhit.c:QUOTE:#include "kbhit.h"#include <stdio.h>#include <termios.h>static struct termios initial_settings, new_settingsstatic int peek_character = -1void init_keyboard(){tcgetattr(0,&initial_settings)new_settings = initial_settingsnew_settings.c_lflag &= ~ICANONnew_settings.c_lflag &= ~ECHOnew_settings.c_lflag &= ~ISIGnew_settings.c_cc[VMIN] = 1new_settings.c_cc[VTIME] = 0tcsetattr(0, TCSANOW, &new_settings)}void close_keyboard(){tcsetattr(0, TCSANOW, &initial_settings)}int kbhit(){unsigned char chint nreadif (peek_character != -1) return 1new_settings.c_cc[VMIN]=0tcsetattr(0, TCSANOW, &new_settings)nread = read(0,&ch,1)new_settings.c_cc[VMIN]=1tcsetattr(0, TCSANOW, &new_settings)if(nread == 1) {peek_character = chreturn 1}return 0}int readch(){char chif(peek_character != -1) {ch = peek_characterpeek_character = -1return ch}read(0,&ch,1)return ch}

1. 设置socket

int oldOption = fcntl(sockfd, F_GETFL)

int newOption = oldOption | O_NONBLOCK

//设置sockfd非阻塞

fcntl(sockfd, F_SETFL, newOption)12345

2. 执行connect

如果返回0,表示连接成功,这种情况一般在本机上连接时会出现(否则怎么可能那么快)

否则,查看error是否等于EINPROGRESS(表明正在进行连接中),如果不等于,则连接失败

int ret = connect(sockfd, (struct sockaddr*)&addr, sizeof(addr))

if(ret == 0)

{

//连接成功

fcntl(sockfd, F_SETFL, oldOption)

return sockfd

}

else if(errno != EINPROGRESS)

{

//连接没有立即返回,此时errno若不是EINPROGRESS,表明错误

perror("connect error != EINPROGRESS")

return -1

}12345678910111213141516

3. 使用select,如果没用过select可以去看看

用select对socket的读写进行监听

那么监听结果有四种可能

1. 可写(当连接成功后,sockfd就会处于可写状态,此时表示连接成功)

2. 可读可写(在出错后,sockfd会处于可读可写状态,但有一种特殊情况见第三条)

3. 可读可写(我们可以想象,在我们connect执行完到select开始监听的这段时间内,

如果连接已经成功,并且服务端发送了数据,那么此时sockfd就是可读可写的,

因此我们需要对这种情况特殊判断)

说白了,在可读可写时,我们需要甄别此时是否已经连接成功,我们采用这种方案:

再次执行connect,然后查看error是否等于EISCONN(表示已经连接到该套接字)。

4. 错误

if(FD_ISSET(sockfd, &writeFds))

{

//可读可写有两种可能,一是连接错误,二是在连接后服务端已有数据传来

if(FD_ISSET(sockfd, &readFds))

{

if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) != 0)

{

int error=0

socklen_t length = sizeof(errno)

//调用getsockopt来获取并清除sockfd上的错误.

if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &length) <0)

{

printf("get socket option failed\n")

close(sockfd)

return -1

}

if(error != EISCONN)

{

perror("connect error != EISCONN")

close(sockfd)

return -1

}

}

}

//此时已排除所有错误可能,表明连接成功

fcntl(sockfd, F_SETFL, oldOption)

return sockfd

}12345678910111213141516171819202122232425262728293031323334353637383940

4. 恢复socket

因为我们只是需要将连接 *** 作变为非阻塞,并不包括读写等,所以我们吃醋要将socket重新设置。

fcntl(sockfd, F_SETFL, oldOption)关于Linux命令的介绍,看看《linux就该这么学》,具体关于这一章地址3w(dot)linuxprobe/chapter-02(dot)html


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8486400.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-16
下一篇 2023-04-16

发表评论

登录后才能评论

评论列表(0条)

保存