打印

CCS+C6678LE开发记录08:以太网接口测试续(大块数据传输)

[复制链接]
1429|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Tennasi|  楼主 | 2015-10-31 21:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

如果将数据(buffer)尺寸设置为一个较大的值(如2048等)就会出现timeout的错误。

在这种情形下更不用说传输一个大文件了,因此我们需要寻找一种解决方案。

本文正是为此而展开。

核心思想是:

1.在PC端,打开文件,分块读取数据到buffer(比如每一块大小为2KB等)

2.在PC端,每次读取数据到bufer后将buffer数据发送到socket

3.数据经过网络连接传送到DSP端

4.DSP端不断处理(暂存)ETH0接口收到的数据并发送响应

5.在PC端,每次发送一个数据块之后等待来自DSP的响应,之后才发送下一块

6.在PC端,不断发送数据块,直到整个文件数据发送完毕,最后关闭连接

经过测试发现,将文件分成2048B(=2KB)大小的块进行发送是一个比较好的选择。

每次发送2KB被DSP收到后立即被处理,然后DSP发回响应,表示已经收到这个数据。

PC端收到应答后就知道刚才发给DSP的数据已经被接收了,可以发送下一块数据。

为了让测试更加严谨,我们找来几个大小不同的文件,具体测试过程截图如下


一幅普通尺寸(1000*1000以下)的图片,30KB左右,处理时间不到1秒

一幅稍大尺寸(1920*1080)的图片,不到1MB,处理时间1秒左右

测试一个较大的文件,44.13MB大小,处理用时25秒左右

测试一个更大的文件,191.82MB大小,处理用时103秒左右

最后测试传输一张大尺寸照片,4k*3k分辨率,5.28MB大小,用时约3秒

在CCS调试输出窗口的截图如下


对比一下发现,5次测试中都能正确收到全部数据。


这个测试表明,我们的流程设计是合理的。

最后将PC端发送数据以及DSP端接收数据的代码贴上来以供参考。

// PC端:发送数据  
// fengyhack [url=home.php?mod=space&uid=72445]@[/url] 20150203  
#include <stdio.h>  
#include <time.h>  
#include <stdlib.h>  
#include "sockets.h"  
#pragma comment(lib,"ws2_32.lib")  
#pragma warning(disable:4996)  
  
const char  *TARGET = "169.254.11.123";  
#define PORT  7  
#define TIMEOUT 1  /* second(s) */  
  
