UDP实现文件内容传输

##程序可以直接复制使用,不受环境影响;

============================================================================

该设计框图左边实现文件循环写入并读取,读取数据存放于buf中,通过sendto()发送出去;

右边实现内容接收并保存到文件中,由recvfrom()接收暂存于buf缓冲区,write()将buf 内容存入文件,

read()进行读取验证。如果是只需要发送与接收功能:左边去掉write()部分,右边去掉read()

(不对信息进行验证)部分。

============================================================================

============================================================================

                                                      client 端口实现发送

/*client端实现对文件的追加写入以及发送;

*提示用户手动输入发送文件的路径与名称;

*文件必须是已经存在的;(后期修改自动创建文件)

*如果不需要向文件写入buf内容,可以将WriteInfo()函数功能去掉;

*/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <errno.h>

#include <stdlib.h>

#include <arpa/inet.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

 

#define PORT 8886

#define BUF_SIZE 1024

//#define FILE_PATH "./udpFile.txt"

 

int UdpClient(char path1[BUF_SIZE],int n1);

int WriteInfo(char path0[BUF_SIZE],int n0);

/*一维数组作为参数传递,手动输入发送文件文件路径*/

int main(void)

{

int n;

char path[BUF_SIZE];

n = sizeof(path)/sizeof(char);

printf("Please input send file path and name:\n");

scanf("%s",path);

UdpClient(path,n);

return 0;

}

/*<----------------从当前位置偏移2位,写入buf内容到文件----------------------->*/

int WriteInfo(char path0[BUF_SIZE],int n0)

{

int fd,len;

char buf[]="No xx:UDP send file content and save in receive file!";

fd=open(path0,O_WRONLY|O_APPEND);

if(fd<0)

{

perror("Write open file error ");

return 1;

}

else if(write(fd,buf,53)<0)

{

perror("write message failed!\n");

return 1;

}

else if(lseek(fd,4,SEEK_CUR)<0)/*当前位置偏移4位更改内容*/

{

perror("Write lseek error!");

return 1;

}

else

{

printf("Write message to file sucess!\n");

}

close(fd);

len=strlen(buf); /*接收端第0次位空白*/

return len;

}

/*<----------------发送buff缓存的内容,循环一次偏移一次----------------------->*/

int UdpClient(char path1[BUF_SIZE],int n1)

{

int i=0,StepSize,Steplen=0;

int fd;

struct sockaddr_in s_addr; //套接字地址结构

int sock; //套接字描述符

int addr_len; //地址结构长度

int len; //发送字节长度

char buff[BUF_SIZE];

/* 创建数据报模式的套接字 */

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { //SOCK_DGRAM表示数据包套接字UDP

perror("socket error");

exit(errno);

}

else

printf("create socket successful.\n\r");

/* 设置对方地址和端口信息 */

s_addr.sin_family = AF_INET; //地址族

s_addr.sin_port = htons(PORT);

s_addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_addr(argv[1]);

addr_len = sizeof(s_addr); //地址结构长度

/*从客户端的buff缓冲区中发送消息到地址结构为s_addr的远端机器*/

printf("-----------------------------%d------------------------------\n",i);

while(1)

{

/*write and Read file message to buff*/

StepSize=WriteInfo(path1,n1);

fd=open(path1,O_RDWR); /*以读写方式打开,O_RDNOLY 只读方式存在问题*/

if(fd<0)

{

perror("Read Open file error");

return 1;

}

else if(lseek(fd,Steplen,SEEK_SET)<0) /*步长+strlen(buf),循环一次读取新写入的内容*/

{

perror("Read lseek error!");

return 1;

}

else

printf("Read open file sucess!\n");

if(read(fd,buff,53)<0)

{

perror("read file content failed ");

return 1;

}

else

printf("Read file information save to buff sucessful!\n");

close(fd);

len = sendto(sock, buff, sizeof(buff), 0,(struct sockaddr *) &s_addr, addr_len);

if (len < 0) { /*如果发送失败*/

printf("\n\rsend error.\n\r");

return 1;

}

printf("Send buff info successful!\n\r");

Steplen+=StepSize;

printf("StepSize=%d\tSteplen=%d\n",StepSize,Steplen);

sleep(2);

printf("-----------------------------%d------------------------------\n",++i);

 

}

close(sock);

return 0;

}

