我最近写一个项目的时候需要涉及到udp传输文件.网上找了找发现没什么合适的,那么我就写了一个自己的供参考.

文件分成两类:第一类是文本文件,第二类是二进制文件.他们的文件读写是不一样的.所以我提供了两种文件的读写,传输方式.

首先看源端DataSource的main.cpp:

#include "UDPSocket.h"
#include "Package.h"#include <unordered_map>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <fstream>using namespace std;//传输二进制文件的函数
void sendBinFile(){string dstip = "162.105.85.198";unsigned short dstport = 51002;UDPSocket udpsocket;udpsocket.create(20022);string file1;cout << "Please input file name: " << endl;cin >> file1;ifstream in(file1, ios::binary);if(!in){cout << "File open error" << endl;return;}  int count = 1;//需要一直读取到文件结束,注意这里不是按行读取,是按长度读取while (!in.eof())  {DataPackage datapackage;string contentName = "pku/eecs/file/" + file1 + "/segment" + to_string(count);strcpy(datapackage.contentName, contentName.c_str());in.read(datapackage.data, 1400);//这句话是核心,表示读取的长度.正常情况是1400,但是最后一次可能小于1400datapackage.datasize = in.gcount();cout << datapackage.datasize << endl;datapackage.segmentNum = count;if(datapackage.datasize != 1400){datapackage.end = 1;}else{datapackage.end = 0;}char sendbuffer[1500];memcpy(sendbuffer, &datapackage, sizeof(sendbuffer));udpsocket.sendbuf(sendbuffer, sizeof(sendbuffer), dstip, dstport);       if(datapackage.end == 1){break;}count++;}udpsocket.Close();
}//传输文本文件的函数
void sendTextFile(){string dstip = "162.105.85.198";unsigned short dstport = 51002;UDPSocket udpsocket;udpsocket.create(20021);string file1;cout << "Please input file name: " << endl;cin >> file1;ifstream in(file1);  string filename;  string line;  int count = 1;//按行读取while (getline (in, line))  {DataPackage datapackage;int i;for(i = 0; i < line.size(); i++){datapackage.data[i] = line[i];}datapackage.data[i] = '\0';string contentName = "pku/eecs/file/" + file1 + "/segment" + to_string(count);strcpy(datapackage.contentName, contentName.c_str());datapackage.datasize = i + 2;datapackage.segmentNum = count;//如果已经读到了最后一行,那么加上标志位if(in.eof()){datapackage.end = 1;}else{datapackage.end = 0;}char sendbuffer[1500];memcpy(sendbuffer, &datapackage, sizeof(sendbuffer));udpsocket.sendbuf(sendbuffer, sizeof(sendbuffer), dstip, dstport);       count++;}udpsocket.Close();
}int main(){//按照你向测试的函数调用即可//sendTextFile();//sendBinFile();return 0;
}

接收端是对应的:

