如何使用套接字的阻塞状态作为条件?
How do I use blocking-status of socket as a condition?
我是 maintaining/developing 现有的代码库。我们有一个 Raspberry Pi 控制一堆硬件,其中一些是模块化的。该代码用 C(可能是 C++)编写,使用 IPv4 标准通过套接字(使用 socket.h)与 Windows 上的图形用户界面进行通信。我很确定我们没有在覆盆子代码中实现多线程,否则这会容易得多。
某些模块化硬件未与代码交互。没有额外的硬件,树莓派就坐在那里等待 GUI 发送一些东西。这就是我们希望它的行为方式。
问题是,当我们连接了这个额外的硬件时,树莓派还需要 运行 一些代码来响应它的一个 IO 引脚绑定到硬件上的一个按钮。
我尝试在 main() 中的循环中添加(各种)条件,这是我 认为 代码空闲的地方。我总是让硬件或 GUI 控制正常工作,但不能同时工作。
我最终发现在该循环快要结束时调用的 read() 正在阻塞。
现在我想弄清楚如何在 read() 阻塞时执行一段代码(用于硬件控制),而在它停止时执行另一段代码。
类似于:
(Pseudocode)
read socket
while(blocking)
{
check for hardware signal, if found, runTest();
}
{use result of read()}
main 中的循环:
while(true)
{
initPort();
while(listening)
{
openPort();
if (netOpen)
{
//puts("// Tester is connected /////////////////////////////////");
loadCalFactors();
loadCalResistors();
loadExtConf(true);
inOn(false);
outOn(false);
// Loop until client terminates connection.
initPins();
while(netOpen)
{
/*
* Moving the block to work().
*/
// oldI = i;
// i = digitalRead(iTSW);
//
// if((i ^ oldI) == 0 && oldI == 1) // TSW has been held on
// testing = true;
//
// else if((i ^ oldI) == 1 && oldI == 0)
// testing = false;
//
// if(testLoaded && usingTermCtrl && i && !testing)
// {
// RunTp(false);
// }
// else
work();
}
}
}
}
这是阻塞的代码:
void work()
{
char bs[1];
int n;
//socket Sockfd is blocking here, so we only briefly return to the
//loop in main right after an action
n = read(Sockfd, bs, 1);
if(n > 0)
doAct(bs[0]);
else
checkForSOT();
}
我已经尝试将所有硬件检查放入 checkForSOT()(之前是空的)中,但它并没有比 main 中的循环做得更好。
设置套接字的位置:
void initPort()
{
struct sockaddr_in serv_addr;
printf("Initializing Port %d\n", HOST_PORT);
listening = false;
sockListen = socket(AF_INET, SOCK_STREAM, 0);
printf("sockListen=%d\n",sockListen);
if(sockListen < 0)
{
puts("Error opening socket");
delay(1000);
}
else
{
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(HOST_PORT);
if(bind(sockListen, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
puts("Error on binding");
delay(1000);
}
else
{
listen(sockListen, 1);
listening = true;
}
}
}
void openPort()
{
int clilen;
int newsockfd;
printf("\nTester waiting for connection on socket %d\n", sockListen);
clilen = sizeof(cli_addr);
// infinite wait on a connection
if((newsockfd = accept(sockListen,
(struct sockaddr *) &cli_addr, (socklen_t*) &clilen) ) < 0 )
puts("Error on accept");
else
{
if (DEBUG) debugMode = true;
netOpen = true;
Sockfd = newsockfd;
sendVersion();
netWrite("Connected\n");
sendExtConfMessage();
sendExtConf();
}
}
我在套接字阻塞上发现的大多数帖子都提到了 poll() 和 select()(连同它们的 p- 和 e- 升级(?)),但没有足够清楚详细说明它们如何为我工作,以确定它们是否是我需要的。
我也不确定在保持相同行为的同时将套接字更改为非阻塞需要什么。
注意:我仍在尝试通读 Beej 的网络编程指南并全神贯注,因此如果其中有特定部分对我有帮助,请具体说明。
此外,如果有人知道(或可以写出)通过 NetBeans 12(在 Windows 10 上)设置远程调试树莓派的好指南,那将是一个巨大的帮助!
投票不是很难。制作一个至少每 5 毫秒运行一次的循环。
while (running)
初始化,然后等待事情发生
struct pollfd fds = {fd, POLLIN, 0};
int rc = poll(&fds, 1, 5); // wait for fds or 5 msec
if (rc < 0) {
perror("poll");
exit(1);
} else if (rc > 0) {
if (fds.revents & POLLIN)
recv(fd); // fds is ready
}
// check button here
}
显然应该对错误条件进行更多检查和清理。
我是 maintaining/developing 现有的代码库。我们有一个 Raspberry Pi 控制一堆硬件,其中一些是模块化的。该代码用 C(可能是 C++)编写,使用 IPv4 标准通过套接字(使用 socket.h)与 Windows 上的图形用户界面进行通信。我很确定我们没有在覆盆子代码中实现多线程,否则这会容易得多。
某些模块化硬件未与代码交互。没有额外的硬件,树莓派就坐在那里等待 GUI 发送一些东西。这就是我们希望它的行为方式。
问题是,当我们连接了这个额外的硬件时,树莓派还需要 运行 一些代码来响应它的一个 IO 引脚绑定到硬件上的一个按钮。
我尝试在 main() 中的循环中添加(各种)条件,这是我 认为 代码空闲的地方。我总是让硬件或 GUI 控制正常工作,但不能同时工作。
我最终发现在该循环快要结束时调用的 read() 正在阻塞。
现在我想弄清楚如何在 read() 阻塞时执行一段代码(用于硬件控制),而在它停止时执行另一段代码。
类似于:
(Pseudocode)
read socket
while(blocking)
{
check for hardware signal, if found, runTest();
}
{use result of read()}
main 中的循环:
while(true)
{
initPort();
while(listening)
{
openPort();
if (netOpen)
{
//puts("// Tester is connected /////////////////////////////////");
loadCalFactors();
loadCalResistors();
loadExtConf(true);
inOn(false);
outOn(false);
// Loop until client terminates connection.
initPins();
while(netOpen)
{
/*
* Moving the block to work().
*/
// oldI = i;
// i = digitalRead(iTSW);
//
// if((i ^ oldI) == 0 && oldI == 1) // TSW has been held on
// testing = true;
//
// else if((i ^ oldI) == 1 && oldI == 0)
// testing = false;
//
// if(testLoaded && usingTermCtrl && i && !testing)
// {
// RunTp(false);
// }
// else
work();
}
}
}
}
这是阻塞的代码:
void work()
{
char bs[1];
int n;
//socket Sockfd is blocking here, so we only briefly return to the
//loop in main right after an action
n = read(Sockfd, bs, 1);
if(n > 0)
doAct(bs[0]);
else
checkForSOT();
}
我已经尝试将所有硬件检查放入 checkForSOT()(之前是空的)中,但它并没有比 main 中的循环做得更好。
设置套接字的位置:
void initPort()
{
struct sockaddr_in serv_addr;
printf("Initializing Port %d\n", HOST_PORT);
listening = false;
sockListen = socket(AF_INET, SOCK_STREAM, 0);
printf("sockListen=%d\n",sockListen);
if(sockListen < 0)
{
puts("Error opening socket");
delay(1000);
}
else
{
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(HOST_PORT);
if(bind(sockListen, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
puts("Error on binding");
delay(1000);
}
else
{
listen(sockListen, 1);
listening = true;
}
}
}
void openPort()
{
int clilen;
int newsockfd;
printf("\nTester waiting for connection on socket %d\n", sockListen);
clilen = sizeof(cli_addr);
// infinite wait on a connection
if((newsockfd = accept(sockListen,
(struct sockaddr *) &cli_addr, (socklen_t*) &clilen) ) < 0 )
puts("Error on accept");
else
{
if (DEBUG) debugMode = true;
netOpen = true;
Sockfd = newsockfd;
sendVersion();
netWrite("Connected\n");
sendExtConfMessage();
sendExtConf();
}
}
我在套接字阻塞上发现的大多数帖子都提到了 poll() 和 select()(连同它们的 p- 和 e- 升级(?)),但没有足够清楚详细说明它们如何为我工作,以确定它们是否是我需要的。 我也不确定在保持相同行为的同时将套接字更改为非阻塞需要什么。
注意:我仍在尝试通读 Beej 的网络编程指南并全神贯注,因此如果其中有特定部分对我有帮助,请具体说明。
此外,如果有人知道(或可以写出)通过 NetBeans 12(在 Windows 10 上)设置远程调试树莓派的好指南,那将是一个巨大的帮助!
投票不是很难。制作一个至少每 5 毫秒运行一次的循环。
while (running)
初始化,然后等待事情发生
struct pollfd fds = {fd, POLLIN, 0};
int rc = poll(&fds, 1, 5); // wait for fds or 5 msec
if (rc < 0) {
perror("poll");
exit(1);
} else if (rc > 0) {
if (fds.revents & POLLIN)
recv(fd); // fds is ready
}
// check button here
}
显然应该对错误条件进行更多检查和清理。