Multiple File Transfer using BSD socket
I intended to implement multiple file transfers in the Socket File transfer post :
https://www.arupsarker.com/blog/file-transfer-using-bsd-socket . If I did that, the whole post would be very long. The whole idea is to implement multiple file transfer with BSD socket, by using the previous code of file read/write mechanism at the server and client code. I will try to keep it short.
Here is the basic step:
On the server side,
Create a server socket.
Bind socket with server address.
Open a listener to accept the client connection request and wait for an incoming request
Accept client connection requests in a loop for multiple connections.
Now the connection is established. Implement logic for handling incoming files.
Receive a file name from the client and create an empty file with that name.
Start receiving file data line by line and write to the file.
After receiving one file, create a new connection and receive the next one.
On the client side,
Read all the files from a directory.
For each file, repeat steps 2 to 6.
Create a client socket.
Connect with the server socket where there is a listener.
After the connection is successful, send the File Name to the server.
Send data line by line using the socket file descriptor.
From the post, https://www.arupsarker.com/blog/file-transfer-using-bsd-socket , I have just included the accept and recv functions inside the while loop.
Server-side Changes:
We are creating a new connection from the client for each file. Although, it is not a good design. Later with concurrency, we will be able to overcome this design.
Anyway, for starting the basic transfer mechanism, we are good for now.
while(1) { // Only these two read marked lines are added.
// 6. Accept connection for concurrency number
socklen_t adlen = sizeof(nwClientAddr);
int cfd = accept(sockfd, (struct sockaddr *) &nwClientAddr, &adlen);
if (cfd == -1) {
perror("Error in Accepting Connection for ");
exit(1);
}
// 7. Receive incoming file from client
char filename[MAX_NAME] = {0};
if (recv(cfd, filename, MAX_NAME,0) == -1) {
perror("Unable to receive file due to connection or file error");
exit(1);
}
int fileLength = strlen(filename);
if(fileLength > 0) {
// 8. After receiving from client, create file to save data
FILE *fp = fopen(filename, "wb");
if (fp == NULL) {
perror("Unable to create File pointer");
exit(1);
}
// 9. Start receiving file Data and print in console
char addr[INET_ADDRSTRLEN];
// 10. Write the data into file.
fileWriter(filename, cfd, fp);
// 11. Print success message into console
printf("%s is received\n",filename);
}
close(cfd);
}
Client Side changes:
At the client side,
1. We have to read each file from the directory.
2. For each file, we are repeating the steps mentioned in the first part.
These are the newly added codes in the main function.
Inside the while loop for each file, we are calling red lines which was a single call in single file transfer.
char *dirName = basename(argv[1]);
if (dirName == NULL) {
perror("Unable to get dirName");
exit(1);
}
// 4. Read All the file list from directory
DIR *dirPtr = opendir (dirName);
// 5. validate directory open
if (!dirPtr) {
char errbuf[PATH_MAX] = "";
sprintf (errbuf, "opendir failed on '%s'", dirName);
perror (errbuf);
return EXIT_FAILURE;
}
printf("Directory name : %s\n", dirName);
struct dirent *dir;
int idx = 0;
char filePathList[MAX_FILE_COUNT][MAX_NAME] = {0};
char fileNameList[MAX_FILE_COUNT][MAX_NAME] = {0};
if(dirPtr!=NULL) {
int flag = 0;
while((dir=readdir(dirPtr))!=NULL) {
if((strcmp(dir->d_name,".")==0 || strcmp(dir->d_name,"..")==0 || (*dir->d_name) == '.' )){
}
else
{
// 6. Define and Initialize the Buffer
char buff[MAX_NAME] = {0};
char fileWithPath[MAX_NAME] = {0};
strcat(fileWithPath, dirName);
strcat(fileWithPath, "/");
strcat(fileWithPath, dir->d_name);
// 7. Copy the file name into Buffer
strncpy(buff, dir->d_name, strlen(dir->d_name));
sockUtil(argv[2], buff,fileWithPath); // This was a single call for single file transfer
printf("%s\n", fileWithPath);
idx++;
}
}
}
if(idx == 0) {
printf("There is no file in the directory : %s\n", dirName);
return 1;
}
Prepare
$ git clone https://github.com/arupcsedu/BSDSocketProgramming.git
$ cd BSDSocketProgramming
Build and Run Server
$ cd SockMFileTransfer/Server
$ g++ Server.cpp -o Server
$ ./Server
Build and Run Client
$ cd ..
$ cd Client
$ dd if=/dev/zero of=res/s1 bs=10MB count=1 //This is for creating 10MB file in res directory. Execute multiple times for creating multiple files.
$ g++ Client.cpp -o Client
$ ./Client res 127.0.0.1
Source code URL:
https://github.com/arupcsedu/BSDSocketProgramming