I have a bunch of weird characters in my output file when I send it from the client to the server. When I stream the server into an array and print it out, it looks good and legible. However, when I send it over to the server, I get a bunch of weird characters and MICROSOFT everywhere in the text document. Anybody know what's wrong?
Client:
if(sendSize <=0){
for(;;){
unsignedchar buff[256]={0};
int nread = fread(buff,1,256, fp);
total = total + nread;
percentage =(total / fFileSize)*100;
printf("\r%s: Percentage sent: %.2f", NAME_C, percentage);
/* Send data in 256 byte chunks */
if(nread >0){
send(clientSock, buff, nread, 0);
}
if(nread <256){
if(feof(fp)){
printf("\nSend Success!\n");
break;
}
}
}
//printf("%.2f", total);
}
Server:
/* Receive data from client */
char* fileName ="test.txt";
FILE*fp = fopen(fileName,"w+");;
float total =0;
float bytesReceived;
unsignedchar buff[256]={0};
float percentage =(bytesReceived / total)*100;
while((bytesReceived = recv(listenSock, buff,sizeof(buff),0))<0){
//bytesReceived = recv(listenSock, buff, 256, 0);
if(bytesReceived >0){
printf("DONE");
}
//total = total + bytesReceived;
fwrite(buff,sizeof(char), bytesReceived, fp);
//printf("\r%s: Percentage received: %.2f", NAME_C, percentage);
}
Your server's recv() loop is using <0 when it should be using >0 instead. recv() returns -1 on error, 0 on graceful disconnect, and >0 on bytes received.
Also, is listenSock the actual listening socket, or the socket returned by accept()? You should be passing the latter to recv(). My guess is that you are passing the former instead, causing recv() to fail and return -1, which you then enter the body of the loop with garbage buff data and a bad bytesReceived value. The third parameter of fwrite() is a size_t, which is an unsigned type, so passing a signed value of -1 will get interpreted as an unsigned value of 4294967295 or even 18446744073709551615, depending on the size of size_t. Either way, you would be writing garbage to your file, or even crashing the code trying to access invalid memory.
There are other minor issues with your code as well. Try something more like this instead:
Client:
if(sendSize <=0){
unsigned char buff[256];
do{
int nread = fread(buff, sizeof(char), 256, fp);
if (nread > 0){
total += nread;
percentage = (total / fFileSize)*100;
printf("\r%s: Percentage sent: %.2f", NAME_C, percentage);
/* Send data in 256 byte chunks */
if (send(clientSock, buff, nread, 0) == -1){
printf("\nSend Failed!\n");
break;
}
}
if (nread != 256){
if (feof(fp)){
printf("\nSend Success!\n");
else
printf("\nRead Failed!\n");
break;
}
}
while (1);
//printf("%.2f", total);
}
Server:
/* Receive data from client */
char* fileName = "test.txt";
FILE* fp = fopen(fileName, "wb+");
if (!fp){
printf("\nOpen Failed!\n");
}
else{
float total = 0;
float percentage = 0;
int bytesReceived;
unsigned char buff[256];
do{
bytesReceived = recv(acceptedSock, buff, sizeof(buff), 0);
if (bytesReceived <= 0){
if (bytesReceived < 0){
printf("\nRecv Failed!\n");
}
else{
printf("\nDisconnected!\n");
}
break;
}
//total += bytesReceived;
//percentage = ...
if (fwrite(buff, sizeof(char), bytesReceived, fp) != bytesReceived){
printf("\nWrite Failed!\n");
break;
}
//printf("\n%s: Percentage received: %.2f", NAME_C, percentage);
}
while (1);
}
Related
I am writing a program that a client can ask for files to a server. Then the server will send them in chunks of 512 bytes. The problem is that when the client read the file:
*Sometimes the first 512 bytes are different from the original file. The total read file also has a different size (and obviously it also ends different from the original file) and therefore the client loop that writes to the new file does never end.
*Sometimes it works perfectly and i don't know why.
Server:
/* Check if file exists */
if(access(retrFileName, F_OK) == 0){
/* Open file */
fd = open(retrFileName, O_RDONLY);
lseek(fd, 0, SEEK_SET);
if (fd == -1){
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &fileStat) < 0){
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
sprintf(fileSize, "%li", fileStat.st_size);
/* Sending file data */
offset = 0;
remainData = fileStat.st_size;
while (((sentBytes = sendfile(clientSock, fd, &offset, 512)) == 512) && (remainData > 0)) {
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);
}
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);//do while
close(fd);////////////////////////
send(clientSock, NICETRANSFER, sizeof(NICETRANSFER), 0); //LO METE AL ARCHIVO
printf("send\n");
//close(clientSock);///////////
}
else{
send(clientSock, FILEERROR, sizeof(FILEERROR), 0);
printf("send\n");
}
}
Client:
/* Open file */
receivedFile = fopen("r.txt", "wb");
if (receivedFile == NULL){
fprintf(stderr, "Failed to open file --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Write to the file */
int contador = 0;
int remainData = fileSize;
do{
if(remainData < 512)
bytesLeidos = recv(clientSock, readingBuffer, remainData, 0);
else
bytesLeidos = recv(clientSock, readingBuffer, 512, 0);
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= 512;
contador += 512;
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}while(contador < fileSize);
fclose(receivedFile);
Golden rule of socket programming: Always check the return value from recv. It's not always what you think it will be.
Even though you "send" 512 bytes at a time, you are in no way guaranteed that TCP will deliver the same number of bytes at a time to the receiver. TCP segmentation, IP fragmentation, and general Internet weirdness will cause the recv side to get an arbitrary number of bytes at a time.
Hence, your hardcoded assumption that recv will always return 512 is incorrect:
remainData -= 512;
contador += 512;
Instead, you should be saying:
remainData -= bytesLeidos;
contador += bytesLeidos;
An you need to check for errors and socket closing too.
This is an improved main loop for your client code:
while (remainData > 0)
{
size_t recvSize = (remainData >= 512) ? 512 : remainData;
bytesLeidos = recv(clientSock, readingBuffer, recvSize, 0);
if (bytesLeidos > 0)
{
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= bytesLeidos;
contador += bytesLeidos;
/* null terminate readingBuffer so garbage isn't printed.*/
/* Make sure readingBuffer is allocated to be at least */
/* N+1 bytes (513) to account for this character being appended. */
readingBuffer[bytesLeidos] = '\0';
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}
else if (bytesLeidos == 0)
{
/* remote side closed connection */
printf("Remote side exited connection\n");
break;
}
else if (bytesLeidos < 0)
{
/* connection error */
printf("Connection error\n");
break;
}
}
I solved my problem!! I needed to sync both client and server. To do so, the server send the size of the file and waits for an answer for the client with recv. When the client recieve the file size, it send a "" message.
I don't know if this is the correct solution, but this way you can sync server and client.
After sync, the server send the respective file normally with sendfile
I am trying to send a file from client to server. It sometime worksand sometime don't. when first time trying to send file, it sends corrupt file and the file side formed at server side is double of its size. But file successful transfers for all attempts after first attempt. Can anyone help me with this ?
Client.c
message msg;
msg.type = SEND_FILE;
char *username, *filename;
username = strtok(input+6, " ");
filename = strtok(NULL, "");
//Get Picture Size
printf("Getting Picture Size\n");
FILE *picture;
picture = fopen(filename, "r");
int size;
fseek(picture, 0, SEEK_END);
size = ftell(picture);
fseek(picture, 0, SEEK_SET);
//Send Picture Size
printf("Getting Picture Size\n");
sprintf(msg.data, "%d", size);
strncpy(msg.username, username, 20);
if(send(connection->socket, &msg, sizeof(message), 0) < 0)
{
perror("Send failed");
exit(1);
}
//Send Picture as Byte Array
printf("Sending Picture as Byte Array\n");
char send_buffer[size+1];
fread(send_buffer, 1, sizeof(send_buffer), picture);
write(connection->socket, send_buffer, sizeof(send_buffer));
bzero(send_buffer, sizeof(send_buffer));
server.c
//Read Picture Size
printf("Reading Picture Size\n");
int size = atoi(message_text);
//Read Picture Byte Array
printf("Reading Picture Byte Array\n");
char p_array[size];
printf("Converting Byte Array to Picture %d\n", size);
FILE *image;
image = fopen("c4.png", "w");
int readSize = 0;
while (readSize < size) {
readSize = readSize + read(clients[sender].socket, p_array, size);
fwrite(p_array, 1, sizeof(p_array), image);
}
fclose(image);
For starters:
You don't want to store the same number of bytes on every fwrite()
fwrite(p_array, 1, sizeof(p_array), image);
but only the number of bytes actually read.
sizeof(p_array) returns the size of p_array, which is size times the size of a char. The latter is defined as being 1.
Besides this the call to read() completely lacks error checking, along with the test whether the other side shut down the connection. This is not leading far.
To fix this you could do:
#include <errno.h> /* for errno */
...
size_t size = atoi(message_text);
printf("Reading Picture Byte Array\n");
char p_array[size];
size_t readSize = 0;
while (readSize < size) {
ssize_t result = read(clients[sender].socket, p_array, size); /* Mind the ssize_t, it's *not* size_t! */
if (0 >= result)
{
if (0 == result)
{
fprintf(stderr, "The other end gracefully shut down the connection.\n");
break;
}
else
{
if (EINTR == errno) /* got interrupted, start over */
{
continue;
}
if (EAGAIN == errno) /* in case reading from a non-blocking socket: no data available, start over */
{
continue;
}
/* Something went wrong unrecoverable. */
perror("read() failed");
break;
}
}
else
{
fwrite(p_array, 1, result, image);
/* Also add error checking here! */
readSize += result;
}
}
I'm doing a little project of TCP connection by C language, and the problem with my code is mentioned in the title. And the following is the uploading part of my code
Client Side:
FILE * fp = fopen(f2d, "rb+");
if(fp == NULL) perror("Fail to upload(client)");
else
{
fseek(fp, 0, SEEK_END);
int filesize = ftell(fp);
memset(buf, '\0', MAX_SIZE);
sprintf(buf, "%d", filesize);
send(serverSocket, buf, strlen(buf), 0); //send the filesize to the server
rewind(fp);
int byteNum = 0, z = 0;
printf("Uploading......\n");
while((z += byteNum) < filesize)
{
memset(buf, '\0', MAX_SIZE);
byteNum = fread(&buf, sizeof(char), sizeof(buf), fp);
printf("Bytes read to buf : %d\n", byteNum);
send(serverSocket, buf, sizeof(buf), 0);
printf("Totally sent bytes: %d\n", z);
}
printf("Upload completed.\n");
}
fclose(fp);
Server Side:
printf("Upload Requested.\n");
f2df = fopen(buf + 4, "wb+");
if(f2df == NULL) perror("Fail to upload(server)");
else
{
memset(buf, 0, MAX_SIZE);
recv(clientSocket, buf, sizeof(buf), 0); //receive the filesize
int filesize = atoi(buf);
int recvNum = 0, recv_Num = 0;
while((recvNum += recv_Num) < filesize)
{
memset(buf, 0, MAX_SIZE);
recv_Num = recv(clientSocket, buf, sizeof(buf), 0);
fwrite(&buf, sizeof(char), sizeof(buf), f2df);
printf("Bytes received from recv: %d\n", recv_Num);
printf("Totally received bytes: %d\n", recvNum);
}
printf("Upload completed.\n");
}
fclose(f2df);
The idea of my code is to send and receive the bytes until it reaches the filesize. But with a very high frequency(well, sometimes it functions normally, all bytes are transferred to the server) that the server seems to miss some bytes sent from the client(and the return value of "recv" function will then be zero after the client has sent all the bytes to the server, which makes the terminating condition of the while loop never be reached), which then causes an infinitive loop on the server side.
P.S. all the other functions are without problems(e.g. sending and receiving filesize, the actual number of the filesize... etc), I had tested them all. And there's also no problem on the client side.
And the following is the screenshot of the problem
So can anyone help me out with that, I've been trying to deal with this for weeks, thanks a lot in advance!
Go through you entire client and server code and fix:
1) All those times where you do not handle correctly the results returned from system calls. This especially applies to the result returned by recv() which can be negative, (error), zero, (peer closed the connection), or some positive number less than, or equal to, the number of bytes requested - the ONLY WAY YOU CAN TELL FOR SURE HOW MANY BYTES HAVE BEEN READ IN TO THE BUFFER. Forget the number of bytes requested in the call and any memset/bzero before, and/or strlen/whatever after, it returns, they are all inadequate/misleading.
2) All those times where you assume that, just because you request the recv() of X bytes and recv() returns a positive number, that number will be X.
3) All those times that you call any str* C-style library calls on any buffers that are not 100% guaranteed to be NULL-terminated.
The main problem is the (not) handling of the send() return value, because even in the absence of any error condition, send() may return a smaller value than requested (e. g. if a buffer is full). After each loop cycle in the client, you increment z by the number of bytes read to buf, but disregard that a smaller number of bytes may have been sent. This leads to the outcome that the client loop completes without having sent all data, despite of incorrectly saying so. Change that e. g. to:
printf("Uploading......\n");
while (z < filesize)
{
byteNum = fread(buf, sizeof(char), sizeof buf, fp);
printf("Bytes read to buf : %d\n", byteNum);
int sent = 0;
while (byteNum > 0)
{
int ret = send(serverSocket, buf+sent, byteNum, 0);
if (ret < 0) { perror("send"); goto fail; }
sent += ret, byteNum -= ret;
printf("Totally sent bytes: %d\n", z += ret);
}
}
printf("Upload completed.\n");
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.
My server code is as follows:
while(bytes_written < filesize){
//Send from send_ptr
bw = send(child_socket, send_ptr, newLength, 0);
printf("%d bytes written\n", (int)bw);
//Increment bytes written
bytes_written += bw;
//Move send pointer
send_ptr = send_ptr + bw;
}
And my client code is as follows:
while((num_bytes_recv = read(sd, jpgBufferPointer, BUFFER_LENGTH))>0){
total_bytes_recv += num_bytes_recv;
printf("Read %d bytes\n",num_bytes_recv);
//Check for error
if(jpgError == NULL)
jpgError = strstr(jpgBufferPointer, "404 Not Found");
if(jpgError != NULL){
//Forwarding error response
if(send(sd, jpgBuffer, num_bytes_recv, 0) == -1){
error("Failed to send response message to client");
}
}
else{
//Find content size
contentSizeBuffer = strstr(jpgBufferPointer,"Content-Length");
if(contentSizeBuffer != NULL){
contentSizeBuffer=contentSizeBuffer+16;
contentSize=atoi(contentSizeBuffer);
jpgBuffer=(char*)realloc(jpgBuffer,(contentSize+FILE_NAME_LENGTH*2)*sizeof(char));
jpgBufferPointer=jpgBuffer;
}
jpgBufferPointer+=num_bytes_recv;
}
}
The server is saying it has sent all 43000 bytes, but client says it has received only 32768 bytes.
Appreciate any help! Thanks
You have a bug in the sending part, you should update newLength, because if you have 1 byte left to send from the file, it will send more, going out of the memory area where the content you want to send is stored. You should fix in this way:
bw = send(child_socket, send_ptr, newLength<(filesize-bytes_written)?newLength:(filesize-bytes_written), 0);
In this way the last send will have the correct size.
Also, use write instead of send if you are not using any flags.
You need to have the similar loop as you have on the writing side (bytes_written < filesize) on the reading side (i.e., while you can read more bytes, you should read them and append them).
The network doesn't guarantee that one read() call will return all available data.
The best way of writing client-server socket programming is to have a header before your data. The header should state the amount of data that it is going to transfer.
For example, To send data "Hello World", then send it as "0011+HELLO WORLD"
Here 11 stands for the size of the data the sender is planning to send now. The receiver on reading the first 4 bytes can understand that he should be ready to read next 11 bytes of data from the sender.
So reader will do two read:
hRead = 5 /* With 5 you are saying it can read upto max of 9999 bytes from data".
read(sd, buff, hRead);
dRead = atoi(buff);
readn(sd, buff, dRead);
For Example : Server
size_t sendn(int fd, const void *vptr, size_t n) {
size_t nleft;
size_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nwritten = send(fd, vptr, nleft, 0)) <= 0) {
if (errno == EINTR)
nwritten = 0;
else {
fprintf(stderr, "send failed %d - %s\n", fd, strerror(errno));
return (-1);
}
}
nleft -= nwritten;
ptr += nwritten;
}
return (n);
}
To send message:
sprintf(buff, "%d + %d + %s\r\n", MSG_LOGIN, strlen("Hello World"), Hello World);
sendn(sd, buff, strlen(buff));
Client:
size_t readn(int fd, void *vptr, size_t n) {
size_t nleft;
size_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ((nread = recv(fd, ptr, nleft, 0)) < 0) {
if (errno == EINTR)
nread = 0;
else {
fprintf(stderr, "read failed %d - %s\n", fd, strerror(errno));
return (-1);
}
} else if (nread == 0)
break;
nleft -= nread;
ptr += nread;
}
return (n - nleft);
}