OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 346|回复: 2

求教LWIP connect函数服务器没有开启会一直阻塞问题

[复制链接]

89

主题

171

帖子

0

精华

高级会员

Rank: 4

积分
600
金钱
600
注册时间
2015-9-7
在线时间
140 小时
发表于 2024-9-2 00:06:02 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 wt13568089592 于 2024-9-2 01:23 编辑

求教LWIP connect函数一直阻塞问题
当tcp服务器没有开的时候connect函数会一直阻塞,如果后面tcp服务器已开启会连不上服务器,有没有办法设置超时呢?当使用了 ioctlsocket(g_lwip_sock,FIONBIO,&block);  //设置为非阻塞模式 connect会返回-1,实际上已经连接成功,但是怎么去判断是否成功呢?
void lwip_demo(void)
{
    struct sockaddr_in atk_client_addr;
    err_t err;
    int recv_data_len;
    BaseType_t lwip_err;
    char *tbuf;
    int block = 1;
    lwip_data_send();                                           /* 创建发送数据线程 */

    while (1)
    {
      sock_start:
                         printf("TCP开始连接中\r\n");
                         g_lwip_sock = socket(AF_INET, SOCK_STREAM, 0);                 /* 可靠数据流交付服务既是TCP协议 */
                         setsockopt(g_lwip_sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
        g_lwip_connect_state = 0;
        atk_client_addr.sin_family = AF_INET;                   /* 表示IPv4网络协议 */
        atk_client_addr.sin_port = htons(LWIP_DEMO_PORT);       /* 端口号 */
        atk_client_addr.sin_addr.s_addr = inet_addr(IP_ADDR);   /* 远程IP地址 */
        memset(&(atk_client_addr.sin_zero), 0, sizeof(atk_client_addr.sin_zero));
       ioctlsocket(g_lwip_sock,FIONBIO,&block);  //设置为非阻塞模式

//        tbuf = mymalloc(SRAMIN, 200); /* 申请内存 */
//        sprintf((char *)tbuf, "ort:%d", LWIP_DEMO_PORT); /* 客户端端口号 */
      //  disp_show_string(5, 150, 200, 16, 16, tbuf, CC);
        printf("TCP尝试连接中\r\n");
        /* 连接远程IP地址 */
        err = connect(g_lwip_sock, (struct sockaddr *)&atk_client_addr, sizeof(struct sockaddr));
        printf("TCP连接结束\r\n");
        if (err == -1)
        {
            printf("连接失败\r\n");
            g_lwip_sock = -1;
            closesocket(g_lwip_sock);
//            myfree(SRAMIN, tbuf);
            vTaskDelay(1000);
            goto sock_start;
        }

        printf("连接成功\r\n");
      //  disp_show_string(5, 90, 200, 16, 16, "State:Connection Successful", CC);
        g_lwip_connect_state = 1;

        while (1)
        {
            recv_data_len = recv(g_lwip_sock,g_lwip_demo_recvbuf,
                                 LWIP_DEMO_RX_BUFSIZE,0);
            if (recv_data_len <= 0 )
            {
                                                         printf("网络数据接收错误\r\n");
                closesocket(g_lwip_sock);
                g_lwip_sock = -1;
//                lcd_fill(5, 89, lcddev.width,110, WHITE);
             //   disp_show_string(5, 90, 200, 16, 16, "Stateisconnect", CC);
//                myfree(SRAMIN, tbuf);
                goto sock_start;
            }

            /* 接收的数据 */
//            lwip_err = xQueueSend(g_display_queue,&g_lwip_demo_recvbuf,0);
           // printf("%s",&g_lwip_demo_recvbuf);
            if (lwip_err == errQUEUE_FULL)
            {
                                                         printf("Key_Queue fault!\r\n");
              //  printf("队列Key_Queue已满,数据发送失败!\r\n");
            }

            vTaskDelay(10);
        }
    }
}


最佳答案

查看完整内容[请看2#楼]

在您的代码中,您尝试将套接字设置为非阻塞模式,然后调用 `connect` 函数。在非阻塞模式下,如果连接无法立即建立,`connect` 将返回 `-1` 并设置错误号为 `EINPROGRESS`。这意味着连接操作已经开始,但尚未完成。在这种情况下,您需要检查连接状态以确定连接是否成功。 为了实现这一点,您可以使用 `select` 或 `poll` 函数来轮询套接字的状态,直到连接成功或者超时为止。下面是一个示例代码片段,展示如何实现这一功能: ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

881

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4199
金钱
4199
注册时间
2019-9-4
在线时间
881 小时
发表于 2024-9-2 00:06:03 | 显示全部楼层
在您的代码中,您尝试将套接字设置为非阻塞模式,然后调用 `connect` 函数。在非阻塞模式下,如果连接无法立即建立,`connect` 将返回 `-1` 并设置错误号为 `EINPROGRESS`。这意味着连接操作已经开始,但尚未完成。在这种情况下,您需要检查连接状态以确定连接是否成功。

为了实现这一点,您可以使用 `select` 或 `poll` 函数来轮询套接字的状态,直到连接成功或者超时为止。下面是一个示例代码片段,展示如何实现这一功能:

```c
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>

// ... 其他代码 ...

fd_set readfds;
struct timeval timeout;

// 设置超时时间为5秒
timeout.tv_sec = 5;
timeout.tv_usec = 0;

FD_ZERO(&readfds);
FD_SET(g_lwip_sock, &readfds);

printf("等待连接...\r\n");

if (select(g_lwip_sock + 1, NULL, &readfds, NULL, &timeout) > 0) {
    if (connect_status(g_lwip_sock) == 0) {
        printf("连接成功\r\n");
        // 连接成功后的处理...
    } else {
        printf("连接失败\r\n");
        // 处理连接失败...
    }
} else {
    printf("连接超时\r\n");
    // 处理连接超时...
}

// 检查连接状态的辅助函数
int connect_status(int sockfd) {
    int error = 0;
    socklen_t len = sizeof(error);
    if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
        perror("getsockopt");
        return -1;
    }
    return error == 0 ? 0 : -1;
}
```

在这个示例中,我们使用 `select` 函数来等待套接字变为可写状态(即连接完成)。如果在指定的时间内(这里是5秒)`select` 返回一个正数,则表明套接字准备好进行读/写操作。此时,我们可以通过调用 `connect_status` 函数来检查连接是否成功。

`connect_status` 函数通过调用 `getsockopt` 来获取套接字的错误状态。如果 `SO_ERROR` 的值为 0,则连接成功;否则,连接失败。

这种方法可以让您的程序在尝试连接时不会无限期地阻塞,并且可以在连接失败或超时时采取适当的措施。
回复

使用道具 举报

89

主题

171

帖子

0

精华

高级会员

Rank: 4

积分
600
金钱
600
注册时间
2015-9-7
在线时间
140 小时
 楼主| 发表于 2024-9-2 13:56:39 | 显示全部楼层
太感谢了,谢谢谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 08:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表