我正在使用 Ubuntu,我有一个 C/C++ 应用程序,它使用 WxWidgets 并通过 TCP 发送一个字符串。 只有在路由器和连接正常的情况下它才能正常工作,否则它会卡住,我需要手动退出应用程序。
我是这样调用函数的:
SendCommand ptr;
if ( ptr.sendcommand(16,16,1) ){
printf("Porta Aperta\n");
} else {
printf("Errore di comunicazione - porta non aperta\n");
}
这是函数:
int SendCommand::sendcommand(int relay_on, int relay_off, int stop){
printf("eseguo la funzione nella classe\n");
std::array<uint8_t, 8> command1;
std::array<uint8_t, 8> command2;
switch(relay_on){
case 16: command1 = {0x58, 0x01, 0x12, 0x00, 0x00, 0x00, 0x10, 0x7B}; // switch on the relay 16
break;
}
switch(relay_off){
case 16: command2 = {0x58, 0x01, 0x11, 0x00, 0x00, 0x00, 0x10, 0x7A}; // switch off the relay 16
break;
}
int sockfd, n;
struct sockaddr_in servaddr;
std::string serveraddr = "192.168.1.4";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if ( sockfd < 0 )
{
cerr << "Error creating socket! " << strerror(errno) << endl;
return -1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(serveraddr.c_str());
servaddr.sin_port = htons(3000);
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
{
cerr << "Error connecting socket!" << strerror(errno) << endl;
close(sockfd);
return -1;
}
//Relay #14 per porta bilancia
printf("Apro la porta\n");
int bytes_to_send1 = sizeof(command1);
int bytes_to_send2 = sizeof(command2);
int bytes_sent1 = 0;
int bytes_sent2 = 0;
do
{
n = send(sockfd, command1.data() + bytes_sent1, bytes_to_send1 - bytes_sent1, 0);
if ( n < 0 )
{
cerr << "Error writing to socket!" << strerror(errno) << endl;
close(sockfd);
}
bytes_sent1 += n;
}
while (bytes_sent1 < bytes_to_send1);
n=0;
sleep(stop);
do
{
n = send(sockfd, command2.data() + bytes_sent2, bytes_to_send2 - bytes_sent2, 0);
if ( n < 0 )
{
cerr << "Error writing to socket!" << strerror(errno) << endl;
close(sockfd);
}
bytes_sent2 += n;
}
while (bytes_sent2 < bytes_to_send2);
close(sockfd);
n=0;
return 1;
}
感谢在上一个主题中收到的建议,我使用符号 std::array<uint8_t, 8> command1;
定义要通过网络发送的内容的数组,但即使网络出现问题,我也找不到让我的程序正确流动的解决方案。
我尝试使用线程或 fork() 并且它有效,但是有没有其他更简单的解决方案?
附言当它因为没有互联网连接而卡住时,它会阻塞在这里:
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
{
cerr << "Error connecting socket!" << strerror(errno) << endl;
close(sockfd);
return -1;
}
它永远不会进入 if 条件。
最佳答案
几个选项
- 使用 Boost ASIO
- 线程/进程
- 将超时设置为低(例如 - 5 秒),以便阻止相对较少的时间
- 设置套接字非阻塞并对其执行epoll(涉及线程)。
对于 2 - 尝试使用标准线程,应该易于使用(您也可以使用异步 + lambda 并使用 futures 简化控制流)。
这样代码看起来更容易阅读。
对于 3 和 4 - 您需要将套接字设置为非阻塞并进行轮询(通过 select 或 epoll)- 参见 fnctl(.., O_NONBLOCK ..) select()。如果没有错误,则可以按原样使用套接字(或者可能从异步返回它并在将来获取)。
关于c++ - 在 C/C++ 和 std::array 中使用 TCP 时避免阻塞程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58509599/