###############################################################################

                                                           server端口实现接收

/*server端实现对文件的接收并保存到指定文件中;

*提示用户手动输入保存文件的路径与名称;

*文件必须是已经存在的;(后期修改自动创建文件)

*保存后在进行读取打印,确认信息无误。

*/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <errno.h>

#include <stdlib.h>

#include <arpa/inet.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

 

#define PORT 8886

#define BUF_SIZE 1024

//#define FILE_PATH "./udpSave.txt"

 

int WriteFileInfo(char buff[BUF_SIZE],int Steplen,char path[BUF_SIZE],int n);

int ReadFileInfo(int Steplen,char path[BUF_SIZE],int n);

int UdpServerRecv(char path[BUF_SIZE],int n);

/*一维数组作为参数传递,手动输入保存文件路径*/

int main(void) /*main(int argc, char **argv)*/

{

int n;

char path[BUF_SIZE];

n = sizeof(path)/sizeof(char);

printf("Please input save file path and name:\n");

scanf("%s",path);

UdpServerRecv(path,n);

return 0;

}

int UdpServerRecv(char path[BUF_SIZE],int n)

{

struct sockaddr_in s_addr; //服务器地址结构,IPV4对应的是sockaddr_in结构体

struct sockaddr_in c_addr; //客户端地址结构

int sock,i=0; //套接字描述符

socklen_t addr_len; //地址结构长度

int len,StepSize,Steplen=0; //接收到的消息字节数

char buff[BUF_SIZE ]; //存放接收消息的缓冲区

 

if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {

perror("socket");

exit(errno);

}

else

printf("create socket successful.\n\r");

 

memset(&s_addr, 0, sizeof(struct sockaddr_in));

 

s_addr.sin_family = AF_INET;

s_addr.sin_port = htons(PORT); //把16位值从主机字节序转换成网络字节序

s_addr.sin_addr.s_addr = INADDR_ANY; //输入本机IP地址

if ((bind(sock, (struct sockaddr *) &s_addr, sizeof(s_addr))) == -1) {

perror("bind error");

exit(errno);

}

else

printf("bind address to socket successfuly.\n\r");

 

addr_len = sizeof(c_addr);

printf("-------------------------------------%d---------------------------------------\n",i);

while (1) {

len = recvfrom(sock, buff, sizeof(buff) - 1, 0,(struct sockaddr *) &c_addr, &addr_len);

if (len < 0) {

perror("recvfrom error");

exit(errno);

}

StepSize=strlen(buff)-1;

buff[len] = '\0';

printf("Received from a remote computer:%s ;The port number is:%d\nBuf Message is: \n%s\n\r",inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port), buff);

WriteFileInfo(buff,Steplen,path,n);

ReadFileInfo(Steplen,path,n);

Steplen+=StepSize;

printf("StepSize=%d\tSteplen=%d\n",StepSize,Steplen);

sleep(2);

printf("-------------------------------------%d---------------------------------------\n",++i);

}

close(sock);

return 0;

}

int WriteFileInfo(char buff[BUF_SIZE],int Steplen,char path[BUF_SIZE],int n)

{

int fd;

fd= open(path,O_WRONLY); //"O_WRONLY"

if(fd<0)

{

perror("Write open file error");

return 1;

}

else if(lseek(fd,Steplen,SEEK_SET)<0) /*步长+strlen(buf),循环一次读取新写入的内容*/

{

perror("Read lseek error!");

return 1;

}

else if(write(fd,buff,53)<0)

{

perror("write file error");

return 1;

}

else

printf("write sucessful!\n");

close(fd);

return 0;

}

