I want to implement a SimpleFtp with Winsock. But I was stuck in the maybe the file stream reading and writing. This is the Server.
#include <WinSock2.h>
#include <memory.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define MAX_FILE_NAME 100
#define DATA_PACK_SIZE 80*1000 // ??DataPack?????80KB
#define SOCKKET_BUFFER_SIZE 80*1000 // socket???
#define FILE_BUFFER_SIZE DATA_PACK_SIZE-MAX_FILE_NAME-4*sizeof(int)-sizeof(u_long) //?????,??,??????content?????
#define CONTENT_SIZE FILE_BUFFER_SIZE // DataPack?????content???
// Define a structure to hold the content of a file
typedef struct FilePack{
char fName[MAX_FILE_NAME]; // File's name
int fLen; // File's length
int packNum; // Number of the DataPack
int packLen; // DataPack's length
int packCount;
int contenLen; // the content length the DataPack actually holds
u_long index; // ??????????
char content[CONTENT_SIZE]; // DataPack??????
}DataPack, *pDataPack;
void WinsockInitial(){
WSADATA wsaData;
WORD wVersionRequested;
int err;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested, &wsaData);
if(err!=0){
cout<<"Error at WSAStartup()."<<endl;
exit(0);
}
if( LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2 ){
cout<<"Error at version of Winsock. "<<endl;
WSACleanup();
exit(0);
}
}
void SockBind(SOCKET sock, int port, sockaddr_in &addrsock){
addrsock.sin_family=AF_INET;
addrsock.sin_port=htons(port);
addrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if( bind(sock, (sockaddr*)&addrsock, sizeof(addrsock)) == SOCKET_ERROR ){
cout<<"Error at bind(). Error: "<<GetLastError()<<endl;
closesocket(sock);
WSACleanup();
exit(0);
}
}
void SockListen(SOCKET sock, int bak){
int err=listen(sock, bak);
if(err==SOCKET_ERROR){
cout<<"Error at listen()."<<WSAGetLastError()<<endl;
closesocket(sock);
WSACleanup();
exit(0);
}
}
int SockSend(DataPack &dataPack, SOCKET sock, char *sockBuf){
int bytesLeft=0, bytesSend=0;
int idx=0;
bytesLeft=sizeof(dataPack);
// ?DataPack?????sockBuf???
memcpy(sockBuf, &dataPack, sizeof(dataPack));
while(bytesLeft>0){
bytesSend=send(sock, &sockBuf[idx], bytesLeft, 0);
if(bytesSend==SOCKET_ERROR){
cout<<"Error at send()."<<endl;
return 1;
}
bytesLeft-=bytesSend;
idx+=bytesSend;
}
return 0;
}
int GetFileLen(FILE *fp){
// ??????
if(fp==NULL){
cout<<"Invalid argument. Error at GetFileLen()."<<endl;
exit(0);
}
fseek(fp, 0, SEEK_END);
int tempFileLen=ftell(fp);
fseek(fp, 0, SEEK_SET);
return tempFileLen;
}
int main(){
int err;
sockaddr_in addrServ;
int port=8000;
// Initialize Winsock
WinsockInitial();
// Create a socket
SOCKET sockListen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockListen==INVALID_SOCKET){
cout<<"Error at socket()."<<endl;
WSACleanup();
return 1;
}
// Bind the socket.
SockBind(sockListen, port, addrServ);
// Listen for incoming connection requests
cout<<"Waiting for incoming connection requests..."<<endl;
SockListen(sockListen, 5);
// Accept the connection request.
sockaddr_in addrClient;
int len=sizeof(addrClient);
SOCKET sockConn=accept(sockListen, (sockaddr*)&addrClient, &len);
if(sockConn!=INVALID_SOCKET){
cout<<"Connected to client successfully."<<endl;
}
// Set the buffer size of socket
char sockBuf[SOCKKET_BUFFER_SIZE];
int nBuf=SOCKKET_BUFFER_SIZE;
int nBufLen=sizeof(nBuf);
err=setsockopt(sockConn, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, nBufLen);
if(err!=0){
cout<<"Error at setsockopt(). Failed to set buffer size for socket."<<endl;
exit(0);
}
//???????????
err = getsockopt(sockConn, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, &nBufLen);
if( SOCKKET_BUFFER_SIZE != nBuf){
cout<<"Error at setsockopt(). ?socket????????"<<endl;
closesocket(sockListen);
closesocket(sockConn);
WSACleanup();
exit(0);
}
//------------------------------------------------------------------------//
DataPack dataPackSend;
memset(&dataPackSend, 0, sizeof(dataPackSend));
int bytesRead;
int bytesLeft;
int bytesSend;
int packCount; // Counts how many DataPack needed
FILE *frp; // Used to read
if(strcpy_s(dataPackSend.fName, "music.mp3")!=0){
cout<<"Error at strcpy_s()."<<endl;
return 1;
}
// Open the file in read+binary mode
err=fopen_s(&frp, dataPackSend.fName, "rb");
if(err!=0){
cout<<"Error at fopen_s()."<<endl;
return 1;
}
char fileBuf[FILE_BUFFER_SIZE];
// Set the buffer size of File
if(setvbuf(frp, fileBuf, _IONBF, FILE_BUFFER_SIZE)!=0){
cout<<"Error at setvbuf().Failed to set buffer size for file."<<endl;
closesocket(sockListen);
closesocket(sockConn);
WSACleanup();
exit(0);
}
// Get file's length
int fileLen=GetFileLen(frp);
cout<<"File ???:"<<fileLen<<" bytes."<<endl;
// Calculate how many DataPacks needed
packCount=ceil( (double)fileLen/CONTENT_SIZE );
cout<<"File Length: "<<fileLen<<" "<<"Content Size: "<<CONTENT_SIZE<<endl;
cout<<"???"<<packCount<<" ?DataPack"<<endl;
int i=0;
for(i=0; i<packCount; i++){
//?????dataPackSend?????
memset(&dataPackSend, 0, sizeof(dataPackSend));
// Fill the dataPackSend
if(strcpy_s(dataPackSend.fName, "abc.txt")!=0){
cout<<"Error at strcpy_s()."<<endl;
return 1;
}
dataPackSend.packLen=DATA_PACK_SIZE;
dataPackSend.fLen=fileLen;
dataPackSend.packCount=packCount;
if( packCount==1 ){ //??DataPack???
bytesRead=fread(fileBuf, 1, dataPackSend.fLen, frp);
dataPackSend.contenLen=dataPackSend.fLen;
memcpy(dataPackSend.content, fileBuf, bytesRead);
dataPackSend.packNum=0; //???????DataPack
// ?????dataPackSend?Client?
if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
cout<<"??? "<<dataPackSend.packNum<<" ?DataPack"<<endl;
}
}else if( packCount>1 && i<(packCount-1) ){ // ???(???????)
bytesRead=fread(fileBuf, 1, CONTENT_SIZE, frp);
dataPackSend.contenLen=CONTENT_SIZE;
memcpy(dataPackSend.content, fileBuf, bytesRead);
dataPackSend.packNum=i;
//?dataPackSend??????Client?
if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
cout<<"??? "<<dataPackSend.packNum<<" ?DataPack."<<endl;
}
}else{ // ?????
bytesRead=fread(fileBuf, 1, (dataPackSend.fLen-i*CONTENT_SIZE), frp);
dataPackSend.contenLen=dataPackSend.fLen-i*CONTENT_SIZE;
memcpy(dataPackSend.content, fileBuf, bytesRead);
dataPackSend.packNum=i;
//?dataPackSend???Client?
if( SockSend(dataPackSend, sockConn, sockBuf)==0 ){
cout<<"??? "<<dataPackSend.packNum<<" ?DataPack."<<endl;
}
}
}
fclose(frp);
closesocket(sockListen);
closesocket(sockConn);
WSACleanup();
return 0;
}
And this is Client.
#include <WinSock2.h>
#include <memory.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
#define MAX_FILE_NAME 100
#define DATA_PACK_SIZE 80*1000 // ??DataPack?????80KB
#define SOCKKET_BUFFER_SIZE 80*1000 // socket???
#define FILE_BUFFER_SIZE DATA_PACK_SIZE-MAX_FILE_NAME-4*sizeof(int)-sizeof(u_long) //?????,??,??????content?????
#define CONTENT_SIZE FILE_BUFFER_SIZE // DataPack?????content???
// Define a structure to hold the content of a file
typedef struct FilePack{
char fName[MAX_FILE_NAME]; // File's name
int fLen; // File's length
int packNum; // Number of the DataPack
int packLen; // DataPack's length
int packCount; //DataPack???
int contenLen; // the content length the DataPack actually holds
u_long index; // ??????????
char content[CONTENT_SIZE]; // DataPack??????
}DataPack, *pDataPack;
void WinsockInitial(){
WSADATA wsaData;
WORD wVersionRequested;
int err;
wVersionRequested=MAKEWORD(2,2);
err=WSAStartup(wVersionRequested, &wsaData);
if(err!=0){
cout<<"Error at WSAStartup()."<<endl;
exit(0);
}
if( LOBYTE(wsaData.wVersion)!=2 || HIBYTE(wsaData.wVersion)!=2 ){
cout<<"Error at version of Winsock. "<<endl;
WSACleanup();
exit(0);
}
}
int SockRecv(SOCKET sock, char *sockBuf){
int bytesLeft, bytesRecv;
int idx=0;
bytesLeft=DATA_PACK_SIZE;
while(bytesLeft>0){
bytesRecv=recv(sock, &sockBuf[idx], bytesLeft, 0);
if(bytesRecv==SOCKET_ERROR){
cout<<"Error at recv()."<<endl;
return 1;
}
bytesLeft-=bytesRecv;
idx+=bytesRecv;
}
return 0;
}
int main(){
int err;
sockaddr_in addrServ;
int port=8000;
// Initialize Winsock
WinsockInitial();
// Create a socket
SOCKET sockClient=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockClient==INVALID_SOCKET){
cout<<"Error at socket()."<<endl;
WSACleanup();
return 1;
}
// Set the buffer size of socket
char sockBuf[SOCKKET_BUFFER_SIZE];
int nBuf=SOCKKET_BUFFER_SIZE;
int nBufLen=sizeof(nBuf);
err=setsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, nBufLen);
if(err!=0){
cout<<"Error at setsockopt(). Failed to set buffer size for socket."<<endl;
exit(0);
}
//???????????
err = getsockopt(sockClient, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, &nBufLen);
if( SOCKKET_BUFFER_SIZE != nBuf){
cout<<"Error at getsockopt(). ?socket????????"<<endl;
closesocket(sockClient);
WSACleanup();
exit(0);
}
// Connect to the Server
addrServ.sin_family=AF_INET;
addrServ.sin_port=htons(port);
addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
err=connect(sockClient, (sockaddr*)&addrServ, sizeof(sockaddr));
if(err==SOCKET_ERROR){
cout<<"Error at connect()."<<GetLastError()<<endl;
closesocket(sockClient);
WSACleanup();
return 1;
}else{
cout<<"Connected to the FTP Server successfully."<<endl;
}
/*
int i=0;
int bytesRecv, bytesLeft, bytesWrite;
int packCount=0, fLen=0;
DataPack dataPackRecv;
//??????
SockRecv(sockClient, sockBuf);
memcpy(&dataPackRecv, sockBuf, sizeof(dataPackRecv));
cout<<"???? "<<dataPackRecv.packNum<<" ?DataPack."<<endl;
cout<<"?DataPack??fName????: "<<dataPackRecv.fName<<endl;
//???????
packCount=dataPackRecv.packCount;
cout<<"?? "<<packCount<<" ?DataPack."<<endl;
fLen=dataPackRecv.fLen;
// Create a local file to write into
FILE *fwp;
err=fopen_s(&fwp, dataPackRecv.fName, "wb");
if(err!=0){
cout<<"Error at creat fopen_s(). Failed to create a local file to write into."<<endl;
return 1;
}
// Set the buffer size of File
char fileBuf[FILE_BUFFER_SIZE];
if(setvbuf(fwp, fileBuf, _IONBF, FILE_BUFFER_SIZE)!=0){
cout<<"Error at setvbuf().Failed to set buffer size for file."<<endl;
memset(fileBuf, 0, sizeof(fileBuf));
closesocket(sockClient);
WSACleanup();
exit(0);
}
//???????content????
memcpy(fileBuf, dataPackRecv.content, sizeof(dataPackRecv.content));
bytesWrite=fwrite(fileBuf, 1, sizeof(fileBuf), fwp);
if(bytesWrite<sizeof(fileBuf)){
cout<<"Error at fwrite(). Failed to write the content of dataPackRecv to local file."<<endl;
}
//?????packCount-1?????????????????
for(int i=1; i<packCount; i++){
// ?????????
memset(sockBuf, 0, sizeof(sockBuf));
memset(&dataPackRecv, 0, sizeof(dataPackRecv));
memset(fileBuf, 0, sizeof(fileBuf));
SockRecv(sockClient, sockBuf);
memcpy(&dataPackRecv, sockBuf, sizeof(dataPackRecv));
cout<<"???? "<<dataPackRecv.packNum<<" ?DataPack."<<endl;
//????
memcpy(fileBuf, dataPackRecv.content, dataPackRecv.contenLen);
bytesWrite=fwrite(fileBuf, 1, dataPackRecv.contenLen, fwp);
if(bytesWrite<dataPackRecv.contenLen){
cout<<"Error at fwrite(). Failed to write the content of dataPackRecv to local file."<<endl;
}
}
if( (i+1)==packCount ){
cout<<"??DataPack????????!"<<endl;
}
fclose(fwp);
closesocket(sockClient);
WSACleanup();
return 0;*/
}