OpenEdv-开源电子网

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

关于TCP server程序的一点问题

[复制链接]

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2015-10-27
在线时间
1 小时
发表于 2015-11-20 14:44:42 | 显示全部楼层 |阅读模式
5金钱
对TCP协议不太了解,但是任务需要做一个用tcp传2640的jpeg图像(串口太慢)
遇到以下一些问题

200M的jpeg图像大概在90K左右,目前TCP_SND_BUF 是5840 B
所以要分多次发送,所以我修改了tcp_server_demo.c的轮询函数
if(tcp_server_flag&(1<<7))
{
    while(remsize)
    { 
        if(remsize<=TCP_SND_BUF)
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,remsize,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+data_blk_offset*TCP_SND_BUF,remsize);
            tcp_server_senddata(tpcb,es); 
            if(es->p!=NULL)
                pbuf_free(es->p); 
            remsize=0;
        }
        else
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,TCP_SND_BUF,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+data_blk_offset*TCP_SND_BUF,TCP_SND_BUF);
            tcp_server_senddata(tpcb,es);
            if(es->p!=NULL)
                pbuf_free(es->p); 
            data_blk_offset++;
            remsize-=TCP_SND_BUF;
        }
    }
tcp_server_flag&=~(1<<7);
}

执行这段,会产生错误,assertion : p->ref 0
我在后面加了一句  tcp_output(tpcb);
if(tcp_server_flag&(1<<7))
{
    while(remsize)
    { 
        if(remsize<=TCP_SND_BUF)
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,remsize,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+data_blk_offset*TCP_SND_BUF,remsize);
            tcp_server_senddata(tpcb,es); 
            if(es->p!=NULL)
                pbuf_free(es->p); 
            remsize=0;
        }
        else
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,TCP_SND_BUF,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+data_blk_offset*TCP_SND_BUF,TCP_SND_BUF);
            tcp_server_senddata(tpcb,es);
            if(es->p!=NULL)
                pbuf_free(es->p); 
            data_blk_offset++;
            remsize-=TCP_SND_BUF;
        }
       tcp_output(tpcb);
    }
tcp_server_flag&=~(1<<7);
}

但是我觉得逻辑有点奇怪,为什么要在poll里发送?
直接调用函数发送不行吗?
于是把这段程序在检测到KEY0按下那段里
但是好像在accept里已经申请了内存给arg,其他回调函数使用的es都是从arg里分配的
在检测按键那段获得不了arg。。。
可能我描述的有些混乱
简单点就是想问,想发一个大的数据流,不在poll里发送,应该如何修改。。。。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-11-20 15:34:42 | 显示全部楼层
可以不再poll里面发送,你可以直接调用发送函数发送,在poll里面发送是为了利用poll会被轮询调用这个特点。
开往春天的手扶拖拉机
回复

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2015-10-27
在线时间
1 小时
 楼主| 发表于 2015-11-20 17:29:01 | 显示全部楼层
回复【2楼】zuozhongkai:
---------------------------------
不在poll里发送,我把发送的语句直接放到检测到KEY0按下部分
senddata函数里的参数es该怎么初始化?
原来的程序里,es所占的内存先由accept分配,并且绑定到void* arg,
再进入poll,
struct tcp_server_struct *es;
es=(struct tcp_server_struct *)arg;

但是如果在主程序里直接发送,不知道arg的地址啊。。。
回复

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2015-10-27
在线时间
1 小时
 楼主| 发表于 2015-11-21 11:25:36 | 显示全部楼层
不知道arg的地址。。。就不能对pbuf初始化。。。
回复

使用道具 举报

2

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
50
金钱
50
注册时间
2015-10-27
在线时间
1 小时
 楼主| 发表于 2015-11-23 21:16:50 | 显示全部楼层
偷偷把accept里的arg传给了一个全局变量,
根据轮询里原来的那段发送的程序,我在tcp_server_senddata外写了一层函数tcp_server_sent_data

void tcp_server_sent_data(void *arg, struct tcp_pcb *tpcb, u8 *data,u32 len)
{
    struct tcp_server_struct *es;
    u32 remsize=len;
    u8 offset_blk=0;
    printf("send %d bytes data to PC\r\n",remsize);
    es=(struct tcp_server_struct *)arg; 
    while(remsize)
    {
        if(remsize<=TCP_SND_BUF)
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,remsize,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+offset_blk*TCP_SND_BUF,remsize);
            tcp_server_senddata(tpcb,es);
            if(es->p!=NULL)
            {
                pbuf_free(es->p); 
                es->p = 0;
            }
            remsize=0;
        }
        else
        {
            es->p=pbuf_alloc(PBUF_TRANSPORT,TCP_SND_BUF,PBUF_POOL);
            pbuf_take(es->p,tcp_server_sendbuf+offset_blk*TCP_SND_BUF,TCP_SND_BUF);
            tcp_server_senddata(tpcb,es);
            if(es->p!=NULL)
            {
                pbuf_free(es->p);
                es->p = 0;
            }
            offset_blk++;
            remsize-=TCP_SND_BUF;
        }
        tcp_output(tpcb);
        //delay_ms(3);
      }
    return;
}

暂且不管把arg地址泄露出来这个问题。。
现在还是有两个问题。。。

我一次发了100K左右的数据
1.如果不加这个delay_ms(3)
在pbuf_take或者pbuf_free阶段  会出现assert:pbuf->ref >0
这个是不是因为pbuf的剩余数据是在sent回调里完成的,如果没有延时,发送太快导致上一个packet没发完下一个又来了,所以pbuf_take 或者pbuf_free会出现问题
2.我用原子软件资料里的网络调试助手调试,
加了这个delay_ms(3)后,上面这个问题稍微得到解决(但是传输速度肯定受到影响了)
收到的数据有时候会出现错误,但是接收到的长度是正确的,实在找不出原因,后来怀疑是不是这个调试助手显示的问题
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2015-11-24 10:25:29 | 显示全部楼层
回复【5楼】65993366:
---------------------------------
不调用tcp_output()这个函数试一下
开往春天的手扶拖拉机
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 15:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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