I'm sending a file from the client to the server.
Client sends filename
Server receives filename
Client sends file size
Server receives file size
Client sends file contents
Server receives file contents
When I print out the file size that I sent, it is the exact number of bytes as the file I wish to send so that's fine. The issue is that the server (receives) doesn't seem to exit the while loop when writing to the new file. I know this because the final print statement printf("The server has received the requested document\n"); is never reached and it just hangs. What could be causing this?
Client snippet (sends):
else if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
size_t size, bytes_read, bytes_written;
int x;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((x = write(sd, buf, sizeof(buf))) < 0){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("Sending file size\n");
if((write(sd, &size, sizeof(size))) < 0){ //sending filesize
printf("error sending file size\n");
}
printf("Sending file\n");
while((bytes_read = fread(buf, 1, sizeof(buf), fp)) > 0){ //sending file contents
if ((bytes_written = write(sd, buf, bytes_read)) < 0){
printf("Error sending client file.\n");
}
}
printf("bytes written: %ld\n", bytes_written);
fclose(fp);
}
}
Server snippet (receives):
if(strcmp(shortCommand, "put") == 0){
char *tmp = buf + 4;
char filename2[MAX_BLOCK_SIZE];
size_t filesize;
size_t total_bytes_read = 0;
ssize_t bytes_read = 0;
size_t error;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n"); //filename is received on the first read before this IF
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file size...\n");
if((error = read(sd, &filesize, sizeof(filesize))) < 0){ //receiving file size
perror("Error reading filesize\n");
exit(1);
}
printf("Filesize is: %ld \n", filesize);
while(total_bytes_read < filesize){
while((bytes_read = read(sd, buf, sizeof(buf))) > 0){ //receving file contents and writing to file
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
if(ferror(fp)){
perror("error");
fclose(fp);
}
}
}
printf("The server has received the requested document.\n");
fflush(stdout);
fclose(fp);
}
After I exit the program by force, I can actually see that the file has been copied. Just doesn't exit that while loop to let me go back to the client.
Time for some basic debugging. I'd suggest changing your read loop to something like this:
while (total_bytes_read < filesize) {
printf("DEBUG A: total=%zu, size=%zu\n", total_bytes_read, filesize);
while ((bytes_read = read(sd, buf, sizeof(buf))) > 0) {
printf("DEBUG B: read=%zd\n", bytes_read);
fwrite(buf, 1, bytes_read, fp);
total_bytes_read += bytes_read;
printf("DEBUG C: total=%zu\n", total_bytes_read);
if (ferror(fp))
printf("DEBUG D\n");
perror("error");
fclose(fp);
}
printf("DEBUG E\n");
}
printf("DEBUG F\n");
}
printf("DEBUG G\n");
Then run it, piping the output through less or some other pager, it should then hopefully become clearer what's actually happening.
Feel free to post the output of this modified code (in a comment, or in the actual question), we'll no doubt be able to help with the analysis.
Related
In here I am sending file name first then sending the file in chunks, then trying to read the received message but it is just freezing. No respond. But after loop if I shutdown the WR shutdown(connfd,SHUT_WR); It is working fine. Though I should be able to send message again, if I do this I can not do that.
CLIENT.C
write(sockfd, fname,100);
FILE *fp = fopen(fname,"rb");
if(fp==NULL)
{
printf("File opern error");
exit(1);
}
int hi = 0;
while(1)
{
/* First read file in chunks of 256 bytes */
unsigned char buff[1024]={0};
int nread = fread(buff,1,1024,fp);
/* If read was success, send data. */
if(nread > 0)
{
hi++;
//printf("Sending \n");
write(sockfd, buff, nread);
}
if (nread < 1024)
{
if (feof(fp))
{
printf("File transfer completed!\n");
}
if (ferror(fp))
printf("Error reading\n");
break;
}
}
char fname2[100];
// cant read
read(sockfd, fname2, 100);
printf("File Name: %s\n",fname2);
SERVER.C
FILE *fp;
int bytesReceived = 0;
char recvBuff[1024];
char fname[100];
char fname2[100];
read(newsockfd, fname, 100);
//strcat(fname,"AK");
printf("File Name: %s\n",fname);
printf("Receiving file...");
fp = fopen(fname, "ab");
if(NULL == fp)
{
printf("Error opening file");
}
long double sz=1;
/* Receive data in chunks of 256 bytes */
printf("\nCompleted.\n");
int hi = 0;
while((bytesReceived = read(newsockfd, recvBuff, 1024)) > 0)
{
hi++;
sz++;
fwrite(recvBuff, 1,bytesReceived,fp);
}
printf("Not pring this this!");
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
write(newsockfd, "SayGee",100);
I had to send the size of the file, then check from the other side inside loop. It was in deadlock.I found the solution. So thanks anyway!
I want to be able to send a file from the client to the server. I'm using TCP. I'm trying to use fseek and etc to get the size of the file because I want to be able to handle large files, and then send that amount of bytes of data as well as the files contents to the server. So far, according to my printf messages everything goes through and the file is created. However, the file created on the server is empty. There's obviously something wrong with the way I am sending it and receiving it via parameters or something, but I can't figure it out. Can someone please show me where I've gone wrong and how I can fix it because I'm so close!
Server part:
if(getFile){
char *tmp = buf + 9;
char filename2[MAX_BLOCK_SIZE];
int length, x;
long file_size = 0;
FILE *fp;
strcpy(filename2, tmp);
printf("Server receiving file name...\n");
//first 'read' receives the file name
fp = fopen(filename2, "wb");
if(fp == NULL){
printf("File could not be opened.\n");
exit(1);
}
printf("Server receiving file...\n");
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, file_size, fp);
}
fclose(fp);
printf("The server has received the requested document.\n");
}
Client side:
else if(putCommand){
char *tmp = buf + 4;
char filename[MAX_BLOCK_SIZE];
long file_size;
strcpy(filename, "filename ");
strcat(filename, tmp);
FILE *fp;
printf("File name: %s\n", tmp);
fp = fopen(tmp, "rb");
if(fp == NULL){
printf("ERROR: Requested file does not exist.\n");
}
else{
printf("Client sending filename...\n");
if ((nw = write(sd, filename, sizeof(filename)) < nr)){ //sending the file name to the client first
printf("Error sending client's filename.\n");
}
//size_t file_size;
printf("Client sending file...\n");
fseek(fp, 0, SEEK_END);
long filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
while((file_size = fread(buf, 1, MAX_BLOCK_SIZE, fp)) > 0){ //sending the file
if ((x = write(sd, buf, filesize) < 0)){
printf("Error sending client file.\n");
}
}
fclose(fp);
}
It is close to a typo. On the receiver side, you have:
long file_size = 0;
...
while(...)
...
fwrite(buf, 1, file_size, fp);
So you consistently write 0 byte.
The standard way is:
while((x = read(sd, buf, sizeof(buf)) > 0)){ //second read now retrieving the file
printf("Server creating new file...\n");
fwrite(buf, 1, x, fp); // write the number of bytes returned by previous read
}
Last remark, I hope that buf is a true array and not a pointer...
I have written the following code for sending file from a client:
FILE *fp = fopen("video.mp4","rb");
if(fp==NULL)
{
printf("File opern error");
return 1;
}
int bytesToWrite=84440670;
int bytesWritten=0;
while(bytesWritten<bytesToWrite)
{
int m=minimum(256,bytesToWrite-bytesWritten);
/* First read file in chunks of 256 bytes or the remaining bytes*/
unsigned char *buff=malloc(sizeof(char)*m);
bzero(buff, m);
int nread = fread(buff,1,m,fp);
printf("Bytes read %d \n", nread);
bytesWritten+=m;
/* If read was success, send data. */
if(nread > 0)
{
printf("Sending \n");
write(sockfd, buff, nread);
}
/*
* There is something tricky going on with read ..
* Either there was error, or we reached end of file.
*/
if (nread < 256)
{
if (feof(fp))
printf("End of file\n");
if (ferror(fp))
printf("Error reading\n");
break;
}
}
and the following code for receiving by the server :
FILE *fp;
fp = fopen("receive.mp4", "wb");
if(NULL == fp)
{
printf("Error opening file");
return 1;
}
int bytesToRead=84440670;
/* Receive data in chunks of 256 or remaining bytes */
int totalbytesread=0;
while(totalbytesread < bytesToRead)
{
int m = minimum(256,bytesToRead-totalbytesread);
char *recvBuff=malloc(sizeof(char)*m);
bzero(recvBuff,m);
bytesReceived = read(newsocfd, recvBuff,m );
printf("Bytes received %d\n",bytesReceived);
totalbytesread += bytesReceived;
fwrite(recvBuff, 1,bytesReceived,fp);
}
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
The sending is working correctly for .txt files ,some data is being lost in sending other formats(for e.g some ending seconds of .mp4 files is not being sent).
I am new to socket programming. Any help would be deeply appreciated.
You are missing a fclose(fp); in the server after you have finished receiving. You can also use fflush(fp); to just flush the contents.
Besides, there are several memory leaks and improper error handling.
I was trying to implement FTP Server as a part of an assignment and I wrote the following code to implement GET Command, which essentially reads file1 from server and stores it in file2.
int getCommandImpl(int clientSocket, char *file1, char *file2){
char *messageContent;
char buffer[256], userCommand[256], *tempString ;
int messageHead, endOfTransfer =0;
int messageLength;
sprintf(userCommand, "GET %s", file1);
messageLength = write(clientSocket,userCommand,strlen(userCommand));
if(messageLength <0){
perror("Error sending data to server in RETR");
return 0;
}
FILE *fp;
fp = fopen(file2, "w");
if(fp==NULL){
printf("%s Can not be created\n", file2);
return 0;
}
printf("Writing to file %s\n", file2);
while(!endOfTransfer){
messageLength = read(clientSocket, buffer, strlen(buffer)-1);
if(messageLength == -1){
perror("GET: Error in read() ");
break;
}
//puts(buffer);
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
tempString = strdup(buffer);
messageHead = atoi(strtok(tempString, " "));
messageContent = strtok(NULL, " ");
if(messageHead == 0 && strlen(messageContent)==0){ //End of file transfer
endOfTransfer = 1;
break;
}
fwrite(messageContent, sizeof(char), sizeof(messageContent), fp);
memset(buffer,0,sizeof(buffer));
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
}
fclose(fp);
return 1;
}
While running it, I am always getting the error "GET: Error in read() : Bad address". If I remove the statement
memset(buffer,0,sizeof(buffer));
I am getting a segmentation fault. I am assuming that the error has something to do with the string buffer being empty from the second iteration.
Any help to solve this will be highly appreciated.
I'm trying to send files using TCP from a windows client to a Linux server in C.
The size of the buffer I use to send the data is 65535. When the size of the file exceeds this value, I get an error saying 'connection reset by peer' or the error code 10054. When the size of the file is less than 65535 bytes, the server receives only a part of it (usually 2760 bytes).
I just want to send files with a maximum size of 50 MB.
This is the part of the windows client that I use to send data:
char *fileName; // pointer to filename
char buf[65535]; // buffer
int fileSize; // # bytes to send
for(i = 0; i < ARRAYSIZE; i++) {
if(selectList[i] != NULL) {
// select file
fileName= selectList[i]; // get path and filename from selectList
printf("=============================================\nSending: %s\n", fileName);
filefd = fopen(fileName, "rb"); // open file
if(filefd == NULL) {
printf("File %s not found\n", fileName);
exit(1);
}
// read and send file
memset(buf, '\0', 65535);
while((fileSize= fread(buf, sizeof(char), 65535, filefd)) > 0) { // read file
if((numberOfBytes = send(sockfd, buf, fileSize, 0)) < 0) { // send buffer
printf("send: %s (Error: %d)\n", filename, WSAGetLastError());
break;
}
printf("#bytes = %i \n", numberOfBytes);
memset(buf, '\0', 65535);
}
printf("File %s send!\n", filename);
// close file after sending it
if(fclose(filefd) < 0) {
printf("fclose: %i", WSAGetLastError());
}
} else if(selectList[0] == NULL) {
printf("no files selected");
}
}
The selectList contains multiple strings such as: C:\Windows\test.txt
The recieve part of the Linux server:
char* fr_name = "/home/MtFS/UploadedFiles/public/testFile.gif";
FILE *fr = fopen(fr_name, "wb");
if(fr == NULL)
printf("[Open_File]file %s cannot be created\n", fr_name);
else {
bzero(revbuf, LENGTH);
int fr_block_sz = 0;
while((fr_block_sz = recv(nsockfd, revbuf, LENGTH, 0)) > 0) {
int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);
if(write_sz < fr_block_sz) {
error("[Write] error\n");
}
bzero(revbuf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512) {
break;
}
}
if(fr_block_sz < 0) {
if (errno == EAGAIN) {
printf("[Receive] time out\n");
}
else {
printf("[Receive] error\n");
exit(1);
}
}
printf("[Receive] succesfull\n");
fclose(fr);
}
What am I doing wrong?
Your problem are those 3 lines of code. That's not the correct way to know that you're done:
if (fr_block_sz == 0 || fr_block_sz != 512) {
break;
}
Also you check against 512 instead of LENGTH. But only 0 means that you're done (assuming your connection is not NONBLOCKED.)
As a side note: you do not have to clear your buffers (bzero, memset) before using them with a read since the read/recv will overwrite the content of the buffers anyway.
I think the culprit is this line in your server
if (fr_block_sz == 0 || fr_block_sz != 512) {
fr_block_sz cab be anything between 1 to 65535 - the size block that you sent.
In your code, when its not 512 so your server is terminating the connection.