| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1391 人关注过本帖
标题:这个函数不用goto怎么改
取消只看楼主 加入收藏
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:6 
这个函数不用goto怎么改
程序代码:
static char
mysh_recv_data(char data[], char endata[], unsigned *size,
           unsigned (*recv)(void *, unsigned),
           unsigned (*send)(const void *, unsigned))
{
    unsigned sz, len, n;
    unsigned need, max_size;
    char *p, *e, *begin, c;

    len = sz = 0;
    begin = endata;
    max_size = MYSH_EN_DATA_BLOCK_SIZE;
    goto lab_skip_get_header;

    while(1)
    {
    /* lab_get_header */
        begin = endata;

        c = mysh_send_cmd(C_RETRY, send);
        if (c != C_RETRY) break;
        c = mysh_recv_cmd(C_DATAB, recv);
        if (c == C_STOP) break;
        if (c != C_DATAB) continue;

    lab_skip_get_header:
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1) goto lab_skip_get_header;
        len = len + n;
        e = p + n;

    lab_try_find_data_end:
        while(p < e && mysh_is_endata_char(*p))
            ++p;
        c = *p;
        if (p >= e) goto lab_skip_get_header;
        if (c == C_END) goto lab_finded_data;
        if (c == C_STOP) goto lab_return_value;

        while(p < e)
        {
            c = *p++;
            if (c == C_STOP) goto lab_return_value;
            if (c != C_DATAB) continue;
            begin = p;
            goto lab_try_find_data_end;
        }
        /* we re-need a C_DATAB header */
        continue;

    lab_finded_data:
        n = (p - begin);
        sz = mysh_data_decode(data, begin, n);
        /* we re-need a C_DATAB header */
        if (n < 1) continue;
        c = mysh_send_cmd(C_OK, send);
        if (c == C_OK)
        c = C_DATAB;
        break;
    }


 lab_return_value:
    *size = sz;
    return c;
}



[ 本帖最后由 皮天佑 于 2015-7-4 17:02 编辑 ]
2015-07-04 16:58
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
回复 2楼 风清云起
这个函数接受一包数据,然后把这包传输格式的数据转成本地数据,如果转出来的本地数据有误或者接受到的数据有误则重新接收。
mysh_send_cmd 发送一个命令
mysh_recv_cmd 接受一个命令
mysh_data_decode 将传送中的数据解码为本地数据
传输的数据格式为 C_DATAB + 传输中的数据  + 校验 + C_END;
如果接受到C_STOP立即返回,如果接受数据成功者返送C_OK命令。
2015-07-04 17:23
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
老大要改为没有goto的代码,感觉越改越复杂。
2015-07-04 17:24
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
回复 6楼 erty1001
现在写这段代码的人走了,老大让我来维护,这个代码我感觉写的很精练。goto是可以去掉,但感觉是为了去掉而增加了代码的复杂性。
while(1)里面的标签是按顺序来的,接受数据的头,接受数据,尝试查找数据的结尾,如果找到数据结尾则尝试解码数据,成功则退出循环。
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1) goto lab_skip_get_header;
这里如果该成do while循环是可以,但是下面要还要回到这里,估计得要至少2层循环,
while(1)
{
        while(1)
        {
           while(接收buff中有所数据);
           while(跳过是传输数据的字符)
           如果接收到数据结尾,尝试解码数据为本地数据
           否则是要重新查找数据头
           。。。
        }
        获取数据头
}
好像要加变量来控制2层循环的退出,我改的版本看起来很乱,没原来代码清晰简单。
C_STOP是为了防止停在函数里面,这个命令可以让接收方在任何位置退出接受,在传输过程中即使丢数据都能正确的完成接受。
感觉能改的就是那个lab_skip_get_header标签改为lab_input_data,
不知道老大是怎么想的。
2015-07-04 22:48
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
代码作者当时的建议是每个标签做成函数。整个代码都是基于非阻塞的,再加上C_STOP处理起来比较麻烦,作者是说获取输入重复计算接收长度,反正没收到数据,再算一次无所谓,这里最好加上sleep函数让出cpu
2015-07-05 10:07
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
多谢beyoundyf的提醒,确实有2个bug.在接收头的时候应该让len为0,接收完应让把if(n<1)改为sz
2015-07-05 11:00
皮天佑
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2015-7-4
收藏
得分:0 
我整理的下程序,

程序代码:
static char
mysh_recv_data(char data[], char endata[], unsigned *size,
           unsigned (*recv)(void *, unsigned),
           unsigned (*send)(const void *, unsigned))
{
    unsigned sz, len, n;
    unsigned need, max_size;
    char *p, *e, *begin, c;

    len = sz = 0;
    begin = endata;
    max_size = MYSH_EN_DATA_BLOCK_SIZE;
    goto lab_input_data;

    while(1)
    {
    /* lab_get_header: */
        begin = endata;
        len = 0; /* discard all data*/

        c = mysh_send_cmd(C_RETRY, send);
        if (c != C_RETRY) break;
        c = mysh_recv_cmd(C_DATAB, recv);
        if (c == C_STOP) break;
        if (c != C_DATAB) continue;

    lab_input_data:
        /* 接收端不发C_RETRY,发送端不会直接重传。但是接收端要加个超时重传。
           如果传输过程中突然硬件突然不通然后再通再不通,可能连续出现C_END丢失和C_DATAB丢失,这样会出现溢出 */
        if (len >= max_size)
            continue;
        need = max_size - len;
        p = endata + len;
        n = recv(p, need);
        if (n < 1)
        {
            /* if (超时) continue; */
            mysh_sleep(100);
            goto lab_input_data;
        }
        len = len + n;
        e = p + n;

    lab_try_find_data_end:
        /* 有预留的空间,程序不会出现访问违例,但这样该最好 */
        while(p < e && mysh_is_endata_char((c = *p)))
            ++p;
        if (p >= e) goto lab_input_data;
        if (c == C_END) goto lab_finded_data;
        if (c == C_STOP) goto lab_return_value;

        while(p < e)
        {
            c = *p++;
            if (c == C_STOP) goto lab_return_value;
            if (c != C_DATAB) continue;
            begin = p;
            goto lab_try_find_data_end;
        }
        /* we re-need a C_DATAB header */
        continue;

    lab_finded_data:
        n = (p - begin);
        sz = mysh_data_decode(data, begin, n);
        /* 应该是判断解码后的数据长度 */
        /* we re-need a C_DATAB header */
        if (sz < 1) continue;
        c = mysh_send_cmd(C_OK, send);
        if (c == C_OK)
           c = C_DATAB;
        break;
    }

lab_return_value:
    *size = sz;
    return c;
}


[ 本帖最后由 皮天佑 于 2015-7-5 12:49 编辑 ]
2015-07-05 11:40
快速回复:这个函数不用goto怎么改
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.052556 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved