Linux c++ udp按包发送接收文件
我最近写一个项目的时候需要涉及到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按包发送接收文件相关推荐
- Linux内核网络数据包发送(二)——UDP协议层分析
Linux内核网络数据包发送(二)--UDP协议层分析 1. 前言 2. `udp_sendmsg` 2.1 UDP corking 2.2 获取目的 IP 地址和端口 2.3 Socket 发送:b ...
- Linux内核网络协议栈:udp数据包发送(源码解读)
<监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...
- Linux内核网络udp数据包发送(二)——UDP协议层分析
1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...
- Linux内核网络UDP数据包发送(三)——IP协议层分析
1. 前言 Linux内核网络 UDP 协议层通过调用 ip_send_skb 将 skb 交给 IP 协议层,本文通过分析内核 IP 协议层的关键函数来分享内核数据包发送在 IP 协议层的处理,并分 ...
- Linux内核网络数据包发送(四)——Linux netdevice 子系统
Linux内核网络数据包发送(四)--Linux netdevice 子系统 1. 前言 2. `dev_queue_xmit` and `__dev_queue_xmit` 2.1 `netdev_ ...
- 分析udp数据报_Linux内核网络udp数据包发送(二)——UDP协议层分析
1. 前言 本文分享了Linux内核网络数据包发送在UDP协议层的处理,主要分析了udp_sendmsg和udp_send_skb函数,并分享了UDP层的数据统计和监控以及socket发送队列大小的调 ...
- Linux内核网络数据包发送(三)——IP协议层分析
Linux内核网络数据包发送(三)--IP协议层分析 1. 前言 2. `ip_send_skb` 3. `ip_local_out` and `__ip_local_out` 3.1 netfilt ...
- Linux内核网络数据包发送(一)
Linux内核网络数据包发送(一) 1. 前言 2. 数据包发送宏观视角 3. 协议层注册 4. 通过 socket 发送网络数据 4.1 `sock_sendmsg`, `__sock_sendms ...
- 如何快速优化 Linux 内核 UDP 收包效率? | CSDN 博文精选
作者 | dog250 责编 | 郭芮 出品 | CSDN 博客 现在很多人都在诟病Linux内核协议栈收包效率低,不管他们是真的懂还是一点都不懂只是听别人说的,反正就是在一味地怼Linux内核协议栈 ...
最新文章
- [转]建一个XMLHttpRequest对象池
- 单脉冲雷达的相干干扰的研究文章_什么是量子纠缠和量子退相干?这个比喻太绝了!...
- 介绍了如何取成员函数的地址以及调用该地址
- 牛客IOI周赛26-提高组(逆序对,对序列,未曾设想的道路) 题解
- vue 接口节流_vue输入节流,避免实时请求接口的实例代码
- 4am永远 鼠标按键设置_4AM碾压性夺冠创PCL历史!韦神赛后采访彰显霸气
- 唯一《可解释机器学习》中文书来了:复旦研究生翻译,原作者转发点赞
- android代码使用adb,如何使用adb在Android 11上触发BroadcastReceiver?
- iText 生成复杂表格
- 网站开发流程以及HTML5简介(七)
- imagenet标签
- Firefox如何给页面权限
- window本地代理及共享端口445修改
- 解锁加密音乐,支持mgg mflac ncm kgm qmc等
- python UIAutomator2使用教程
- Arch Linux下解决zip解压乱码的方法
- SSD目标检测的个人总结(1)—— 锚框的生成
- OFD格式如何在线转成PDF?
- 高可用分布式存储 etcd 的实现原理
- 备受瞩目的Instant App即将到来
热门文章
- python和java学哪个好-Python VS Java,学哪个更有前途?
- 5岁自学python编程-25 岁才开始学习python晚吗?40 岁都不晚!
- python工资一般多少p-Python里的黄金库,学会了你的工资至少翻一倍
- python学了有什么用-让孩子学了Python编程有什么用
- 为何python不好找工作-为什么说Python不好找工作?原因在这里!
- python是什么意思中文、好学吗-Python的前景和Python好不好学呢?
- 语音识别的原理_语音识别原理_语音识别原理框图 - 云+社区 - 腾讯云
- jQuery-动画排队
- java progressbar swt_SWT(JFace)体验之ProgressBar
- perl linux 独立运行,Perl脚本打包为独立执行程序