UDP批量文件传输服务端接收端实现(一)发送端

#ifndef _MULTI_NET_UTIL_H__
#define _MULTI_NET_UTIL_H__


#include <iostream>
#include <vector>
#include <map>
#ifdef WIN32
#include <WinSock2.h>
#else
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/socket.h>
#endif

#ifdef WIN32
#define OUT_CLASS
#ifdef OUT_CLASS  
#define OUT_EX_CLASS _declspec(dllexport)  
#else  
#define OUT_EX_CLASS _declspec(dllimport)  
#endif  
#endif

class UDPNetShare;

typedef struct _CIPInfo {
	std::string strIP;
	int nPort;
	int nChannel;
	_CIPInfo()
	{
		strIP = "";
		nPort = 5000;
		nChannel = 0;
	}
}CIPPort;

typedef struct  _DataInfo{
	int nChannel;
	char* pBuf;
	int nSize;
}DataInfo;
#ifdef WIN32
class OUT_CLASS MultiNetUtil
#else
class MultiNetUtil
#endif
{
public:
	//传入本地绑定接口
	MultiNetUtil();

	~MultiNetUtil();

	bool InitSocket(int nPort);

public:
	bool AddIpPort(std::string strIp, int nPort, int nChannel);
	int PushData(int nChannel, int nTotalSize, char* pBuf);

	bool SetSleepTime(int nTime) { m_nTime = nTime; return true; }

private:
	//服务器需要向这些ip或者端口发送消息
	std::vector<CIPPort> m_arrIPPort;
	int m_nTime;
#ifdef WIN32
	SOCKET m_sock;
#else
	int m_sock;
#endif
	sockaddr_in m_clientaddr;
	sockaddr_in m_servaddr;

public:
	std::vector<DataInfo*> m_arrData;
	std::map<int, UDPNetShare*> m_mapNetUtil;
};

#ifdef WIN32
__declspec(dllexport) MultiNetUtil* createNetUtil();
#else
MultiNetUtil* createNetUtil();
#endif
#endif
#include "MultiNetUtil.h"
#include "UDPNetShare.h"
#include <pthread.h>

#include "sysfun.h"

using namespace std;

CThreadLock g_RoundLock;

#ifdef WIN32
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "pthreadVC2.lib")
#endif

MultiNetUtil::MultiNetUtil():m_nTime(3)
{
#ifdef WIN32
	WSAData wsa;
	WSAStartup(2, &wsa);
#endif
}

MultiNetUtil::~MultiNetUtil()
{
#ifdef WIN32
	WSACleanup();
#endif
}

void* IdleRoundThread(void* pArgs)
{
	MultiNetUtil* pUtil = (MultiNetUtil*)pArgs;
	if (pUtil != NULL)
	{
		while (true)
		{
			if (pUtil->m_arrData.size() > 0)
			{
				g_RoundLock.Lock();
				std::vector<DataInfo*>::iterator iterInfo = pUtil->m_arrData.begin();
				std::map<int, UDPNetShare*>::iterator iterObj = pUtil->m_mapNetUtil.find((*iterInfo)->nChannel);
				if (iterObj != pUtil->m_mapNetUtil.end())
				{
					iterObj->second->PushData((*iterInfo)->nSize, (*iterInfo)->pBuf);
					cout << "nChannel:" << (*iterInfo)->nChannel << "-DataSize:" << pUtil->m_arrData.size() << "-IpPort Size:" << pUtil->m_mapNetUtil.size() << endl;
				}
				pUtil->m_arrData.erase(iterInfo);
				nsleep(1);
				g_RoundLock.UnLock();
			}
			else
			{
				nsleep(10);
			}
		}
	}
	return NULL;
}

MultiNetUtil* createNetUtil()
{
	return new MultiNetUtil();
}

