欢迎来到军工软件开发人才培养基地——学到牛牛

技术文章分享|UDP文件传输

时间:2024-05-06 07:01:10 来源:学到牛牛

UDP简介:  

UDP是用户数据报协议(User Datagram Protocol),它为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。

UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。一般应用于:周期性的状态信息、图片和视频数据传输、局域网内数据传输。

UDP文件传输模型思路:

作为传输层的协议之一,我们可以用UDP传输一些文件或其他数据。

1. 首先以fstat函数与fopen/fread等文件操作函数获取文件信息,如:文件内容、文件大小、文件名等具体信息。

2. 然后将获取的文件信息以UDP形式传输至接收端。

除UDP所需函数外,需要用到的函数介绍如下:

int stat(const char *path, struct stat *buf)

作用:获取文件信息

参数:文件路径(名),struct stat 类型的结构体

 

int fstat (int filedes, struct *buf);

作用:由文件描述符取得文件的状态。

解析:fstat() 用来将参数filedes 所指向的文件状态复制到参数buf 所指向的结构中(struct stat), fstat() 与stat() 作用完全相同,不同之处在于传入的参数为已打开的文件描述符

返回值:执行成功返回0,失败返回-1,错误代码保存在errno中

编码如下:

test.h:

#ifndef __TEST_H

#define __TEST_H

 

#include <string.h>

enum TYPE   // 定义枚举类型,根据类型不同,接收数据时做不同处理

{

NAME,

SIZE,

TYPE,

DATA,

ACK

};

struct file   // 定义文件结构体,传输数据时,解析其内容

{

int idx;

int len;

int type;

char data[1024];

};

#endif

 

recv.c:

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include "test.h"

#include <sys/stat.h>

 

int main()

{

int sock = socket( AF_INET, SOCK_DGRAM, 0 );

 

struct sockaddr_in local;

local.sin_family = AF_INET;

local.sin_port = htons( 10010 );

local.sin_addr.s_addr = inet_addr( "127.0.0.1" );

bind( sock, (struct sockaddr *)&local, sizeof(local) );

 

struct sockaddr_in addr;

int len = sizeof( addr );

 

while( 1 )

{

struct file stat;

recvfrom( sock, &stat, sizeof(stat), 0, (struct sockaddr *)&addr, &len );

 

if( stat.type == NAME )   // 根据类型不同,做不同处理,解析数据并输出

{

printf( "name is %s \n", stat.data );

}

else if( stat.type == SIZE )

{

int size = *(int *)stat.data;

printf( "size is %d \n", size );

}

else if( stat.type == DATA )

{

printf( "data is \n%s \n", stat.data );

}

}

close( sock );

return 0;

}

 

send.c:

#include <stdio.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include "test.h"

#include <sys/stat.h>

#include <fcntl.h>

 

int main( int argc, char *argv[] )

{

int sock = socket( AF_INET, SOCK_DGRAM, 0 );

 

struct sockaddr_in local;

local.sin_family = AF_INET;

local.sin_port = htons( 10086 );

local.sin_addr.s_addr = inet_addr( "127.0.0.1" );

bind( sock, (struct sockaddr *)&local, sizeof(local) );

 

struct sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_port = htons( 10010 );

addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );

 

// name   发送文件名字

struct file stat;

stat.idx = 0;

stat.len = strlen(argv[1]);

stat.type = NAME;

strcpy( stat.data, argv[1] );

sendto( sock, &stat, sizeof(stat), 0, (struct sockaddr *)&addr, sizeof(addr) );

 

// size   发送文件大小

stat.idx = 1;

stat.type = SIZE;

 

int fd = open( argv[1], O_RDONLY );

struct stat buf;

fstat( fd, &buf );   // 获取文件具体数据,比如大小

int size = buf.st_size;

memcpy( stat.data, &size, 4 );

sendto( sock, &stat, sizeof(stat), 0, (struct sockaddr *)&addr, sizeof(addr) );

 

// data   发送文件内容

stat.idx = 2;

stat.type = DATA;

while( 1 )

{

char buf[1024] = {0};

int ret = read(fd, buf, sizeof(buf));   // 读取文件内容

if( ret <= 0 )

{

break;

}

else

{

memcpy(stat.data, buf, sizeof(buf));

sendto( sock, &stat, sizeof(stat), 0, (struct sockaddr *)&addr, sizeof(addr) );  // 发送内容

}

}

 

printf("send complete\n");

 

close( sock );

return 0;

}