#ifndef _TCP_NET_SHARE_CLIENT_H__
#define _TCP_NET_SHARE_CLIENT_H__
#include <iostream>
#include <vector>
#include <map>
#include "sysfun.h"
#define MAX_BUFFER 65535
#define PACKSIZE 65000
#ifdef WIN32
#define OUT_CLASS
#ifdef OUT_CLASS
#define OUT_EX_CLASS _declspec(dllexport)
#else
#define OUT_EX_CLASS _declspec(dllimport)
#endif
#endif
#ifdef WIN32
class OUT_EX_CLASS TCPNetShareClient
{
#else
class TCPNetShareClient
{
#endif
public:
TCPNetShareClient();
virtual ~TCPNetShareClient();
//�ͻ��˶˳�ʼ��Socket
lcmf_net_error InitWithPort(int port);
//�ͻ������ӷ�����ip��˿�
lcmf_net_error ConnectServer(const char* strIP, int nPort);
//设置缓冲区大小
int SetTmpBuffer(int nSize);
int GetTmpBuffer();
int RecvData(int *nSize, char** pData);
public:
std::vector<std::map<int, char*>> m_arrData;
#ifdef WIN32
SOCKET m_sock;
#else
int m_sock;
#endif
CThreadLock m_RecvLock;
int m_nbufsize;
};
#ifdef WIN32
OUT_EX_CLASS TCPNetShareClient* createNetUtil();
#else
TCPNetShareClient* createNetUtil();
#endif
#endif
#include "TCPNetShareClient.h"
#ifdef WIN32
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "pthreadVC2.lib")
#endif
#define BEGIN_NUM 19900711
#define DATA_NUM 20160113
#define END_NUM 11700991
#define BLOCK_DATA_SIZE (10 * 1024)
#define FILE_HEAD 4
#define BLOCK_HEAD 4
using namespace std;
TCPNetShareClient* createNetUtil()
{
return new TCPNetShareClient();
}
TCPNetShareClient::TCPNetShareClient():m_nbufsize(2000000)
{
}
TCPNetShareClient::~TCPNetShareClient()
{
}
//设置缓冲区大小
int TCPNetShareClient::SetTmpBuffer(int nSize)
{
m_nbufsize = nSize;
if(setsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, &m_nbufsize, sizeof(int)) == -1)
{
return -1;
}
return m_nbufsize;
}
int TCPNetShareClient::GetTmpBuffer()
{
return m_nbufsize;
}
//�ͻ��˶˳�ʼ��Socket
lcmf_net_error TCPNetShareClient::InitWithPort(int port)
{
m_sock = socket(AF_INET, SOCK_STREAM, 0);
#ifdef WIN32
if(m_sock == INVALID_SOCKET)
#else
if (m_sock <= 0)
#endif
{
cout << "create socket error" << endl;
return lcmf_net_error_createsocket;
}
sockaddr_in cliaddr;
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(port);
#ifdef WIN32
cliaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
if (bind(m_sock, (struct sockaddr*)&cliaddr, sizeof(sockaddr)) < 0)
{
cout << "bind error port:" << port << endl;
return lcmf_net_error_bindport;
}
cout << "bind success port:" << port << endl;
sockaddr_in testaddr;
#ifdef WIN32
int ntestsocklen = sizeof(sockaddr);
#else
socklen_t ntestsocklen = sizeof(sockaddr);
#endif
getsockname(m_sock, (struct sockaddr*)&testaddr, &ntestsocklen);
string stmp = inet_ntoa(testaddr.sin_addr);
int nPort = testaddr.sin_port;
cout << "port:" << nPort << "ip:" << stmp.c_str() << "--connect can use? 1" << endl;
cout << "set no block" << endl;
//int flags = fcntl(m_sock, F_GETFL, 0); //获取文件的flags值。
//fcntl(m_sock, F_SETFL, flags | O_NONBLOCK); //设置成非阻塞模式;
return lcmf_net_error_success;
}
#if 0
void RecvNetData(void* pArgs)
{
TCPNetShareClient *pUtil = (TCPNetShareClient*)pArgs;
if (pUtil != NULL)
{
char *eachBuf = new char[BLOCK_DATA_SIZE + 2 * FILE_HEAD];
memset(eachBuf, 0, BLOCK_DATA_SIZE + 2 * FILE_HEAD);
unsigned int RecvNum = 0, flag_status = 0, flag_recv = 1;
unsigned int dwFileSize = 0;
#if 0
FILE *fp;
fp = fopen(FILENAME, "wb");
#endif
//1、读取第一组数据,获取文件大小,建立连接
niubiflag:
cout << "recv header: " << endl;
recv(pUtil->m_sock, eachBuf, 2 * FILE_HEAD, 0);//----------------recv
cout << "recv header: " << eachBuf << "end" << endl;
char charFileSize[4] = { 0 };
memcpy(charFileSize, eachBuf, FILE_HEAD); //拷贝前4个字节
for (int i = 0; i < 4; i++)
{
flag_status += ((unsigned char)charFileSize[i]) << (8 * (4 - i - 1)); //获取文件起始符
}
memcpy(charFileSize, eachBuf + FILE_HEAD, FILE_HEAD); //拷贝第5-8个字节
for (int i = 0; i < 4; i++)
{
dwFileSize += ((unsigned char)charFileSize[i]) << (8 * (4 - i - 1)); //获取文件大小
}
int start = clock();
cout << "start recv data, datasize: " << dwFileSize << endl;
{
//开辟接收内存
int DataPos = 0;
char *FileBuffer = new char[dwFileSize];
memset(FileBuffer, 0, dwFileSize);
cout << "malloc memery" << endl;
while (1)
{
cout << "recv" << endl;
int ret = recv(pUtil->m_sock, eachBuf, BLOCK_DATA_SIZE, 0);
cout << "recv end" << endl;
if (ret <= 0 || ret == 8 || ret < BLOCK_DATA_SIZE)
break;
cout << "Get Data Size: " << ret << endl;
memcpy(FileBuffer + DataPos, eachBuf, ret);
DataPos = DataPos + ret;
}
//fwrite(FileBuffer, dwFileSize, 1, fp);
//fclose(fp);
cout << "get data size----: " << DataPos << endl;
std::map<int, char*> mapData;
char* tmpData = (char*)malloc(dwFileSize);
memcpy(tmpData, FileBuffer, dwFileSize);
mapData.insert(std::pair<int, char*>(dwFileSize, FileBuffer));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
goto niubiflag;
delete eachBuf;
delete FileBuffer;
}
int end = clock();
std::cout << "time:" << end - start << "ms" << RecvNum << std::endl;
}
}
void* IdleNetRecvDataThread(void* args)
{
TCPNetShareClient *pUtil = (TCPNetShareClient*)args;
if (pUtil != NULL)
{
#ifdef WIN32
if(pUtil->m_sock != INVALID_SOCKET)
#else
if (pUtil->m_sock >= 0)
#endif
{
while (true)
{
//RecvNetData(pUtil);
unsigned char* lenbuf = (unsigned char*)malloc(14);
int len = recv(pUtil->m_sock, (unsigned char*)lenbuf, 14, 0);
if (len > 0)
{
if(lenbuf[0] == '0' && lenbuf[1] == '1' && lenbuf[2] == '1' && lenbuf[3] == 'A' && lenbuf[4] == 'D')
{
char tmpSize[10] = "0";
memcpy(tmpSize, lenbuf + 5, 9);
cout << "niubi class :" << tmpSize << endl;
const int nSize = atoi(tmpSize);
cout << "Get nSize ------------------: "<< nSize << endl;
unsigned char* ptmpbuf = (unsigned char*)malloc(TCP_MAX_BUFFER);
int len1 = recv(pUtil->m_sock, (unsigned char*)ptmpbuf, nSize, 0);
if(len1 > 0)
{
std::map<int, char*> mapData;
cout << "complete recv size: " << len1 << endl;
cout << "get nsize: " << nSize << endl;
{
unsigned char* tmpData = (unsigned char*)malloc(nSize);
memcpy(tmpData, ptmpbuf, nSize);
mapData.insert(std::pair<int, char*>(nSize, (char*)tmpData));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
}
}
}
}
}
}
}
return NULL;
}
#endif
#define MXB 165000
void* IdleRecvDataThread(void* args)
{
TCPNetShareClient *pUtil = (TCPNetShareClient*)args;
if (pUtil != NULL)
{
#ifdef WIN32
if(pUtil->m_sock != INVALID_SOCKET)
#else
if (pUtil->m_sock >= 0)
#endif
{
time_t timeStart = time(NULL);
RECVDATA data;
//data.pBuf = (char*)malloc(1024 * 10000000);
BYTE* buffer = new BYTE[TCP_MAX_BUFFER];
int m_recvCount = 0;
int nSize = 0;
int nIndex = 0;
unsigned char* ptmpbuf = (unsigned char*)malloc(MXB);
while (true)
{
memset(ptmpbuf, '\0', MXB);
//cout << "wait data--" << endl;
//int len = recv(pUtil->m_sock, (char*)ptmpbuf, TCP_MAX_BUFFER, 0);
//int len = recv(pUtil->m_sock, (char*)ptmpbuf, MXB, MSG_DONTWAIT);
int len = recv(pUtil->m_sock, (unsigned char*)ptmpbuf, MXB, 0);
if (len > 0)
{
#if 0
std::map<int, char*> mapData;
char* tmpData = (char*)malloc(len);
cout << "recv size:" << len << endl;
memcpy(tmpData, buffer, len);
mapData.insert(std::pair<int, char*>(len, tmpData));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
#endif
cout << "recv Data**" << endl;
//cout << ptmpbuf[0] << ptmpbuf[1] << ptmpbuf[2] << ptmpbuf[3] << endl;
if(ptmpbuf[0] == '0' && ptmpbuf[1] == '1' && ptmpbuf[2] == '1' && ptmpbuf[3] == 'A' && ptmpbuf[4] == 'D')
{
cout << "get header---------------------------------------------------------------new --" << endl;
if(m_recvCount != 0)
{
std::map<int, char*> mapData;
cout << "complete recv size: " << m_recvCount << endl;
cout << "get nsize: " << nSize << endl;
if(nSize == m_recvCount)
{
unsigned char* tmpData = (unsigned char*)malloc(nSize);
memset(tmpData, '\0', nSize);
memcpy(tmpData, buffer, nSize);
char strName[20];
sprintf(strName, "./jpg/img-%d.jpg", nIndex++);
FILE* fp = fopen(strName, "wb");
if(fp != NULL)
{
if(fwrite(tmpData, 1, nSize, fp) < nSize)
{
cout << "write size error:" << nSize << endl;
}
fclose(fp);
}
mapData.insert(std::pair<int, char*>(nSize, (char*)tmpData));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
memset(buffer, '\0', TCP_MAX_BUFFER);
m_recvCount = 0;
nSize = 0;
}
else
{
cout << "this is a uhly pix" << endl;
memset(buffer, '\0', TCP_MAX_BUFFER);
m_recvCount = 0;
nSize = 0;
}
}
char tmpSize[10] = "0";
memcpy(tmpSize, ptmpbuf + 5, 9);
cout << "niubi class :" << tmpSize << endl;
nSize = atoi(tmpSize);
cout << "Get nSize ------------------: "<< nSize << endl;
memset(buffer, '\0', TCP_MAX_BUFFER);
memcpy(buffer + m_recvCount, ptmpbuf + 14, len - 14);
cout << "usedata size=: " << len -14 << endl;
m_recvCount += len;
m_recvCount -= 14;
}
else
{
cout << "not header========" << len << endl;
if(TCP_MAX_BUFFER < (m_recvCount + len))
{
m_recvCount = 0;
nSize = 0;
memset(buffer, '\0', TCP_MAX_BUFFER);
}
usleep(3000);
memcpy(buffer + m_recvCount, ptmpbuf, len);
m_recvCount += len;
if(nSize < m_recvCount)
{
nSize = 0;
m_recvCount = 0;
memset(buffer, '\0', TCP_MAX_BUFFER);
}
usleep(3000);
}
//结束发送数据标志
timeStart = time(NULL);
}
// memset(ptmpbuf, '\0', MXB);
if(len <= 0)
{
//cout << "get no data" << endl;
time_t timeEnd = time(NULL);
if(timeEnd - timeStart > 2)
{
if(nSize > 0 && nSize == m_recvCount)
{
std::map<int, char*> mapData;
cout << "complete recv size: " << m_recvCount << endl;
cout << "get nsize: " << nSize << endl;
char* tmpData = (char*)malloc(nSize);
memcpy(tmpData, buffer, nSize);
mapData.insert(std::pair<int, char*>(nSize, tmpData));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
memset(buffer, '\0', TCP_MAX_BUFFER);
m_recvCount = 0;
nSize = 0;
}
}
}
#if 0
BYTE* buffer = new BYTE[MAX_BUFFER];
int fsize = sizeof(sockaddr);
int len = recv(pUtil->m_sock, (char*)buffer, MAX_BUFFER, 0);
if (len == -1)
m_recvCount = 1;
NetData *pack;
pack = (NetData*)buffer;
int iCount = pack->nIndex;
int iBufferSize = pack->nBufSize;
bool bFinish = pack->bFinish;
printf("%d--%d--%d--%d--%s\n", m_recvCount, iCount, iBufferSize, bFinish, "buffer");
if (m_recvCount == iCount)
{
memcpy(data.pBuf + PACKSIZE*(m_recvCount - 1), pack->buffer, iBufferSize);
m_recvCount += 1;
if (bFinish)
{
m_recvCount = 1;
data.nDataSize = pack->nTotalSize;
std::map<int, char*> mapData;
char* tmpData = (char*)malloc(data.nDataSize);
memcpy(tmpData, data.pBuf, data.nDataSize);
mapData.insert(std::pair<int, char*>(data.nDataSize, tmpData));
pUtil->m_RecvLock.Lock();
pUtil->m_arrData.push_back(mapData);
pUtil->m_RecvLock.UnLock();
printf("finish\n");
}
}
else
{
m_recvCount = 1;
}
#ifdef WIN32
Sleep(1);
#else
usleep(1);
#endif
delete buffer;
#endif
}
delete buffer;
free(ptmpbuf);
}
}
}
//�ͻ������ӷ�����ip��˿�
lcmf_net_error TCPNetShareClient::ConnectServer(const char* strIP, int nPort)
{
#ifdef WIN32
if(m_sock == INVALID_SOCKET)
#else
if (m_sock <= 0)
#endif
{
cout << "invalid socket" << endl;
return lcmf_net_error_createsocket;
}
cout << "valid socket" << endl;
sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(nPort);
#ifdef WIN32
servaddr.sin_addr.S_un.S_addr = inet_addr(strIP);
#else
servaddr.sin_addr.s_addr = inet_addr(strIP);
#endif
string stmp = inet_ntoa(servaddr.sin_addr);
int tmpPort = servaddr.sin_port;
cout << "port:" << tmpPort << "ip:" << stmp.c_str() << "--connect can use? 1" << endl;
int err = connect(m_sock, (struct sockaddr *)&servaddr, sizeof(sockaddr));
if (err == 0)
{
cout << "connect server ip:" << strIP << "--port:" << nPort << "success" << endl;
//return lcmf_net_error_success;
}
else
{
cout << "connect server ip:" << strIP << "--port:" << nPort << "failed" << endl;
return lcmf_net_error_connect;
}
#if 1
//create thread to recvdata
pthread_t pid;
if (pthread_create(&pid, NULL, IdleRecvDataThread, this) != 0)
{
cout << "thread recv create failed" << endl;
return lcmf_net_error_createthread;
}
else
{
pthread_detach(pid);
cout << "thread recv create success" << endl;
return lcmf_net_error_success;
}
#endif
#if 0
//create thread to recvdata
pthread_t pid;
if (pthread_create(&pid, NULL, IdleNetRecvDataThread, this) != 0)
{
cout << "thread recv create failed" << endl;
return lcmf_net_error_createthread;
}
else
{
pthread_detach(pid);
cout << "thread recv create success" << endl;
return lcmf_net_error_success;
}
#endif
}
int TCPNetShareClient::RecvData(int *nSize, char** pData)
{
#if 1
// int i = 0;
if (m_arrData.size() > 0)
{
std::vector<std::map<int, char*>>::iterator iterData = m_arrData.begin();
{
m_RecvLock.Lock();
std::map<int, char*>::iterator iterMap = iterData->begin();
#if 0
*nSize = iterMap->first;
*pData = (char*)malloc(*nSize);
cout << "--------size1:" << *nSize << endl;
memcpy(*pData, iterMap->second, *nSize);
free(iterMap->second);
cout << "size2:" << *nSize << endl;
m_arrData.erase(iterData);
cout << "size3:" << *nSize << endl;
#endif
*nSize = iterMap->first;
*pData = iterMap->second;
//char strName[20];
//sprintf(strName, "./jpg/img-%d.jpg", i++);
//FILE* fp = fopen(strName, "wb");
//if(fp != NULL)
// {
// fwrite(*pData, 1, *nSize, fp);
// fclose(fp);
// }
m_arrData.erase(iterData);
m_RecvLock.UnLock();
return 1;
}
}
#endif
return -1;
}
公共函数
#ifndef _SYS_FUN_H__
#define _SYS_FUN_H__
//#define WIN32
#ifdef WIN32
#include <windows.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>
#include <stdio.h>
#include <stdlib.h>
#endif
#include <pthread.h>
//#define WIN32
#ifdef WIN32
#define nsleep Sleep
#else
//#define BYTE unsigned char* 这真是世界第一大bug啊,接受文件总是出错,多加了×号,害得我找了好几天的问题
#define BYTE unsigned char
#define nsleep usleep
#endif
#define MAX_BUFFER 65535
#define TCP_MAX_BUFFER 3400000
#define PACKSIZE 65000
typedef struct _RECVDATA {
int nDataSize;
int nDataIndex;
char* pBuf;
}RECVDATA;
typedef struct _NetData {
int nIndex;
int nBufSize;
bool bFinish;
char buffer[PACKSIZE];
int nTotalSize;
}NetData;
enum lcmf_net_error {
lcmf_net_error_none,
lcmf_net_error_createsocket,
lcmf_net_error_bindport,
lcmf_net_error_connect,
lcmf_net_error_createthread,
lcmf_net_error_success
};
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
Makefile
CC = g++ -std=c++11
cflags = -I. #./libevent/include
INC = -L. #libevent/lib
SRCS = TCPNetShareClient.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
cp TCPNetShareClient.h ./test
clean:
rm libmultinetutil.so
测试程序
#include "TCPNetShareClient.h"
using namespace std;
int main(void)
{
TCPNetShareClient * pClient = createNetUtil();
if(pClient == NULL)
{
cout << "create TCPNetUtilClient failed" << endl;
return -1;
}
pClient->InitWithPort(9999);
pClient->SetTmpBuffer(2000000);
pClient->ConnectServer("127.0.0.1", 6666);
int i = 0;
char strName[100] = "abcde";
for(;;)
{
int nSize = 0;
char* pBuf;
if(pClient->RecvData(&nSize, &pBuf) > 0)
{
sprintf(strName, "./jpg/%d.jpg", i);
i++;
cout << "-=-==-=-=-" << strName << endl;
FILE* fp = fopen(strName, "wb");
fwrite(pBuf, 1, nSize, fp);
fclose(fp);
free(pBuf);
//cout << "-=-==-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-==-=-=-=-=-=-=" << strName << endl;
}
nsleep(1);
}
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
客户端和服务端源文件地址:
源码中有点问题,有一个宏定义写错了
#define BYTE unsigned char*
改成
#define BYTE unsigned char
否则收到文件出错
https://download.csdn.net/download/chnim/10499725
刚开始研究网络传输,看到一些关于粘包的问题,虽然这个例子没有出现这种问题,但是有必要做一下修改
以后有空了再写一个例子
思路是:
将文件名,文件长度,包头标识符放到包头,包头定长便于每次读取,然后在读取数据包时,先去读取文件头获取文件名,打开文件根据获取的文件长度,循环获取数据写入文件,知道将当前文件内容获取完毕,然后在开始获取下一个文件的包头信息如此往复