bool MultiNetUtil::InitSocket(int nPort)
{
	m_sock = socket(AF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
	if (m_sock == INVALID_SOCKET)
#else
	if(m_sock < 0)
#endif
	{
		cout << "create error " << endl;
		return false;
	}
		

	m_servaddr.sin_family = AF_INET;
#ifdef WIN32
	m_servaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
	m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
	m_servaddr.sin_port = htons(nPort);

	if (bind(m_sock, (sockaddr*)&m_servaddr, sizeof(sockaddr)) < 0)
	{
		cout << "error bind" << endl;
		return false;
	}

	//创建发送循环线程
	pthread_t pid;
	if (pthread_create(&pid, NULL, IdleRoundThread, this) != 0)
	{

		cout << "thread round create failed" << endl;
		return false;
	}
	else
	{
		pthread_detach(pid);
		cout << "thread round create success" << endl;
	}
	return true;
}

bool MultiNetUtil::AddIpPort(std::string strIp, int nPort, int nChannel)
{
	CIPPort sip;
	sip.nChannel = nChannel;
	sip.nPort = nPort;
	sip.strIP = strIp;

	m_arrIPPort.push_back(sip);

	//创建发送类
	UDPNetShare *pShare = new UDPNetShare;
	pShare->SetSleepTime(m_nTime);
	pShare->InitWith(m_sock);
	pShare->InitIPPort(strIp.c_str(), nPort);
	m_mapNetUtil[nChannel] = pShare;
	return true;
}

int MultiNetUtil::PushData(int nChannel, int nTotalSize, char* pBuf)
{
	DataInfo * pData = new DataInfo;
	pData->nChannel = nChannel;
	pData->nSize = nTotalSize;
	pData->pBuf = pBuf;
	g_RoundLock.Lock();
	m_arrData.push_back(pData);
	g_RoundLock.UnLock();
	return m_arrData.size();
}

公共函数:

#ifndef _SYS_FUN_H__
#define _SYS_FUN_H__
#ifdef WIN32
#include <windows.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif
#include <pthread.h>

//#define WIN32

#ifdef WIN32
#define nsleep  Sleep
#else
#define nsleep  usleep
#endif

class CThreadLock
{
public:
	CThreadLock() { pthread_mutex_init(&m_lock, NULL); }
	~CThreadLock() { pthread_mutex_destroy(&m_lock); }

public:
	void Lock() { pthread_mutex_lock(&m_lock); }
	void UnLock() { pthread_mutex_unlock(&m_lock); }

private:
	pthread_mutex_t m_lock;
};

#endif
#ifndef _UDP_NET_SHARE_H__
#define _UDP_NET_SHARE_H__

#include <vector>
#include <iostream>
#include <map>
#ifdef WIN32
#include <WinSock2.h>
#else
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/socket.h>
#endif
#include "sysfun.h"


#define MAX_BUFFER 65535
#define PACKSIZE 65000

typedef struct _NetData {
	int nIndex;
	int nBufSize;
	bool bFinish;
	char buffer[PACKSIZE];
	int nTotalSize;
}NetData;

class UDPNetShare
{
public:
	UDPNetShare();									//實例化
	~UDPNetShare();
#ifdef WIN32
	bool InitWith(SOCKET sock);						//初始化端口
#else	
	bool InitWith(int sock);	
#endif
	int PushData(int nSize, char* pBuf);			//推送數據

	bool InitIPPort(const char* strIP, int nPort);	//發送端口

	bool SetSleepTime(int time);					//发送间隔时间
	bool GetClientSleep() { return m_SleepTime; }   //获取休眠时间

	std::vector<std::map<int, char*>> m_arrData;	//存储发不完的数据
#ifdef WIN32
	SOCKET m_sock;									//socket
#else
	int m_sock;
#endif
	sockaddr_in m_clientaddr;						//發送地址
	int m_SleepTime;								//發送休眠時間

public:
	CThreadLock m_lock;
};

#endif

#include "UDPNetShare.h"
#include "sysfun.h"

#include "sysfun.h"

using namespace std;

UDPNetShare::UDPNetShare():m_SleepTime(3)
{

}

UDPNetShare::~UDPNetShare()
{

}

#ifdef WIN32
bool UDPNetShare::InitWith(SOCKET sock)
{
	m_sock = sock;
	return true;
}
#else
bool UDPNetShare::InitWith(int sock)
{
	m_sock = sock;
	return true;
}	
#endif

int UDPNetShare::PushData(int nSize, char* pBuf)
{
	std::map<int, char*> mapData;
	mapData.insert(std::pair<int, char*>(nSize, pBuf));
	m_lock.Lock();
	m_arrData.push_back(mapData);
	cout << "push data-------------------------size:" << m_arrData.size() << endl;
	m_lock.UnLock();
	return m_arrData.size();
}

void* IdleSendDataThread(void* pArgs)
{
	UDPNetShare* pShare = (UDPNetShare*)pArgs;
	while (1)
	{
		if (pShare->m_arrData.size() > 0)
		{
				pShare->m_lock.Lock();
				std::vector<std::map<int, char*>>::iterator iterData = pShare->m_arrData.begin();
				{
					std::map<int, char*>::iterator iterMap = iterData->begin();
					NetData pack;
					int t_nCount = iterMap->first / PACKSIZE;
					int t_nMod = iterMap->first % PACKSIZE;
					if (t_nMod != 0)
						t_nCount += 1;
					memset(pack.buffer, '\0', PACKSIZE);
					pack.bFinish = false;
					pack.nIndex = 0;
					pack.nBufSize = 0;
					pack.nTotalSize = 0;
					for (int j = 1; j <= t_nCount; ++j)
					{
						pack.nIndex = j;
						pack.nTotalSize = iterMap->first;
						if (j < t_nCount)
						{
							pack.bFinish = false;
							pack.nBufSize = PACKSIZE;
							memcpy(pack.buffer, iterMap->second + PACKSIZE*(j - 1), PACKSIZE);
						}
						else
						{
							printf("finish\n");
							pack.bFinish = true;
							pack.nBufSize = iterMap->first - PACKSIZE*(t_nCount - 1);
							memcpy(pack.buffer, iterMap->second + PACKSIZE*(j - 1), pack.nBufSize);
						}
						int ret = sendto(pShare->m_sock, (char*)&pack, sizeof(NetData), 0, (sockaddr*)&(pShare->m_clientaddr), sizeof(pShare->m_clientaddr));
						if (ret > 0)
							printf("Send %d OK To Server\n", pack.nIndex);
						nsleep(pShare->GetClientSleep()*1000);
					}
					free(iterMap->second);
					pShare->m_arrData.erase(iterData);
					cout << "pop data**************************size:" << pShare->m_arrData.size() << endl;
					pShare->m_lock.UnLock();
					printf("finish--\n");
				}
		}
		else
		{
			nsleep(1000);
		}
	}
}

bool UDPNetShare::InitIPPort(const char* strIP, int nPort)
{
	int addrLen = sizeof(struct sockaddr_in);
	cout << "socket create success" << endl;
	m_clientaddr.sin_family = AF_INET;
	m_clientaddr.sin_port = htons(nPort);
#ifdef WIN32
	m_clientaddr.sin_addr.S_un.S_addr = inet_addr(strIP);
#else
	m_clientaddr.sin_addr.s_addr = inet_addr(strIP);
#endif
	//启动线程
	pthread_t pid;
	if (pthread_create(&pid, NULL, IdleSendDataThread, this) != 0)
	{

		cout << "thread send create failed" << endl;
		return false;
	}
	else
	{
		pthread_detach(pid);
		cout << "thread send create success" << endl;
	}

	return true;
}

bool UDPNetShare::SetSleepTime(int time)
{
	m_SleepTime = time;
	return true;
}

Makefile

CC = g++ -std=c++11


cflags = -I. #./libevent/include
INC = -L. #libevent/lib


SRCS = MultiNetUtil.cpp UDPNetShare.cpp


C_FLAGS = -lpthread #-levent_core -levent_extra -levent_openssl -levent_pthreads
# -lopencv_imgcodecs

LIBRARY = libmultinetutil.so

all:
	$(CC) $(SRCS) $(C_FLAGS) -fPIC --shared -O2  -g -o $(LIBRARY) $(INC) $(cflags)
	cp $(LIBRARY) ./test
	cp MultiNetUtil.h ./test
	cp sysfun.h     ./test
clean:
	rm libmultinetutil.so

测试程序:

#include "MultiNetUtil.h"
#include "sysfun.h"

#ifdef WIN32
#pragma comment(lib, "MultiNetUtil.lib")
#endif

using namespace std;

int main(void)
{
	cout << "hello start" << endl;
	MultiNetUtil *pShare = createNetUtil();
	pShare->InitSocket(6666);
	char chBuf[100] = "123456hg";
	pShare->SetSleepTime(10);

	for (int i = 0; i < 1; i++)
		pShare->AddIpPort("127.0.0.1", 9999+i, i);

	int nIndex = 0;
	int nChannel = 0;
	
	cout << "Add Data" << endl;

	for (int i = 1; i < 41; i++)
	{
		sprintf(chBuf, "/home/long/Databases/netimg/sendimg/%d.jpg", i);
		FILE * fp = fopen(chBuf, "rb");
		if (fp == NULL)
		{
			cout << "Open file Error" << endl;
			return -1;
		}
		int size = 0;
		fseek(fp, 0, SEEK_END);
		size = ftell(fp);

		fseek(fp, 0, SEEK_SET);
		//rewind(fp);

		char * tmpBuf = (char*)malloc(size);
		fread(tmpBuf, 1, size, fp);

		pShare->PushData(nChannel, size, tmpBuf);
		fclose(fp);
		
		nChannel++;
		if (nChannel == 1)
		{
			nChannel = 0;
		}
		nIndex++;
		cout << "total number========================:" << nIndex << endl;
		if(nIndex == 40)
			break;
		usleep(300);
		
		if (i == 40)
			i = 0;
	}
	cout << "Send Over" << endl;
	//nsleep(100000);
	cout << "hello endl" << endl;
	getchar();
	return 0;
}


测试程序Makefile

CC = g++ -std=c++11


cflags = -I.#./libevent/include
INC = -L. # ../libevent/lib -L ./


SRCS = test.cpp


C_FLAGS = -lpthread -lmultinetutil #-levent_core -levent_extra -levent_openssl -levent_pthreads
# -lopencv_imgcodecs

LIBRARY = test

all:
	$(CC) $(SRCS) $(C_FLAGS) -O2  -g -o $(LIBRARY) $(INC) $(cflags)
	#cp $(LIBRARY) /home/VideoAnalysis/Bin/
clean:
	rm test

发送接受源码

https://download.csdn.net/download/chnim/10499799

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

telllong

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值