#include "UDPSocket.h"
#include "Package.h"#include <unordered_map>
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <fstream>
using namespace std;//接收二进制文件
void receiveBinFile(char* filename){ofstream outfile(filename, ios::binary);UDPSocket udpsocket;udpsocket.create(51002);char recvBuf[1500];string srcip_;unsigned short sport_;int lenrecv;while (true){lenrecv = udpsocket.recvbuf(recvBuf, 1500, srcip_, sport_);if(lenrecv < 0){cout << "[Error] udpSocket recv error" << endl;break;}DataPackage datapackage;memcpy(&datapackage, recvBuf, sizeof(DataPackage));outfile.write(datapackage.data, datapackage.datasize);//判断是不是最后一个if(datapackage.end == 1) break;}udpsocket.Close();outfile.close();
}//接收文本文件
void receiveTextFile(char* filename){ofstream outfile(filename);UDPSocket udpsocket;udpsocket.create(51002);char recvBuf[1500];string srcip_;unsigned short sport_;int lenrecv;while (true){lenrecv = udpsocket.recvbuf(recvBuf, 1500, srcip_, sport_);if(lenrecv < 0){cout << "[Error] udpSocket recv error" << endl;break;}DataPackage datapackage;memcpy(&datapackage, recvBuf, sizeof(DataPackage));outfile << datapackage.data << endl;//判断是不是最后一行if(datapackage.end == 1) break;}udpsocket.Close();outfile.close();
}int main(){//按需调用,注意传参数为想要保存的文件名称和地址//receiveTextFile("test2.txt");receiveBinFile("11583.mp3");return 0;
}

除了上面两个收发核心代码之外,我定义了传输数据包的格式,以及自己封装了udp socket供调用

Package.h

#ifndef __PACKAGE_H__
#define __PACKAGE_H__#include <string.h>
#include <iostream>
using namespace std;struct DataPackage{/*** 内容名字 忽略即可*/char contentName[50];/*** 具体数据,我只是初步定于1400字节,因为考虑到IP的MTU是1500字节*/char data[1400];/*** 数据长度*/int datasize;/*** 包序号,排序用的*/int segmentNum;/*** 是否为最后一个包* 不是: end = 0* 是: end = 1*/int end;DataPackage(const char* _contentName, const char* _data, int _size, int _segmentNum, int _end){strcpy(contentName, _contentName);strcpy(data, _data);datasize = _size;segmentNum = _segmentNum;end = _end;}DataPackage(){}bool operator==(const DataPackage rhs) const{//return (this->segmentNum == rhs.segmentNum && this->datasize == rhs.datasize && strlen(this->contentName) == strlen(rhs.contentName) && strncmp(this->contentName, rhs.contentName, sizeof(this->contentName)));return (strlen(this->contentName) == strlen(rhs.contentName) && strncmp(this->contentName, rhs.contentName, sizeof(this->contentName)) == 0);}bool operator < (const DataPackage rhs) const{string contentstr1 = this->contentName;string contentstr2 = rhs.contentName;return contentstr1 < contentstr2;}
};#endif

以及封装的udp socket

UDPSocket.h

#pragma once
#ifndef UDPSOCKET_H
#define UDPSOCKET_H
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include<time.h>
#include<string>
#include<unistd.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<iostream>
using std::string;
class UDPSocket
{public:UDPSocket();~UDPSocket();int create(unsigned short port);//绑定端口int create();int create(string mcastip,int mcastport);int sendbuf(char *buf,int buflen,string destip,unsigned short destport);int recvbuf(char *buf,int buflen,string&srcip,unsigned short &srcport);int Close();int sock;int m_sock;};
#endif

UDPSocket.cpp

#include"UDPSocket.h"
#include<iostream>
//#include<WinSock2.h>UDPSocket::UDPSocket()
{}
UDPSocket::~UDPSocket()
{close(sock);
}
int UDPSocket::create()
{sock=socket(AF_INET,SOCK_DGRAM,0);if(sock<0){std::cout<<"socket initialize error"<<std::endl;close(sock);return -1;} return sock;
}
int UDPSocket::create(unsigned short port)
{//struct sockaddr_in localaddr;sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){std::cout << "socket initialize error" << std::endl;close(sock);return -1;}struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(port);//int addr_len = sizeof(addr);setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, NULL, 0);int ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));if (ret == -1){std::cout << "socket bind error" << std::endl;close(sock);return -1;}return sock;
}
int UDPSocket::create(string mcastip,int mcastport)
{struct sockaddr_in addr;struct ip_mreq mreq;u_int yes = 1;if ((m_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0){std::cout << "mcastsocket error" << std::endl;return -1;}if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(yes)) < 0){std::cout << "setsockopt error" << std::endl;return -1;}memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(mcastport);if (bind(m_sock, (struct sockaddr*)&addr, sizeof(addr))!=0){std::cout << "msockt bind error" << std::endl;return -1;}mreq.imr_multiaddr.s_addr = inet_addr(mcastip.c_str());mreq.imr_interface.s_addr = htonl(INADDR_ANY);if (setsockopt(m_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){std::cout << "msockt bind error" << std::endl;return -1;}return m_sock;
}
int UDPSocket::sendbuf(char *buf,int buflen,string destip,unsigned short destport)
{struct sockaddr_in dstaddr;memset(&dstaddr, 0, sizeof(dstaddr));dstaddr.sin_family = AF_INET;dstaddr.sin_addr.s_addr = inet_addr(destip.c_str());dstaddr.sin_port = htons(destport);return sendto(sock, buf, buflen, 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr));
}
int UDPSocket::recvbuf(char *buf, int buflen, string &srcip, unsigned short  &srcport)
{struct sockaddr_in srcaddr;int from_addr_len = sizeof(struct sockaddr);int recvsize;recvsize = recvfrom(sock,buf,buflen,0,(struct sockaddr *)&srcaddr,(socklen_t *)&from_addr_len);if (recvsize > 0){srcip = inet_ntoa(srcaddr.sin_addr);srcport = ntohs(srcaddr.sin_port);}return recvsize;
}
int UDPSocket::Close()
{close(sock);return 0;
}

这样写了Makefile之后,收发两端都把datapackage.h UDPSocket.h UDPSocket.cpp 包括进去,编译运行即可,即可实现发端读取文件并按照包的形式UDP发送,收端接收到包存储即可.

Linux c++ udp按包发送接收文件相关推荐

  1. Linux内核网络数据包发送(二)——UDP协议层分析

    Linux内核网络数据包发送(二)--UDP协议层分析 1. 前言 2. `udp_sendmsg` 2.1 UDP corking 2.2 获取目的 IP 地址和端口 2.3 Socket 发送:b ...

  2. Linux内核网络协议栈:udp数据包发送(源码解读)

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  3. Linux内核网络udp数据包发送(二)——UDP协议层分析

    1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...

  4. Linux内核网络UDP数据包发送(三)——IP协议层分析

    1. 前言 Linux内核网络 UDP 协议层通过调用 ip_send_skb 将 skb 交给 IP 协议层,本文通过分析内核 IP 协议层的关键函数来分享内核数据包发送在 IP 协议层的处理,并分 ...

  5. Linux内核网络数据包发送(四)——Linux netdevice 子系统

    Linux内核网络数据包发送(四)--Linux netdevice 子系统 1. 前言 2. `dev_queue_xmit` and `__dev_queue_xmit` 2.1 `netdev_ ...

  6. 分析udp数据报_Linux内核网络udp数据包发送(二)——UDP协议层分析

    1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...

  7. Linux内核网络数据包发送(三)——IP协议层分析

    Linux内核网络数据包发送(三)--IP协议层分析 1. 前言 2. `ip_send_skb` 3. `ip_local_out` and `__ip_local_out` 3.1 netfilt ...

  8. Linux内核网络数据包发送(一)

    Linux内核网络数据包发送(一) 1. 前言 2. 数据包发送宏观视角 3. 协议层注册 4. 通过 socket 发送网络数据 4.1 `sock_sendmsg`, `__sock_sendms ...

  9. 如何快速优化 Linux 内核 UDP 收包效率? | CSDN 博文精选

    作者 | dog250 责编 | 郭芮 出品 | CSDN 博客 现在很多人都在诟病Linux内核协议栈收包效率低,不管他们是真的懂还是一点都不懂只是听别人说的,反正就是在一味地怼Linux内核协议栈 ...

最新文章

  1. [转]建一个XMLHttpRequest对象池
  2. 单脉冲雷达的相干干扰的研究文章_什么是量子纠缠和量子退相干?这个比喻太绝了!...
  3. 介绍了如何取成员函数的地址以及调用该地址
  4. 牛客IOI周赛26-提高组(逆序对,对序列,未曾设想的道路) 题解
  5. vue 接口节流_vue输入节流,避免实时请求接口的实例代码
  6. 4am永远 鼠标按键设置_4AM碾压性夺冠创PCL历史!韦神赛后采访彰显霸气
  7. 唯一《可解释机器学习》中文书来了:复旦研究生翻译,原作者转发点赞
  8. android代码使用adb,如何使用adb在Android 11上触发BroadcastReceiver?
  9. iText 生成复杂表格
  10. 网站开发流程以及HTML5简介(七)
  11. imagenet标签
  12. Firefox如何给页面权限
  13. window本地代理及共享端口445修改
  14. 解锁加密音乐,支持mgg mflac ncm kgm qmc等
  15. python UIAutomator2使用教程
  16. Arch Linux下解决zip解压乱码的方法
  17. SSD目标检测的个人总结(1)—— 锚框的生成
  18. OFD格式如何在线转成PDF?
  19. 高可用分布式存储 etcd 的实现原理
  20. 备受瞩目的Instant App即将到来

热门文章

  1. python和java学哪个好-Python VS Java,学哪个更有前途?
  2. 5岁自学python编程-25 岁才开始学习python晚吗?40 岁都不晚!
  3. python工资一般多少p-Python里的黄金库,学会了你的工资至少翻一倍
  4. python学了有什么用-让孩子学了Python编程有什么用
  5. 为何python不好找工作-为什么说Python不好找工作?原因在这里!
  6. python是什么意思中文、好学吗-Python的前景和Python好不好学呢?
  7. 语音识别的原理_语音识别原理_语音识别原理框图 - 云+社区 - 腾讯云
  8. jQuery-动画排队
  9. java progressbar swt_SWT(JFace)体验之ProgressBar
  10. perl linux 独立运行,Perl脚本打包为独立执行程序