C/C++网络编程:文件传输系统(双协议单线程版)
README
UDP和TCP双协议,UDP控制用户指令,TCP控制文件传输。
用户指令:get file(下载)、put file(上传)、list(列出服务器指定位置文件列表)。
服务端UDP、TCP占用两个端口,双线程同时启动。未使用多线程,所以客户端每次只能接入一个。
cJSON包需要自行下载编译。
同时支持windows、linux操作系统,只需要修改两个socket头文件中引用的库即可,windows用winsock2.h,linux用另外三个。
- 源代码结构图
- 源代码
udpsocket.hpp
#ifndef __UDPSOCKET_HPP
#define __UDPSOCKET_HPP
#include "utils.hpp"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
// #include <sys/socket.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
#include <winsock2.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
class udpSocket
{
private:
int udpSock;
public:
udpSocket();
~udpSocket();
bool CreateUDPSocket();
bool Bind2IPandPort(const char * ip, const uint16_t port);
bool RecvPackageFrom(void * recvBuffer, void * ip, uint16_t * port);
bool SendPackageTo(const void * sendBuffer, const char * ip, const uint16_t port);
bool CloseUDPSocket();
};
#endif
udpsocket.cpp
#include "../header/udpSocket.hpp"
udpSocket::udpSocket():udpSock(-1)
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
printf("WSAStartup error!\n");
#else
// Nothing todo...
#endif
}
udpSocket::~udpSocket()
{
}
bool udpSocket::CreateUDPSocket()
{
udpSock = socket(AF_INET, SOCK_DGRAM, 0);
if(!CHECK_POINT(udpSock, "usocket"))
return false;
return true;
}
bool udpSocket::Bind2IPandPort(const char * ip, const uint16_t port)
{
sockaddr_in usock_addr;
usock_addr.sin_family = AF_INET;
usock_addr.sin_addr.s_addr = inet_addr(ip);
usock_addr.sin_port = htons(port);
int bindCode = bind(udpSock, (sockaddr *)&usock_addr, sizeof(usock_addr));
if(!CHECK_POINT(bindCode, "ubind"))
return false;
return true;
}
bool udpSocket::RecvPackageFrom(void * recvBuffer, void * ip = nullptr, uint16_t * port = nullptr)
{
char tempRecvBuffer[UNIFORM_BUFFER_SIZE];
memset(tempRecvBuffer, 0x00, sizeof(tempRecvBuffer));
sockaddr_in net_usock_addr;
socklen_t len = sizeof(net_usock_addr);
int recvfromSize = recvfrom(udpSock, tempRecvBuffer, sizeof(tempRecvBuffer), 0, (sockaddr *)&net_usock_addr, &len);
// printf("%d\n", recvfromSize);
if(!CHECK_POINT(recvfromSize, "urecvfrom"))
return false;
memcpy(recvBuffer, tempRecvBuffer, recvfromSize);
if(ip)
memcpy(ip, inet_ntoa(net_usock_addr.sin_addr), 16);
if(port)
*port = ntohs(net_usock_addr.sin_port);
return true;
}
bool udpSocket::SendPackageTo(const void * sendBuffer, const char * ip, const uint16_t port)
{
sockaddr_in net_usock_addr;
net_usock_addr.sin_family = AF_INET;
net_usock_addr.sin_addr.s_addr = inet_addr(ip);
net_usock_addr.sin_port = htons(port);
socklen_t len = sizeof(net_usock_addr);
int sendtoSize = sendto(udpSock, (char *)sendBuffer, UNIFORM_BUFFER_SIZE, 0, (sockaddr *)&net_usock_addr, len);
if(!CHECK_POINT(sendtoSize, "usendto"))
return false;
return true;
}
bool udpSocket::CloseUDPSocket()
{
close(udpSock);
return true;
}
tcpsocket.hpp
#ifndef __TCPSOCKET_HPP
#define __TCPSOCKET_HPP
#include "utils.hpp"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
// #include <sys/socket.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
#include <winsock2.h>
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
class tcpSocket
{
private:
int tcpSock;
public:
tcpSocket();
~tcpSocket();
bool CreateTCPSocket();
bool Bind2IPandPort(const char * ip, const uint16_t port);
bool ListenSocket(const int& times);
bool Accept(tcpSocket * peerTcpSock, char * ip, uint16_t * port);
bool Connect(const char * ip, const uint16_t& port);
bool RecvPackage(void * recvBuffer);
bool SendPackage(const void * sendBuffer);
bool CloseTCPSocket();
};
#endif
tcpsocket.cpp
#include "../header/tcpSocket.hpp"
tcpSocket::tcpSocket():tcpSock(-1)
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
printf("WSAStartup error!\n");
#else
// Nothing todo...
#endif
}
tcpSocket::~tcpSocket()
{
}
bool tcpSocket::CreateTCPSocket()
{
tcpSock = socket(AF_INET, SOCK_STREAM, 0);
if(!CHECK_POINT(tcpSock, "tsocket"))
return false;
return true;
}
bool tcpSocket::Bind2IPandPort(const char * ip, const uint16_t port)
{
sockaddr_in tsock_addr;
tsock_addr.sin_family = AF_INET;
tsock_addr.sin_addr.s_addr = inet_addr(ip);
tsock_addr.sin_port = htons(port);
int bindCode = bind(tcpSock, (sockaddr *)&tsock_addr, sizeof(tsock_addr));
if(!CHECK_POINT(bindCode, "tbind"))
return false;
return true;
}
bool tcpSocket::ListenSocket(const int& times)
{
int listenCode = listen(tcpSock, times);
if(!CHECK_POINT(listenCode, "tlisten"))
return false;
return true;
}
bool tcpSocket::Accept(tcpSocket * peerTcpSock, char * ip = nullptr, uint16_t * port = nullptr)
{
sockaddr_in net_tsock_addr;
socklen_t len = sizeof(net_tsock_addr);
int peertcpSock = accept(tcpSock, (sockaddr *)&net_tsock_addr, &len);
if(!CHECK_POINT(peertcpSock, "taccept"))
return false;
// memcpy(peerTcpSock, &peertcpSock, sizeof(int));
peerTcpSock->tcpSock = peertcpSock;
if(ip)
memcpy(ip, inet_ntoa(net_tsock_addr.sin_addr), IP_SIZE);
if(port)
*port = ntohs(net_tsock_addr.sin_port);
return true;
}
bool tcpSocket::Connect(const char * ip, const uint16_t& port)
{
sockaddr_in tsock_addr;
tsock_addr.sin_family = AF_INET;
tsock_addr.sin_addr.s_addr = inet_addr(ip);
tsock_addr.sin_port = htons(port);
int connectCode = connect(tcpSock, (sockaddr *)&tsock_addr, sizeof(tsock_addr));
if(!CHECK_POINT(connectCode, "tconnect"))
return false;
return true;
}
bool tcpSocket::RecvPackage(void * recvBuffer = nullptr)
{
char tempRecvBuffer[UNIFORM_BUFFER_SIZE];
memset(tempRecvBuffer, 0x00, sizeof(tempRecvBuffer));
int recvsize = recv(tcpSock, tempRecvBuffer, sizeof(tempRecvBuffer), 0);
if(!CHECK_POINT(recvsize, "trecv"))
return false;
if(!recvsize)
return false;
if (recvBuffer)
memcpy(recvBuffer, tempRecvBuffer, sizeof(tempRecvBuffer));
return true;
}
bool tcpSocket::SendPackage(const void * sendBuffer)
{
int sendsize = send(tcpSock, (char *)sendBuffer, UNIFORM_BUFFER_SIZE, 0);
if(!CHECK_POINT(sendsize, "tsend"))
return false;
return true;
}
bool tcpSocket::CloseTCPSocket()
{
return (shutdown(tcpSock, 2) == 0);
}
utils.hpp
#ifndef __UTILS_HPP
#define __UTILS_HPP
#include <time.h>
#include <stdio.h>
#include <string.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
typedef unsigned short uint16_t;
typedef int socklen_t;
#endif
#define NOT_FOUND "not found"
#define EXIT_SYS "exit"
#define ACK "ACK"
#define OK "OK"
#define GET "get"
#define PUT "put"
#define LIST "list"
#define SERVER_ROOT_PATH "/root/Socket_Workspace/FILETransfer/filebuffer/"
#define IP_SIZE 32
#define LISTEN_TIMES 5
#define COMMAND_REQ_HEADER_MAXLENGTH 64
#define SEGMENT_NAME_MAXLENGTH 64
#define SEGMENT_DATA_MAXLENGTH 1300
#define UNIFORM_BUFFER_SIZE 1400
struct commandPackage
{
char reqHeader[COMMAND_REQ_HEADER_MAXLENGTH] = {0};
char reqContext[SEGMENT_NAME_MAXLENGTH] = {0};
commandPackage()
{}
void setcommandPackage(const char * _reqHeader, const char * _reqContext)
{
strcpy(this->reqHeader, _reqHeader);
strcpy(this->reqContext, _reqContext);
}
static commandPackage * getInstance()
{
static commandPackage commandpackage;
return &commandpackage;
}
~commandPackage()
{
reqHeader[COMMAND_REQ_HEADER_MAXLENGTH] = {0};
reqContext[SEGMENT_NAME_MAXLENGTH] = {0};
}
};
struct HEADER_GET_PUT_Package
{
bool is_exist = false;
long length = 0;
char file_name[SEGMENT_NAME_MAXLENGTH] = {0};
HEADER_GET_PUT_Package()
{}
void setHEADER_GET_PUT_Package(const bool& _is_exist, const long& _length, const char * _file_name)
{
this->is_exist = _is_exist;
this->length = _length;
strcpy(this->file_name, _file_name);
}
static HEADER_GET_PUT_Package * getInstance()
{
static HEADER_GET_PUT_Package header_gpp_Instance;
return &header_gpp_Instance;
}
~HEADER_GET_PUT_Package()
{
is_exist = false;
length = 0;
file_name[SEGMENT_NAME_MAXLENGTH] = {0};
}
};
static char * resolutionFileName_FromFilePath(char * filePath)
{
char * fileName = new char[COMMAND_REQ_HEADER_MAXLENGTH];
memset(fileName, 0x00, COMMAND_REQ_HEADER_MAXLENGTH);
int index = 0;
char * ptrFilePath = filePath;
while((*ptrFilePath) != '\0')
{
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
;
#else
if((*ptrFilePath) == '/' || (*ptrFilePath) == '\\')
{
memset(fileName, 0x00, COMMAND_REQ_HEADER_MAXLENGTH);
index = 0;
}
else
{
fileName[index++] = *ptrFilePath;
}
#endif
ptrFilePath++;
}
return fileName;
}
static char * IntToString(const int& ival)
{
char * itos = new char[16];
memset(itos, 0x00, 16);
sprintf(itos, "%d", ival);
return itos;
}
static char * LongIntToString(const long& ival)
{
char * litos = new char[16];
memset(litos, 0x00, 16);
sprintf(litos, "%ld", ival);
return litos;
}
static long obtainFileLength(FILE * fp_FILE)
{
fseek(fp_FILE, 0L, SEEK_END);
return ftell(fp_FILE);
}
static bool criticalOperator(const char * _first_operator, const char * _second_operator)
{
return (strcmp(_first_operator, _second_operator) == 0);
}
static bool CHECK_POINT(const int number, const char * point)
{
if(number < 0)
{
printf("%s error! exit code %d\n", point, number);
return false;
}
return true;
}
static int progress(int prog, int lastpos)
{
int i = 0;
for (i = 0; i < lastpos; i++)
{
printf("\b");
}
for (i = 0; i < prog; i++)
{
printf("#");
}
printf(">>");
for (i += 2; i < 104; i++)
{
printf(" ");
}
i = i + printf("[%d%%]", prog);
fflush(stdout);
return i;
}
static char * getLocalTime()
{
time_t timep;
time(&timep);
static char localTime[256];
strftime(localTime, sizeof(localTime), "%Y-%m-%d %H:%M:%S", localtime(&timep));
return localTime;
}
#endif
commandAnaly.hpp
#ifndef __COMMANDANALY_HPP
#define __COMMANDANALY_HPP
#include "utils.hpp"
#include <string.h>
typedef struct commandPackage commandPackage;
class commandAnaly
{
private:
char * command;
public:
commandAnaly(char * _command);
~commandAnaly();
commandPackage * getcommandPackage();
};
#endif
commandAnaly.cpp
#include "../header/commandAnaly.hpp"
commandAnaly::commandAnaly(char * _command)
{
this->command = new char[UNIFORM_BUFFER_SIZE];
memset(this->command, 0x00, UNIFORM_BUFFER_SIZE);
strcpy(this->command, _command);
}
commandAnaly::~commandAnaly()
{
delete[] this->command;
}
commandPackage * commandAnaly::getcommandPackage()
{
commandPackage * cmdPack = commandPackage::getInstance();
char * ptrcommand = this->command;
while(*ptrcommand != '\0')
{
if(*ptrcommand == ' ' && strlen(cmdPack->reqHeader) == 0)
{
ptrcommand++;
continue;
}
if(*ptrcommand == ' ')
{
while(*ptrcommand != '\0')
{
if(*ptrcommand == ' ')
{
ptrcommand++;
continue;
}
sprintf(cmdPack->reqContext, "%s%c", cmdPack->reqContext, *ptrcommand);
ptrcommand++;
}
break;
}
sprintf(cmdPack->reqHeader, "%s%c", cmdPack->reqHeader, *ptrcommand);
ptrcommand++;
}
return cmdPack;
}
dataPackage.hpp
#ifndef __dataPackage_HPP
#define __dataPackage_HPP
#include "utils.hpp"
#include <string.h>
class dataPackage
{
private:
char PackageSegmentName[SEGMENT_NAME_MAXLENGTH];
char PackageSegmentData[SEGMENT_DATA_MAXLENGTH];
int PackageSegmentNumber;
int PackageSegmentSize;
bool PackageSegmentEnd;
public:
dataPackage();
dataPackage(const char * _PackageSegmentName, const char * _PackageSegmentData,
const int _PackageSegmentNumber, const int _PackageSegmentEnd, const int _PackageSegmentSize);
~dataPackage();
char * getPackageSegmentName();
char * getPackageSegmentData();
void getPackageSegmentData(char *&pPackageSegmentData);
int getPackageSegmentNumber();
int getPackageSegmentSize();
bool packageSegmentisEnd();
bool setPackageSegmentName(const char * _PackageSegmentName);
bool setPackageSegmentData(const char * _PackageSegmentData);
bool setPackageSegmentNumber(const int _PackageSegmentNumber);
bool setPackageSegmentEnd();
bool operator==(dataPackage& udpack);
void getdata(char * buf)
{
memcpy(buf, PackageSegmentData, PackageSegmentSize);
}
};
#endif
dataPackage.cpp
#include "../header/dataPackage.hpp"
dataPackage::dataPackage()
{
memset(this->PackageSegmentName, 0x00, SEGMENT_NAME_MAXLENGTH);
memset(this->PackageSegmentData, 0x00, SEGMENT_DATA_MAXLENGTH);
this->PackageSegmentNumber = -1;
this->PackageSegmentEnd = false;
}
dataPackage::dataPackage(const char * _PackageSegmentName, const char * _PackageSegmentData,
const int _PackageSegmentNumber, const int _PackageSegmentEnd, const int _PackageSegmentSize)
{
memset(this->PackageSegmentName, 0x00, SEGMENT_NAME_MAXLENGTH);
memset(this->PackageSegmentData, 0x00, SEGMENT_DATA_MAXLENGTH);
memcpy(this->PackageSegmentName, _PackageSegmentName, sizeof(this->PackageSegmentName));
memcpy(this->PackageSegmentData, _PackageSegmentData, sizeof(this->PackageSegmentData));
this->PackageSegmentNumber = _PackageSegmentNumber;
this->PackageSegmentEnd = _PackageSegmentEnd;
this->PackageSegmentSize = _PackageSegmentSize;
}
dataPackage::~dataPackage()
{
}
char * dataPackage::getPackageSegmentName()
{
return this->PackageSegmentName;
}
char * dataPackage::getPackageSegmentData()
{
return this->PackageSegmentData;
}
void dataPackage::getPackageSegmentData(char *&pPackageSegmentData)
{
pPackageSegmentData = PackageSegmentData;
}
int dataPackage::getPackageSegmentNumber()
{
return this->PackageSegmentNumber;
}
int dataPackage::getPackageSegmentSize()
{
return this->PackageSegmentSize;
}
bool dataPackage::packageSegmentisEnd()
{
return PackageSegmentEnd == true;
}
bool dataPackage::setPackageSegmentName(const char * _PackageSegmentName)
{
memset(this->PackageSegmentName, 0x00, SEGMENT_NAME_MAXLENGTH);
strcpy(this->PackageSegmentName, _PackageSegmentName);
return true;
}
bool dataPackage::setPackageSegmentData(const char * _PackageSegmentData)
{
memset(this->PackageSegmentData, 0x00, SEGMENT_DATA_MAXLENGTH);
strcpy(this->PackageSegmentData, _PackageSegmentData);
return true;
}
bool dataPackage::setPackageSegmentNumber(const int _PackageSegmentNumber)
{
this->PackageSegmentNumber = _PackageSegmentNumber;
return true;
}
bool dataPackage::setPackageSegmentEnd()
{
this->PackageSegmentEnd = true;
return true;
}
bool dataPackage::operator==(dataPackage& udpack)
{
return (strcmp(this->PackageSegmentName, udpack.getPackageSegmentName()) == 0)
&& (strcmp(this->PackageSegmentData, udpack.getPackageSegmentData()) == 0)
&& (this->PackageSegmentNumber == udpack.getPackageSegmentNumber())
&& (this->PackageSegmentSize == udpack.getPackageSegmentSize())
&& (this->packageSegmentisEnd() == udpack.packageSegmentisEnd());
}
dirReader.hpp
#ifndef __DIRREADER_HPP
#define __DIRREADER_HPP
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <vector>
#include "utils.hpp"
#include "../include/cJSON.h"
class dirReader
{
private:
int numbers;
char * dirPath;
cJSON * fileContainer_cjson;
public:
dirReader(char * _dirPath);
~dirReader();
void readDirPath();
cJSON * getfileContainer_cjson();
};
#endif
dirReader.cpp
#include "../header/dirReader.hpp"
dirReader::dirReader(char * _dirPath)
{
this->numbers = 0;
this->dirPath = new char[SEGMENT_NAME_MAXLENGTH * 2];
this->fileContainer_cjson = cJSON_CreateObject();
memset(this->dirPath, 0x00, SEGMENT_NAME_MAXLENGTH * 2);
strcpy(this->dirPath, _dirPath);
}
dirReader::~dirReader()
{
}
void dirReader::readDirPath()
{
struct dirent * ptrFile;
DIR * ptrDirPath;
if((ptrDirPath = opendir(this->dirPath)) == nullptr)
{
printf("dir open error!\n");
return;
}
while((ptrFile = readdir(ptrDirPath)) != nullptr)
{
if(strcmp(ptrFile->d_name, ".") == 0 || strcmp(ptrFile->d_name, "..") == 0)
continue;
else
cJSON_AddStringToObject(this->fileContainer_cjson, IntToString(++(this->numbers)), ptrFile->d_name);
}
}
cJSON * dirReader::getfileContainer_cjson()
{
return this->fileContainer_cjson;
}
fileTransferClient.hpp
#ifndef __FILETRANSFERCLIENT_HPP
#define __FILETRANSFERCLIENT_HPP
#include "tcpSocket.hpp"
class fileTransferClient
{
private:
tcpSocket tcpClientSocket;
char ip[IP_SIZE];
uint16_t port;
public:
fileTransferClient(const char * _ip, const uint16_t& _port);
~fileTransferClient();
bool ConnectToTcpServer();
bool CloseConnect();
bool Recv(void * recvBuffer);
bool Send(const void * sendBuffer);
bool fileTransferClientdoGET(char * getFileName);
bool fileTransferClientdoPUT(char * putFileName);
};
#endif
fileTransferClient.cpp
#include "../header/fileTransferClient.hpp"
#include "../header/dataPackage.hpp"
fileTransferClient::fileTransferClient(const char * _ip, const uint16_t& _port):port(_port)
{
tcpClientSocket.CreateTCPSocket();
memset(this->ip, 0x00, sizeof(this->ip));
strcpy(this->ip, _ip);
}
fileTransferClient::~fileTransferClient()
{
tcpClientSocket.CloseTCPSocket();
}
bool fileTransferClient::ConnectToTcpServer()
{
return tcpClientSocket.Connect(this->ip, this->port);
}
bool fileTransferClient::CloseConnect()
{
return tcpClientSocket.CloseTCPSocket();
}
bool fileTransferClient::Recv(void * recvBuffer)
{
commandPackage * commandpackage = (commandPackage *)recvBuffer;
if(criticalOperator(commandpackage->reqHeader, GET))
return fileTransferClientdoGET(commandpackage->reqContext);
else if(criticalOperator(commandpackage->reqHeader, PUT))
return fileTransferClientdoPUT(commandpackage->reqContext);
else
return false;
}
bool fileTransferClient::Send(const void * sendBuffer)
{
return tcpClientSocket.SendPackage(sendBuffer);
}
bool fileTransferClient::fileTransferClientdoGET(char * getFileName)
{
char clientRecvBuffer[UNIFORM_BUFFER_SIZE] = {0};
tcpClientSocket.RecvPackage(clientRecvBuffer);
if(criticalOperator(clientRecvBuffer, NOT_FOUND))
return false;
long fileTotalLength = 0;
sscanf(clientRecvBuffer, "%ld", &fileTotalLength);
memset(clientRecvBuffer, 0x00, sizeof(clientRecvBuffer));
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
char filePath[SEGMENT_NAME_MAXLENGTH] = ".//filebuffer//";
#else
char filePath[SEGMENT_NAME_MAXLENGTH] = "/root/Socket_Workspace/FILETransfer/";
#endif
char * localhostFileName = strcat(filePath, getFileName);
FILE * fpw;
if((fpw = fopen(localhostFileName, "wb")) == nullptr)
{
printf("fopen error!\n");
return false;
}
long totalRecvLength = 0;
int lastpos = 0;
while(true)
{
tcpClientSocket.RecvPackage(clientRecvBuffer);
if(criticalOperator(clientRecvBuffer, OK))
break;
tcpClientSocket.SendPackage(ACK);
dataPackage * udpack = (dataPackage *)clientRecvBuffer;
int fileblockLength = -1;
if((fileblockLength = fwrite(udpack->getPackageSegmentData(), sizeof(char), udpack->getPackageSegmentSize(), fpw)) < 0)
{
printf("fwrite error!\n");
return false;
}
totalRecvLength += udpack->getPackageSegmentSize();
lastpos = progress((int)(100 * 1.0 * totalRecvLength / fileTotalLength), lastpos);
fflush(stdout);
memset(clientRecvBuffer, 0x00, sizeof(clientRecvBuffer));
}
fclose(fpw);
return true;
}
bool fileTransferClient::fileTransferClientdoPUT(char * putFileName)
{
char tcpClientSendBuffer[UNIFORM_BUFFER_SIZE] = {0};
FILE * fpr;
if((fpr = fopen(putFileName, "rb")) == nullptr)
{
printf("fopen error!\n");
return false;
}
long fileTotalLength = obtainFileLength(fpr);
fseek(fpr, 0L, SEEK_SET);
tcpClientSocket.SendPackage(LongIntToString(fileTotalLength));
tcpClientSocket.RecvPackage(tcpClientSendBuffer);
if(!criticalOperator(tcpClientSendBuffer, ACK))
return false;
memset(tcpClientSendBuffer, 0x00, sizeof(tcpClientSendBuffer));
int fileblockLength = -1;
int segmentNumber = 1;
int readsize = SEGMENT_DATA_MAXLENGTH - 2;
long totalSendLength = 0;
long totalLength = fileTotalLength;
int lastpos = 0;
printf("Uploading......\n");
while(fileTotalLength)
{
if(fileTotalLength < readsize)
{
fileblockLength = fread(tcpClientSendBuffer, sizeof(char), fileTotalLength, fpr);
fileblockLength = fileTotalLength;
fileTotalLength = 0;
}
else
{
fileblockLength = fread(tcpClientSendBuffer, sizeof(char), readsize, fpr);
fileblockLength = readsize;
fileTotalLength -= readsize;
}
char segmentName[UNIFORM_BUFFER_SIZE] = {0};
sprintf(segmentName, "tcp/pack/%s/segment/%d/%d", resolutionFileName_FromFilePath(putFileName), segmentNumber, 0);
dataPackage udpack(segmentName, tcpClientSendBuffer, segmentNumber, false, fileblockLength);
tcpClientSocket.SendPackage(&udpack);
char clientRecvACK[UNIFORM_BUFFER_SIZE] = {0};
tcpClientSocket.RecvPackage(clientRecvACK);
if(!criticalOperator(clientRecvACK, ACK))
break;
// totalSendLength += udpack.getPackageSegmentSize();
// // printf("Send Peocess : %f/%\n", (100 * 1.0 * totalSendLength / totalLength));
// lastpos = progress((int)(100 * 1.0 * totalSendLength / totalLength), lastpos);
// fflush(stdout);
// printf("%s, %d\n", segmentName, udpack.getPackageSegmentSize());
memset(tcpClientSendBuffer, 0x00, sizeof(tcpClientSendBuffer));
segmentNumber++;
}
fclose(fpr);
memset(tcpClientSendBuffer, 0x00, sizeof(tcpClientSendBuffer));
tcpClientSocket.SendPackage(OK);
return true;
}
fileTransferServer.hpp
#ifndef __FILETRANSFERSERVER_HPP
#define __FILETRANSFERSERVER_HPP
#include "tcpSocket.hpp"
#include "../header/dataPackage.hpp"
#include "../header/commandAnaly.hpp"
class fileTransferServer
{
private:
tcpSocket tcpServerSocket;
char ip[IP_SIZE];
uint16_t port;
public:
fileTransferServer(const char * _ip, const uint16_t& _port);
~fileTransferServer();
void fileTransferServerStartUp();
void fileTransferServerdoGET(char * reqContext, tcpSocket& peerTcpSocket, const char * peerIP, const uint16_t& peerPORT);
void fileTransferServerdoPUT(char * reqContext, tcpSocket& peerTcpSocket, const char * peerIP, const uint16_t& peerPORT);
};
#endif
fileTransferServer.cpp
#include "../header/fileTransferServer.hpp"
fileTransferServer::fileTransferServer(const char * _ip, const uint16_t& _port):port(_port)
{
memset(this->ip, 0x00, sizeof(this->ip));
strcpy(this->ip, _ip);
}
fileTransferServer::~fileTransferServer()
{
}
void fileTransferServer::fileTransferServerStartUp()
{
tcpServerSocket.CreateTCPSocket();
tcpServerSocket.Bind2IPandPort(this->ip, this->port);
tcpServerSocket.ListenSocket(LISTEN_TIMES);
printf("[%s] TCP File Transfer Server Start Up...\n", getLocalTime());
while(true)
{
tcpSocket peerTcpSocket;
char peerIP[IP_SIZE] = {0};
uint16_t peerPORT = 0;
if(!tcpServerSocket.Accept(&peerTcpSocket, peerIP, &peerPORT))
continue;
printf("[%s] HOST [%s:%d] connected...\n", getLocalTime(), peerIP, peerPORT);
while(true)
{
char buf[UNIFORM_BUFFER_SIZE] = {0};
if(!peerTcpSocket.RecvPackage(buf))
{
printf("[%s] HOST [%s:%d] disconnected...\n", getLocalTime(), peerIP, peerPORT);
peerTcpSocket.CloseTCPSocket();
break;
}
commandPackage * commandpackage = (commandPackage *)buf;
if(criticalOperator(commandpackage->reqHeader, GET))
fileTransferServerdoGET(commandpackage->reqContext, peerTcpSocket, peerIP, peerPORT);
else if(criticalOperator(commandpackage->reqHeader, PUT))
fileTransferServerdoPUT(commandpackage->reqContext, peerTcpSocket, peerIP, peerPORT);
else
continue;
commandpackage->~commandPackage();
}
}
tcpServerSocket.CloseTCPSocket();
}
void fileTransferServer::fileTransferServerdoGET(
char * reqContext, tcpSocket& peerTcpSocket, const char * peerIP, const uint16_t& peerPORT)
{
char tcpServerSendBuffer[UNIFORM_BUFFER_SIZE] = {0};
char filePath[SEGMENT_NAME_MAXLENGTH * 2] = SERVER_ROOT_PATH;
char * fileName = strcat(filePath, (char *)reqContext);
FILE * fpr;
if((fpr = fopen(fileName, "rb")) == nullptr)
peerTcpSocket.SendPackage(NOT_FOUND);
long fileTotalLength = obtainFileLength(fpr);
fseek(fpr, 0L, SEEK_SET);
peerTcpSocket.SendPackage(LongIntToString(fileTotalLength));
memset(tcpServerSendBuffer, 0x00, sizeof(tcpServerSendBuffer));
int fileblockLength = -1;
int segmentNumber = 1;
int readsize = SEGMENT_DATA_MAXLENGTH - 2;
long totalSendLength = 0;
// long totalLength = fileTotalLength;
// int lastpos = 0;
printf("[%s] HOST [%s:%d] Sending......\n", getLocalTime(), peerIP, peerPORT);
while(fileTotalLength)
{
if(fileTotalLength < readsize)
{
fileblockLength = fread(tcpServerSendBuffer, sizeof(char), fileTotalLength, fpr);
fileblockLength = fileTotalLength;
fileTotalLength = 0;
}
else
{
fileblockLength = fread(tcpServerSendBuffer, sizeof(char), readsize, fpr);
fileblockLength = readsize;
fileTotalLength -= readsize;
}
char segmentName[UNIFORM_BUFFER_SIZE] = {0};
sprintf(segmentName, "tcp/pack/%s/segment/%d/%d", reqContext, segmentNumber, 0);
dataPackage udpack(segmentName, tcpServerSendBuffer, segmentNumber, false, fileblockLength);
peerTcpSocket.SendPackage(&udpack);
char clientRecvACK[UNIFORM_BUFFER_SIZE] = {0};
peerTcpSocket.RecvPackage(clientRecvACK);
if(!criticalOperator(clientRecvACK, ACK))
break;
// totalSendLength += udpack.getPackageSegmentSize();
// // printf("Send Peocess : %f/%\n", (100 * 1.0 * totalSendLength / totalLength));
// lastpos = progress((int)(100 * 1.0 * totalSendLength / totalLength), lastpos);
// fflush(stdout);
// // printf("%s, %d\n", segmentName, udpack.getPackageSegmentSize());
memset(tcpServerSendBuffer, 0x00, sizeof(tcpServerSendBuffer));
segmentNumber++;
}
fclose(fpr);
memset(tcpServerSendBuffer, 0x00, sizeof(tcpServerSendBuffer));
peerTcpSocket.SendPackage(OK);
printf("[%s] HOST [%s:%d] Sended Successful......\n", getLocalTime(), peerIP, peerPORT);
}
void fileTransferServer::fileTransferServerdoPUT(
char * reqContext, tcpSocket& peerTcpSocket, const char * peerIP, const uint16_t& peerPORT)
{
char tcpServerRecvBuffer[UNIFORM_BUFFER_SIZE] = {0};
char filePath[SEGMENT_NAME_MAXLENGTH] = SERVER_ROOT_PATH;
char * reqfileName = resolutionFileName_FromFilePath(reqContext);
char * fileName = strcat(filePath, reqfileName);
peerTcpSocket.RecvPackage(tcpServerRecvBuffer);
peerTcpSocket.SendPackage(ACK);
long fileTotalLength = 0;
sscanf(tcpServerRecvBuffer, "%ld", &fileTotalLength);
memset(tcpServerRecvBuffer, 0x00, sizeof(tcpServerRecvBuffer));
// #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
// char filePath[SEGMENT_NAME_MAXLENGTH] = ".//filebuffer//";
// #else
// char filePath[SEGMENT_NAME_MAXLENGTH] = "../filebuffer/recv/";
// #endif
FILE * fpw;
if((fpw = fopen(fileName, "wb")) == nullptr)
{
printf("fopen error!\n");
}
long totalRecvLength = 0;
int lastpos = 0;
while(true)
{
peerTcpSocket.RecvPackage(tcpServerRecvBuffer);
if(criticalOperator(tcpServerRecvBuffer, OK))
break;
dataPackage * udpack = (dataPackage *)tcpServerRecvBuffer;
int fileblockLength = -1;
if((fileblockLength = fwrite(udpack->getPackageSegmentData(), sizeof(char), udpack->getPackageSegmentSize(), fpw)) <= 0)
{
printf("fwrite error!\n");
break;
}
peerTcpSocket.SendPackage(ACK);
// totalRecvLength += udpack->getPackageSegmentSize();
// lastpos = progress((int)(100 * 1.0 * totalRecvLength / fileTotalLength), lastpos);
// fflush(stdout);
// printf("%s, %d\n", udpack->getPackageSegmentName(), udpack->getPackageSegmentSize());
memset(tcpServerRecvBuffer, 0x00, sizeof(tcpServerRecvBuffer));
}
fclose(fpw);
printf("[%s] HOST [%s:%d] Recved Successful......\n", getLocalTime(), peerIP, peerPORT);
}
messageTransferClient.hpp
#ifndef __messageTransferClient_HPP
#define __messageTransferClient_HPP
#include "udpSocket.hpp"
#include "dataPackage.hpp"
#include "dirReader.hpp"
#include "../include/cJSON.h"
#define __OLD_VERSION true
class messageTransferClient
{
private:
char ip[IP_SIZE];
uint16_t port;
udpSocket udpClientSocket;
public:
messageTransferClient(const char * _ip, const uint16_t _port);
~messageTransferClient();
void Send(const void * sendBuffer);
bool Recv(void * recvBuffer);
bool messageTransferClientdoGET();
bool messageTransferClientdoPUT();
bool messageTransferClientdoLIST();
};
#endif
messageTransferClient.cpp
#include "../header/messageTransferClient.hpp"
messageTransferClient::messageTransferClient(const char * _ip, const uint16_t _port):port(_port)
{
memset(ip, 0x00, sizeof(ip));
strcpy(ip, _ip);
udpClientSocket.CreateUDPSocket();
}
messageTransferClient::~messageTransferClient()
{
udpClientSocket.CloseUDPSocket();
}
void messageTransferClient::Send(const void * sendBuffer)
{
udpClientSocket.SendPackageTo(sendBuffer, this->ip, this->port);
}
bool messageTransferClient::Recv(void * recvBuffer)
{
commandPackage * commandpackage = (commandPackage *)recvBuffer;
if(criticalOperator(commandpackage->reqHeader, GET))
return messageTransferClientdoGET();
else if(criticalOperator(commandpackage->reqHeader, PUT))
{
FILE * fpr;
if((fpr = fopen(commandpackage->reqContext, "rb")) == nullptr)
{
printf("Path error! Not found this file in your localhost!\n");
return false;
}
fclose(fpr);
return messageTransferClientdoPUT();
}
else if(criticalOperator(commandpackage->reqHeader, LIST))
return messageTransferClientdoLIST();
else
return false;
}
bool messageTransferClient::messageTransferClientdoGET()
{
HEADER_GET_PUT_Package * header_gpp = HEADER_GET_PUT_Package::getInstance();
udpClientSocket.RecvPackageFrom(header_gpp, nullptr, nullptr);
if(!header_gpp->is_exist)
{
printf("Not Found!\n");
header_gpp->~HEADER_GET_PUT_Package();
return false;
}
printf("file [%s] Total Lendth : [%ld] bits\n", header_gpp->file_name, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
return true;
}
bool messageTransferClient::messageTransferClientdoPUT()
{
HEADER_GET_PUT_Package * header_gpp = HEADER_GET_PUT_Package::getInstance();
udpClientSocket.RecvPackageFrom(header_gpp, nullptr, nullptr);
if(!header_gpp->is_exist)
{
printf("Allowed upload!\n");
header_gpp->~HEADER_GET_PUT_Package();
return true;
}
printf("file [%s] also exists, Total Lendth : [%ld] bits, can't allowed upload!\n", header_gpp->file_name, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
return false;
}
bool messageTransferClient::messageTransferClientdoLIST()
{
char * dirFileList = new char[UNIFORM_BUFFER_SIZE];
memset(dirFileList, 0x00, UNIFORM_BUFFER_SIZE);
udpClientSocket.RecvPackageFrom(dirFileList, nullptr, nullptr);
cJSON * dirFileList_cJSON = cJSON_Parse(dirFileList);
if(!dirFileList_cJSON)
{
printf("cJSON error!%s\n", cJSON_GetErrorPtr());
return false;
}
cJSON * getDirFileListItem_cJSON;
for(int itemIndex = 1; ; itemIndex++)
{
getDirFileListItem_cJSON = cJSON_GetObjectItem(dirFileList_cJSON, IntToString(itemIndex));
if(!getDirFileListItem_cJSON)
break;
if(getDirFileListItem_cJSON->type == cJSON_String)
printf("%s ", getDirFileListItem_cJSON->valuestring);
}
printf("\n");
return true;
}
messageTransferServer.hpp
#ifndef __messageTransferServer_HPP
#define __messageTransferServer_HPP
#include "udpSocket.hpp"
#include "dataPackage.hpp"
#include "dirReader.hpp"
#include "commandAnaly.hpp"
#include "../include/cJSON.h"
#define __OLD_VERSION false
#define __WRITE_TEST false
class messageTransferServer
{
private:
udpSocket udpServerSocket;
public:
messageTransferServer();
~messageTransferServer();
void messageTransferServerStartUp(const char * ip, const uint16_t port);
void messageTransferServerdoGET(void * reqContext, const char * recvIP, const uint16_t& recvPORT);
void messageTransferServerdoPUT(void * reqContext, const char * recvIP, const uint16_t& recvPORT);
void messageTransferServerdoLIST(const char * recvIP, const uint16_t& recvPORT);
};
#endif
messageTransferServer.cpp
#include "../header/messageTransferServer.hpp"
messageTransferServer::messageTransferServer()
{
udpServerSocket.CreateUDPSocket();
}
messageTransferServer::~messageTransferServer()
{
udpServerSocket.CloseUDPSocket();
}
void messageTransferServer::messageTransferServerStartUp(const char * ip, const uint16_t port)
{
udpServerSocket.Bind2IPandPort(ip, port);
printf("[%s] UDP File Transfer Server Start Up...\n", getLocalTime());
while (true)
{
char recvIP[IP_SIZE] = {0};
uint16_t recvPORT = 0;
char buf[UNIFORM_BUFFER_SIZE] = {0};
if(!udpServerSocket.RecvPackageFrom(buf, recvIP, &recvPORT))
continue;
commandPackage * commandpackage = (commandPackage *)buf;
if(criticalOperator(commandpackage->reqHeader, GET))
messageTransferServerdoGET(commandpackage->reqContext, recvIP, recvPORT); //get
else if(criticalOperator(commandpackage->reqHeader, PUT))
messageTransferServerdoPUT(commandpackage->reqContext, recvIP, recvPORT); //put
else if(criticalOperator(commandpackage->reqHeader, LIST))
messageTransferServerdoLIST(recvIP, recvPORT); //list
else
continue; //nothing todo
commandpackage->~commandPackage();
}
}
void messageTransferServer::messageTransferServerdoGET(void * reqContext, const char * recvIP, const uint16_t& recvPORT)
{
char filePath[SEGMENT_NAME_MAXLENGTH * 2] = SERVER_ROOT_PATH;
char * fileName = strcat(filePath, (char *)reqContext);
HEADER_GET_PUT_Package * header_gpp = HEADER_GET_PUT_Package::getInstance();
FILE * fpr;
if((fpr = fopen(fileName, "rb")) == nullptr)
{
udpServerSocket.SendPackageTo(header_gpp, recvIP, recvPORT);
printf("[%s] HOST [%s:%d] REQ : %s NOT FOUND!, RESP : %ld bits\n", getLocalTime(), recvIP, recvPORT, fileName, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
return;
}
long fileTotalLength = obtainFileLength(fpr);
fclose(fpr);
header_gpp->setHEADER_GET_PUT_Package(true, fileTotalLength, fileName);
udpServerSocket.SendPackageTo(header_gpp, recvIP, recvPORT);
printf("[%s] HOST [%s:%d] REQ : %s, RESP : %ld bits\n", getLocalTime(), recvIP, recvPORT, fileName, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
}
void messageTransferServer::messageTransferServerdoPUT(void * reqContext, const char * recvIP, const uint16_t& recvPORT)
{
char filePath[SEGMENT_NAME_MAXLENGTH * 2] = SERVER_ROOT_PATH;
char * reqfileName = resolutionFileName_FromFilePath((char *)reqContext);
char * fileName = strcat(filePath, reqfileName);
HEADER_GET_PUT_Package * header_gpp = HEADER_GET_PUT_Package::getInstance();
FILE * fpr;
if((fpr = fopen(fileName, "rb")) == nullptr)
{
udpServerSocket.SendPackageTo(header_gpp, recvIP, recvPORT);
printf("[%s] HOST [%s:%d] REQ : %s NOT EXISTS THE SAME FILE, ALLOWED UPLOAD!, RESP : %ld bits\n", getLocalTime(), recvIP, recvPORT, fileName, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
return;
}
long fileTotalLength = obtainFileLength(fpr);
fclose(fpr);
header_gpp->setHEADER_GET_PUT_Package(true, fileTotalLength, fileName);
udpServerSocket.SendPackageTo(header_gpp, recvIP, recvPORT);
printf("[%s] HOST [%s:%d] REQ : %s EXISTS THE SAME FILE, CAN'T ALLOWED UPLOAD!, RESP : %ld bits\n", getLocalTime(), recvIP, recvPORT, fileName, header_gpp->length);
header_gpp->~HEADER_GET_PUT_Package();
}
void messageTransferServer::messageTransferServerdoLIST(const char * recvIP, const uint16_t& recvPORT)
{
dirReader * dirFileReader = new dirReader((char *)SERVER_ROOT_PATH);
dirFileReader->readDirPath();
cJSON * dirFileContainer = dirFileReader->getfileContainer_cjson();
char * sendbuf = cJSON_Print(dirFileContainer);
udpServerSocket.SendPackageTo(sendbuf, recvIP, recvPORT);
printf("[%s] HOST [%s:%d] REQ : %s, RESP : As follows\n", getLocalTime(), recvIP, recvPORT, LIST);
printf("%s\n", sendbuf);
}
serverMain.cpp
#include "../header/messageTransferServer.hpp"
#include "../header/fileTransferServer.hpp"
#include <thread>
const char * ip = "127.0.0.1";
const uint16_t msg_port = 39000;
const uint16_t fil_port = 39001;
messageTransferServer mts;
fileTransferServer fts(ip, fil_port);
void thread_mts()
{
mts.messageTransferServerStartUp(ip, msg_port);
}
void thread_fts()
{
fts.fileTransferServerStartUp();
}
int main()
{
std::thread th_mts(thread_mts);
std::thread th_fts(thread_fts);
th_fts.detach();
th_mts.join();
return 0;
}
clientMain.cpp
#include "../header/messageTransferClient.hpp"
#include "../header/fileTransferClient.hpp"
#include "../header/dataPackage.hpp"
#include "../header/commandAnaly.hpp"
#include <iostream>
const char * ip = "127.0.0.1";
const uint16_t msg_port = 39000;
const uint16_t fil_port = 39001;
void RunCommand()
{
printf("Welcome File Transfer v2.0.0! [%s]\n\n", getLocalTime());
printf("Usage:\n");
printf(" > `get [filename]` --download file from server.\n");
printf(" > `put [filename]` --upload file to server.\n");
printf(" > `list` --list server files.\n");
printf(" > `exit` --exit the sysytem.\n\n");
}
bool recvKeyboardInput(char * _usrCommand)
{
char usrCommand[UNIFORM_BUFFER_SIZE];
memset(usrCommand, 0x00, sizeof(usrCommand));
printf(" > ");
std::cin.getline(usrCommand, sizeof(usrCommand));
if(criticalOperator(usrCommand, EXIT_SYS))
return false;
strcpy(_usrCommand, usrCommand);
return true;
}
void deal1WordCommand(commandPackage * commandpackage)
{
messageTransferClient mtc(ip, msg_port);
mtc.Send(commandpackage);
mtc.Recv(commandpackage);
}
void deal2WordCommand(commandPackage * commandpackage)
{
messageTransferClient mtc(ip, msg_port);
mtc.Send(commandpackage);
if(mtc.Recv(commandpackage))
{
fileTransferClient ftc(ip, fil_port);
ftc.ConnectToTcpServer();
ftc.Send(commandpackage);
if(ftc.Recv(commandpackage))
printf("Successful!\n");
ftc.CloseConnect();
}
}
void RunFILETransfer()
{
RunCommand();
while(true)
{
char usrCommand[UNIFORM_BUFFER_SIZE];
memset(usrCommand, 0x00, sizeof(usrCommand));
if(!recvKeyboardInput(usrCommand))
break;
commandAnaly commandanaly(usrCommand);
commandPackage * commandpackage = commandanaly.getcommandPackage();
if(criticalOperator(commandpackage->reqHeader, LIST))
deal1WordCommand(commandpackage);
else
deal2WordCommand(commandpackage);
commandpackage->~commandPackage();
}
}
int main()
{
RunFILETransfer();
return 0;
}