int ReadFileInfo(int Steplen,char path[BUF_SIZE],int n)

{

int fd;

char buf[BUF_SIZE];

fd=open(path,O_RDWR); /*以读写方式打开,O_RDNOLY 只读方式存在问题*/

if(fd<0)

{

perror("Read open file error");

return 1;

}

else if(lseek(fd,Steplen,SEEK_SET)<0) /*步长+strlen(buf),循环一次读取新写入的内容*/

{

perror("Read lseek error!");

return 1;

}

else if(read(fd,buf,53)<0)

{

perror("Read file error");

return 1;

}

else

printf("Read info on file sucessful!\n");

close(fd);

printf("The save info is : %s\n",buf);

return 0;

}

============================================================================

 

 

 

 

  • 0
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
下面是一个简单的C++实现UDP多线程文件传输的示例代码: ```cpp // UDP多线程文件传输服务器端代码 #include <iostream> #include <fstream> #include <string> #include <thread> #include <mutex> #include <chrono> #include <WinSock2.h> #pragma comment(lib, "Ws2_32.lib") using namespace std; // 接收数据线程函数 void recv_data_thread(SOCKET sock, sockaddr_in& client_addr, mutex& mtx, string& file_name) { char recv_buf[1024]; int recv_len = 0; // 接收文件名 recv_len = recvfrom(sock, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&client_addr, NULL); if (recv_len <= 0) { cerr << "Error: Failed to receive file name!" << endl; return; } mtx.lock(); file_name = recv_buf; mtx.unlock(); // 接收文件内容 ofstream outfile(file_name, ios::out | ios::binary); if (!outfile) { cerr << "Error: Failed to open file " << file_name << " for write!" << endl; return; } while (true) { recv_len = recvfrom(sock, recv_buf, sizeof(recv_buf), 0, (sockaddr*)&client_addr, NULL); if (recv_len <= 0) { break; } outfile.write(recv_buf, recv_len); } outfile.close(); } int main() { // 初始化WinSock WSADATA wsa_data; if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { cerr << "Error: Failed to initialize WinSock library!" << endl; return -1; } // 创建UDP socket SOCKET udp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (udp_sock == INVALID_SOCKET) { cerr << "Error: Failed to create UDP socket!" << endl; WSACleanup(); return -1; } // 绑定socket sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(8000); if (bind(udp_sock, (sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { cerr << "Error: Failed to bind UDP socket!" << endl; closesocket(udp_sock); WSACleanup(); return -1; } cout << "UDP server started..." << endl; while (true) { // 接收客户端请求 sockaddr_in client_addr; memset(&client_addr, 0, sizeof(client_addr)); int addr_len = sizeof(client_addr); mutex mtx; string file_name; thread recv_thread(recv_data_thread, udp_sock, ref(client_addr), ref(mtx), ref(file_name)); recv_thread.detach(); // 休眠一段时间,等待接收线程处理完成 this_thread::sleep_for(chrono::milliseconds(1000)); if (!file_name.empty()) { cout << "File " << file_name << " received!" << endl; } } // 关闭socket closesocket(udp_sock); // 清理WinSock WSACleanup(); return 0; } ``` 在这个示例中,首先使用WSAStartup()函数初始化WinSock库,然后使用socket()函数创建一个UDP socket,并使用bind()函数将socket绑定到本地IP地址和端口号上。在一个无限循环中,使用recv_data_thread()函数作为接收数据的线程函数,使用thread()函数创建一个新的线程来处理客户端请求。每当接收到一个客户端请求时,就创建一个新的线程来接收客户端发送的文件内容。接收文件名和文件内容的过程在接收数据线程函数中实现,使用mutex来保证线程安全。在文件内容接收完成后,将文件名输出到控制台上。 客户端代码可以使用类似的方式实现。需要注意的是,在发送文件内容时,需要将文件内容分成多个数据包进行发送,并在每个数据包中包含文件名和文件偏移量等信息,以便在服务器端将多个数据包组装成完整的文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值