int main(void)  
{  
    system("title Ethernet0 Transfer Test");  
    system("color 2e");  
    printf("Remote ( %s : %d )\n", TARGET, PORT);  
  
    char fileName[256] = { 0 };  
    printf("Input filename:");  
    scanf("%s", fileName);  
    FILE* fp = fopen(fileName, "rb");  
    if (fp == NULL)  
    {  
        printf("Failed to open file.\n");  
        goto leave;  
    }  
    long fsize = 0;  
    fseek(fp, 0L, SEEK_END);  
    fsize = ftell(fp);  
    double kilo = 1.0*fsize / 1024.0;  
    if (kilo >= 1024.0)  
    {  
        printf("File size: %.2fMB\n", kilo/1024.0);  
    }  
    else  
    {  
        printf("File size: %.2fKB\n", kilo);  
    }  
    const int unit = 2048;  
    int loop = fsize / unit;  
    int residue = fsize - loop*unit;  
    char* data = (char*)malloc(unit + 1);  
  
    struct in_addr dst;  
    inet_pton(AF_INET, TARGET, &dst);  
    unsigned short port = PORT;  
    socketsStartup();  
    SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);  
    if (s < 0)  
    {  
        printf("failed socket (%d)\n", getError());  
        goto leave;  
    }  
  
    struct sockaddr_in sin;  
    sin.sin_family = AF_INET;  
    sin.sin_addr.s_addr = 0;  
  
    int status = 0;  
    status = bind(s, (const struct sockaddr *) &sin, sizeof(sin));  
    if (status< 0)   
    {  
        printf(" failed bind (%d)\n", getError());  
        goto leave;  
    }  
    sin.sin_addr = dst;  
    sin.sin_port = htons(port);  
  
    struct timeval timeout;  
    timeout.tv_sec = TIMEOUT;  
    timeout.tv_usec = 0;  
  
    fd_set fds;  
    int nr;  
    char tmp[8] = { 0 };  
  
    printf("<Start sending data>\n");  
  
    time_t time_start = time(0);  
  
    for (int i = 1; i <= loop; ++i)  
    {  
        fread(data, unit, 1, fp);  
        data[unit] = 0;  
        status = sendto(s, data, strlen(data), 0, (const struct sockaddr *)&sin, sizeof(sin));  
        if (status< 0)  
        {  
            printf("send failed (%d)\n", getError());  
            goto leave;  
        }  
  
        FD_ZERO(&fds);  
        FD_SET(s, &fds);  
  
        select(s + 1, &fds, NULL, NULL, &timeout);  
        nr = recv(s, tmp, 8, 0);  
  
        if (i % 64 == 0)  
        {  
            printf(".");  
            if (i % 4096 == 0) printf(" (%4.1f%%)\n", 100.0*i / loop);  
        }  
    }  
    if (residue > 0)  
    {  
        fread(data, residue, 1, fp);  
        data[residue] = 0;  
        status = sendto(s, data, strlen(data), 0, (const struct sockaddr *)&sin, sizeof(sin));  
        if ( status< 0)  
        {  
            printf("send failed (%d)\n", getError());  
            goto leave;  
        }  
  
        FD_ZERO(&fds);  
        FD_SET(s, &fds);  
  
        select(s + 1, &fds, NULL, NULL, &timeout);  
        nr = recv(s, tmp, 8, 0);  
        printf(" (100%%)\n");  
    }  
    fclose(fp);  
  
    printf("Finished transfer. Time = %d seconds\n", (int)(time(0) - time_start));  
  
leave:  
    if(s>=0) closesocket(s);  
    if(data) free(data);  
    socketsShutdown();  
  
    system("pause");  
    return 0;  
}  


相关帖子

沙发
Tennasi|  楼主 | 2015-10-31 21:50 | 只看该作者
DSP端接收数据的代码与本系列的06X篇http://bbs.**/thread-476213-1-1.html基本一致,


唯一改动的地方是在一个函数中,具体代码如下
int udpTransferTask( SOCKET s, UINT32 unused )  
{  
    printf("TASK execution %d\n",++task_counter);  
  
        struct timeval tv;  
        tv.tv_sec  = 1;  
        tv.tv_usec = 0;  
        setsockopt(s,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv));  
        setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv));  
  
        struct sockaddr_in sin1;  
        int sz=sizeof(sin1);  
        int hlen=strlen(reply);  
        int nr,total=0;  
        HANDLE hBuffer;  
        unsigned char* pBuf;  
        while(1)  
        {  
            nr=recvncfrom( s, (void**)&pBuf, 0, (PSA)&sin1, &sz, &hBuffer );  
            if(nr<=0) break;  
            total+=nr;  
            sendto( s, reply, hlen, 0, (PSA)&sin1, sz );  
            recvncfree( hBuffer );  
        }  
  
        double kilo_bytes=1.0*total/1024.0;  
        if(kilo_bytes>=1024.0)  
        {  
            printf("Total size of data received: %.2fMB\n",kilo_bytes/1024.0);  
        }  
        else  
        {  
            printf("Total size of data received: %.2fKB\n",kilo_bytes);  
        }  
  
        return 1;  
}  

使用特权

评论回复
板凳
734774645| | 2015-10-31 22:00 | 只看该作者
这个方法实在是太高效了

使用特权

评论回复
地板
643757107| | 2015-10-31 23:15 | 只看该作者
将文件分割成2kb发送比较好

使用特权

评论回复
5
edishen| | 2015-10-31 23:58 | 只看该作者
感谢分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

169

帖子

1

粉丝